summaryrefslogtreecommitdiff
path: root/chromium/content
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content')
-rw-r--r--chromium/content/BUILD.gn3
-rw-r--r--chromium/content/DEPS16
-rw-r--r--chromium/content/OWNERS1
-rw-r--r--chromium/content/app/BUILD.gn4
-rw-r--r--chromium/content/app/DEPS1
-rw-r--r--chromium/content/app/android/child_process_service_impl.cc (renamed from chromium/content/app/android/child_process_service.cc)78
-rw-r--r--chromium/content/app/android/child_process_service_impl.h (renamed from chromium/content/app/android/child_process_service.h)8
-rw-r--r--chromium/content/app/android/library_loader_hooks.cc10
-rw-r--r--chromium/content/app/content_main_runner.cc8
-rw-r--r--chromium/content/app/mac/mac_init.mm11
-rw-r--r--chromium/content/app/strings/translations/content_strings_hi.xtb4
-rw-r--r--chromium/content/browser/BUILD.gn63
-rw-r--r--chromium/content/browser/DEPS35
-rw-r--r--chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc26
-rw-r--r--chromium/content/browser/accessibility/accessibility_mode_browsertest.cc8
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc1
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.cc6
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc40
-rw-r--r--chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm214
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc179
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h21
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc5
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.h1
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm38
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc20
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.h1
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.cc294
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.h30
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc553
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc4
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc10
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc64
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc13
-rw-r--r--chromium/content/browser/accessibility/hit_testing_browsertest.cc44
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc3
-rw-r--r--chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc58
-rw-r--r--chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc124
-rw-r--r--chromium/content/browser/android/browser_surface_texture_manager.cc9
-rw-r--r--chromium/content/browser/android/browser_surface_texture_manager.h2
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.cc17
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.h8
-rw-r--r--chromium/content/browser/android/content_video_view.cc2
-rw-r--r--chromium/content/browser/android/content_video_view.h2
-rw-r--r--chromium/content/browser/android/content_view_core_impl.cc26
-rw-r--r--chromium/content/browser/android/content_view_core_impl.h3
-rw-r--r--chromium/content/browser/android/deferred_download_observer.cc32
-rw-r--r--chromium/content/browser/android/deferred_download_observer.h42
-rw-r--r--chromium/content/browser/android/download_controller_android_impl.cc635
-rw-r--r--chromium/content/browser/android/download_controller_android_impl.h159
-rw-r--r--chromium/content/browser/android/java/gin_java_method_invocation_helper.cc40
-rw-r--r--chromium/content/browser/android/java/gin_java_method_invocation_helper.h6
-rw-r--r--chromium/content/browser/android/service_registry_android_impl.cc24
-rw-r--r--chromium/content/browser/android/service_registry_android_impl.h6
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.cc150
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.h20
-rw-r--r--chromium/content/browser/appcache/appcache_database.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_database_unittest.cc44
-rw-r--r--chromium/content/browser/appcache/appcache_group.cc1
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.cc13
-rw-r--r--chromium/content/browser/appcache/appcache_internals_ui.cc12
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler_unittest.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_response_unittest.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl_unittest.cc7
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_update_job_unittest.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job_unittest.cc4
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.cc58
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.h25
-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.h12
-rw-r--r--chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc16
-rw-r--r--chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc34
-rw-r--r--chromium/content/browser/blob_storage/blob_reader_unittest.cc9
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_adapter_factory_wrapper.cc146
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_adapter_factory_wrapper.h99
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc43
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h33
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc308
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blacklist.cc28
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blacklist.h12
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc210
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc478
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h148
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_dispatcher_host.cc779
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_dispatcher_host.h187
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_metrics.cc109
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_metrics.h58
-rw-r--r--chromium/content/browser/bluetooth/cache_query_result.h19
-rw-r--r--chromium/content/browser/bluetooth/first_device_bluetooth_chooser.cc49
-rw-r--r--chromium/content/browser/bluetooth/first_device_bluetooth_chooser.h39
-rw-r--r--chromium/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc10
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc350
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.h59
-rw-r--r--chromium/content/browser/bookmarklet_browsertest.cc2
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc61
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.h23
-rw-r--r--chromium/content/browser/browser_context.cc94
-rw-r--r--chromium/content/browser/browser_main_loop.cc117
-rw-r--r--chromium/content/browser/browser_main_loop.h15
-rw-r--r--chromium/content/browser/browser_main_runner.cc5
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc39
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h6
-rw-r--r--chromium/content/browser/browser_shutdown_profile_dumper.cc6
-rw-r--r--chromium/content/browser/browser_side_navigation_browsertest.cc55
-rw-r--r--chromium/content/browser/browser_thread_impl.cc34
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.cc270
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.h78
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.proto1
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.cc91
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.h34
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_handle.cc28
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_handle.h41
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc57
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc78
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h37
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc184
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_unittest.cc139
-rw-r--r--chromium/content/browser/cert_store_impl.cc32
-rw-r--r--chromium/content/browser/cert_store_impl.h27
-rw-r--r--chromium/content/browser/child_process_launcher.cc38
-rw-r--r--chromium/content/browser/child_process_launcher.h16
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc44
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.h4
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc27
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.cc29
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.h14
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc91
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h25
-rw-r--r--chromium/content/browser/compositor/gpu_output_surface_mac.h60
-rw-r--r--chromium/content/browser/compositor/gpu_output_surface_mac.mm139
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc211
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h8
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc45
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h16
-rw-r--r--chromium/content/browser/compositor/image_transport_factory.cc4
-rw-r--r--chromium/content/browser/compositor/image_transport_factory.h18
-rw-r--r--chromium/content/browser/compositor/image_transport_factory_browsertest.cc8
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc35
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h10
-rw-r--r--chromium/content/browser/compositor/owned_mailbox.cc5
-rw-r--r--chromium/content/browser/compositor/owned_mailbox.h3
-rw-r--r--chromium/content/browser/compositor/reflector_impl_unittest.cc19
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.cc23
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.h9
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc38
-rw-r--r--chromium/content/browser/compositor/software_output_device_mac.h3
-rw-r--r--chromium/content/browser/compositor/software_output_device_mac.mm36
-rw-r--r--chromium/content/browser/compositor/surface_utils.cc2
-rw-r--r--chromium/content/browser/compositor/surface_utils.h1
-rw-r--r--chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc6
-rw-r--r--chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h2
-rw-r--r--chromium/content/browser/cross_site_transfer_browsertest.cc78
-rw-r--r--chromium/content/browser/database_browsertest.cc10
-rw-r--r--chromium/content/browser/databases_table_unittest.cc8
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory.h12
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc39
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc7
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc7
-rw-r--r--chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc23
-rw-r--r--chromium/content/browser/devtools/BUILD.gn6
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.cc5
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.h2
-rw-r--r--chromium/content/browser/devtools/devtools.gyp5
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc30
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.h11
-rw-r--r--chromium/content/browser/devtools/devtools_frame_trace_recorder.cc3
-rw-r--r--chromium/content/browser/devtools/devtools_manager_unittest.cc14
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.cc104
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.h56
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc43
-rwxr-xr-xchromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py2
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.cc4
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.cc10
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.h3
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc46
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h10
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.cc81
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.h4
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.cc2
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc2
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.cc42
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.h22
-rw-r--r--chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc2
-rw-r--r--chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc8
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_area.cc33
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_area.h6
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_area_unittest.cc23
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_browsertest.cc3
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.cc121
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.h25
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc46
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc17
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.h8
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database.cc7
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database_unittest.cc18
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_host.cc7
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.cc20
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.h18
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc4
-rw-r--r--chromium/content/browser/download/base_file.cc2
-rw-r--r--chromium/content/browser/download/docs/save-page-as.md26
-rw-r--r--chromium/content/browser/download/download_browsertest.cc59
-rw-r--r--chromium/content/browser/download/download_item_impl.cc34
-rw-r--r--chromium/content/browser/download/download_item_impl.h3
-rw-r--r--chromium/content/browser/download/download_item_impl_unittest.cc6
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc1
-rw-r--r--chromium/content/browser/download/download_request_core.cc26
-rw-r--r--chromium/content/browser/download/download_request_core.h7
-rw-r--r--chromium/content/browser/download/download_resource_handler.cc16
-rw-r--r--chromium/content/browser/download/download_stats.h13
-rw-r--r--chromium/content/browser/download/drag_download_file.cc5
-rw-r--r--chromium/content/browser/download/drag_download_file_browsertest.cc2
-rw-r--r--chromium/content/browser/download/mhtml_generation_browsertest.cc353
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.cc52
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.h8
-rw-r--r--chromium/content/browser/download/save_file_manager.cc36
-rw-r--r--chromium/content/browser/download/save_file_resource_handler.cc26
-rw-r--r--chromium/content/browser/download/save_file_resource_handler.h17
-rw-r--r--chromium/content/browser/download/save_item.cc37
-rw-r--r--chromium/content/browser/download/save_item.h30
-rw-r--r--chromium/content/browser/download/save_package.cc339
-rw-r--r--chromium/content/browser/download/save_package.h145
-rw-r--r--chromium/content/browser/download/save_package_unittest.cc88
-rw-r--r--chromium/content/browser/download/save_types.h8
-rw-r--r--chromium/content/browser/fileapi/file_system_browsertest.cc3
-rw-r--r--chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc4
-rw-r--r--chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc4
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc18
-rw-r--r--chromium/content/browser/find_request_manager.cc526
-rw-r--r--chromium/content/browser/find_request_manager.h197
-rw-r--r--chromium/content/browser/find_request_manager_browsertest.cc321
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc38
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h8
-rw-r--r--chromium/content/browser/frame_host/debug_urls.cc4
-rw-r--r--chromium/content/browser/frame_host/frame_mojo_shell.cc46
-rw-r--r--chromium/content/browser/frame_host/frame_mojo_shell.h22
-rw-r--r--chromium/content/browser/frame_host/frame_navigation_entry.cc17
-rw-r--r--chromium/content/browser/frame_host/frame_navigation_entry.h5
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc39
-rw-r--r--chromium/content/browser/frame_host/frame_tree_browsertest.cc41
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc41
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.h18
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node_blame_context.cc71
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node_blame_context.h39
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc263
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc20
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h11
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc10
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.cc11
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.h2
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc18
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h1
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc867
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc71
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc40
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h15
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc31
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc54
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.h38
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc11
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc2
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc109
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h6
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.cc6
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.h7
-rw-r--r--chromium/content/browser/frame_host/navigator.cc11
-rw-r--r--chromium/content/browser/frame_host/navigator.h34
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc73
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h28
-rw-r--r--chromium/content/browser/frame_host/navigator_impl_unittest.cc8
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h5
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc363
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h106
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc68
-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.cc394
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc90
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc82
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.h23
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc13
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc87
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame.h18
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc15
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc37
-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.cc15
-rw-r--r--chromium/content/browser/frame_host/traced_frame_tree_node.cc69
-rw-r--r--chromium/content/browser/frame_host/traced_frame_tree_node.h36
-rw-r--r--chromium/content/browser/gamepad/gamepad_consumer.h28
-rw-r--r--chromium/content/browser/gamepad/gamepad_data_fetcher.cc85
-rw-r--r--chromium/content/browser/gamepad/gamepad_data_fetcher.h61
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher.cc19
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h62
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.cc151
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.h41
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc274
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h51
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h106
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm575
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc352
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h97
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider.cc334
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider.h168
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider_unittest.cc162
-rw-r--r--chromium/content/browser/gamepad/gamepad_service.cc37
-rw-r--r--chromium/content/browser/gamepad/gamepad_service.h34
-rw-r--r--chromium/content/browser/gamepad/gamepad_service_test_helpers.cc22
-rw-r--r--chromium/content/browser/gamepad/gamepad_service_test_helpers.h38
-rw-r--r--chromium/content/browser/gamepad/gamepad_service_unittest.cc13
-rw-r--r--chromium/content/browser/gamepad/gamepad_shared_buffer_impl.cc46
-rw-r--r--chromium/content/browser/gamepad/gamepad_shared_buffer_impl.h35
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings.cc64
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings.h76
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc336
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm396
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc269
-rw-r--r--chromium/content/browser/gamepad/gamepad_test_helpers.cc64
-rw-r--r--chromium/content/browser/gamepad/gamepad_test_helpers.h91
-rw-r--r--chromium/content/browser/gamepad/raw_input_data_fetcher_win.cc532
-rw-r--r--chromium/content/browser/gamepad/raw_input_data_fetcher_win.h144
-rw-r--r--chromium/content/browser/gamepad/xbox_data_fetcher_mac.cc809
-rw-r--r--chromium/content/browser/gamepad/xbox_data_fetcher_mac.h190
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_impl.cc11
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_impl.h4
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.cc4
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.h6
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.cc87
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.h31
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc183
-rw-r--r--chromium/content/browser/geolocation/mock_location_provider.cc27
-rw-r--r--chromium/content/browser/geolocation/mock_location_provider.h15
-rw-r--r--chromium/content/browser/geolocation/network_location_provider_unittest.cc5
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc10
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc93
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h23
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc8
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc75
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc17
-rw-r--r--chromium/content/browser/gpu/gpu_ipc_browsertests.cc5
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc107
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h21
-rw-r--r--chromium/content/browser/gpu/gpu_surface_tracker.cc2
-rw-r--r--chromium/content/browser/gpu/gpu_surface_tracker.h2
-rw-r--r--chromium/content/browser/iframe_zoom_browsertest.cc30
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc62
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc32
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_browsertest.cc19
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.cc35
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.h8
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc11
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc18
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.cc27
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_unittest.cc6
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.cc5
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc11
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h9
-rw-r--r--chromium/content/browser/leveldb_wrapper_impl.cc2
-rw-r--r--chromium/content/browser/loader/DEPS33
-rw-r--r--chromium/content/browser/loader/async_resource_handler.cc1
-rw-r--r--chromium/content/browser/loader/async_resource_handler_browsertest.cc12
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager_unittest.cc3
-rw-r--r--chromium/content/browser/loader/loader_delegate.h56
-rw-r--r--chromium/content/browser/loader/mime_type_resource_handler.cc5
-rw-r--r--chromium/content/browser/loader/mime_type_resource_handler.h2
-rw-r--r--chromium/content/browser/loader/mime_type_resource_handler_unittest.cc7
-rw-r--r--chromium/content/browser/loader/navigation_resource_throttle.cc38
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.cc6
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.h4
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_delegate.h3
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_factory.h2
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc13
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h14
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.cc53
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.h16
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc6
-rw-r--r--chromium/content/browser/loader/power_save_block_resource_throttle.cc17
-rw-r--r--chromium/content/browser/loader/power_save_block_resource_throttle.h18
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc260
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc250
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h51
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc97
-rw-r--r--chromium/content/browser/loader/resource_hints_impl.cc46
-rw-r--r--chromium/content/browser/loader/resource_loader.cc20
-rw-r--r--chromium/content/browser/loader/resource_loader_delegate.h5
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc37
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc72
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h17
-rw-r--r--chromium/content/browser/loader/resource_scheduler.cc134
-rw-r--r--chromium/content/browser/loader/resource_scheduler.h33
-rw-r--r--chromium/content/browser/loader/resource_scheduler_unittest.cc558
-rw-r--r--chromium/content/browser/loader/temporary_file_stream_unittest.cc2
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.cc40
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.h6
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder_unittest.cc13
-rw-r--r--chromium/content/browser/loader_delegate_impl.cc93
-rw-r--r--chromium/content/browser/loader_delegate_impl.h36
-rw-r--r--chromium/content/browser/mach_broker_mac_unittest.cc4
-rw-r--r--chromium/content/browser/manifest/manifest_browsertest.cc25
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.cc17
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.h4
-rw-r--r--chromium/content/browser/media/android/browser_surface_view_manager.cc6
-rw-r--r--chromium/content/browser/media/android/browser_surface_view_manager.h2
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager.cc91
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager.h60
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc371
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.cc12
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.h10
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura.cc9
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura.h4
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc4
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.cc107
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc21
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_unittest.cc145
-rw-r--r--chromium/content/browser/media/capture/image_capture_impl.cc111
-rw-r--r--chromium/content/browser/media/capture/image_capture_impl.h14
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.cc62
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.h14
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc108
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_muter.cc8
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc21
-rw-r--r--chromium/content/browser/media/capture/window_activity_tracker_mac.h1
-rw-r--r--chromium/content/browser/media/capture/window_activity_tracker_mac.mm2
-rw-r--r--chromium/content/browser/media/media_browsertest.cc16
-rw-r--r--chromium/content/browser/media/media_canplaytype_browsertest.cc102
-rw-r--r--chromium/content/browser/media/media_internals.cc13
-rw-r--r--chromium/content/browser/media/media_internals_proxy.cc10
-rw-r--r--chromium/content/browser/media/media_internals_proxy.h4
-rw-r--r--chromium/content/browser/media/media_redirect_browsertest.cc3
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc29
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.h15
-rw-r--r--chromium/content/browser/media/midi_browsertest.cc4
-rw-r--r--chromium/content/browser/media/session/media_session_controller_unittest.cc19
-rw-r--r--chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc5
-rw-r--r--chromium/content/browser/media/session/media_session_visibility_browsertest.cc40
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc4
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_canvas_capture_browsertest.cc35
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_capture_from_element_browsertest.cc77
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_datachannel_browsertest.cc19
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals.cc17
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals.h7
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals_browsertest.cc107
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_media_recorder_browsertest.cc46
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_webcam_browsertest.cc9
-rw-r--r--chromium/content/browser/memory/memory_pressure_controller_impl_browsertest.cc8
-rw-r--r--chromium/content/browser/message_port_provider_browsertest.cc3
-rw-r--r--chromium/content/browser/mime_registry_impl.cc35
-rw-r--r--chromium/content/browser/mime_registry_impl.h30
-rw-r--r--chromium/content/browser/mime_registry_message_filter.cc41
-rw-r--r--chromium/content/browser/mime_registry_message_filter.h32
-rw-r--r--chromium/content/browser/mojo/browser_shell_connection.cc79
-rw-r--r--chromium/content/browser/mojo/browser_shell_connection.h90
-rw-r--r--chromium/content/browser/mojo/constants.cc10
-rw-r--r--chromium/content/browser/mojo/constants.h2
-rw-r--r--chromium/content/browser/mojo/mojo_app_connection_impl.cc50
-rw-r--r--chromium/content/browser/mojo/mojo_app_connection_impl.h36
-rw-r--r--chromium/content/browser/mojo/mojo_application_host.cc59
-rw-r--r--chromium/content/browser/mojo/mojo_application_host.h63
-rw-r--r--chromium/content/browser/mojo/mojo_child_connection.cc23
-rw-r--r--chromium/content/browser/mojo/mojo_child_connection.h19
-rw-r--r--chromium/content/browser/mojo/mojo_shell_context.cc100
-rw-r--r--chromium/content/browser/mojo/mojo_shell_context.h3
-rw-r--r--chromium/content/browser/net/network_errors_listing_ui.cc8
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store_unittest.cc40
-rw-r--r--chromium/content/browser/net_info_browsertest.cc9
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.cc71
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.h53
-rw-r--r--chromium/content/browser/notifications/notification_database.cc3
-rw-r--r--chromium/content/browser/notifications/notification_database.h5
-rw-r--r--chromium/content/browser/notifications/notification_message_filter.cc10
-rw-r--r--chromium/content/browser/notifications/notification_message_filter.h3
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.cc37
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.h24
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.cc18
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.h13
-rw-r--r--chromium/content/browser/plugin_data_remover_impl.cc4
-rw-r--r--chromium/content/browser/plugin_private_storage_helper.cc415
-rw-r--r--chromium/content/browser/plugin_private_storage_helper.h37
-rw-r--r--chromium/content/browser/power_save_blocker_android.cc117
-rw-r--r--chromium/content/browser/power_save_blocker_android.h11
-rw-r--r--chromium/content/browser/power_save_blocker_chromeos.cc101
-rw-r--r--chromium/content/browser/power_save_blocker_impl.cc21
-rw-r--r--chromium/content/browser/power_save_blocker_impl.h60
-rw-r--r--chromium/content/browser/power_save_blocker_mac.cc115
-rw-r--r--chromium/content/browser/power_save_blocker_ozone.cc36
-rw-r--r--chromium/content/browser/power_save_blocker_win.cc153
-rw-r--r--chromium/content/browser/power_save_blocker_x11.cc493
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc44
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.h3
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.cc39
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.h43
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl_unittest.cc26
-rw-r--r--chromium/content/browser/quota/quota_database_unittest.cc12
-rw-r--r--chromium/content/browser/renderer_host/DEPS1
-rw-r--r--chromium/content/browser/renderer_host/OWNERS8
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.h222
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.mm422
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc207
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h7
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.cc79
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.h14
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.cc38
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.h8
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc8
-rw-r--r--chromium/content/browser/renderer_host/gamepad_browser_message_filter.h11
-rw-r--r--chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc11
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc79
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h2
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc13
-rw-r--r--chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc10
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc266
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h15
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc239
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_browsertest.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.cc12
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc89
-rw-r--r--chromium/content/browser/renderer_host/input/ui_touch_selection_helper.cc42
-rw-r--r--chromium/content/browser/renderer_host/input/ui_touch_selection_helper.h21
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm127
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_debug_writer.h1
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc20
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc19
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.cc52
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.h6
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc20
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc24
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h4
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc82
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h26
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc34
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.h3
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h3
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc55
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_client.cc33
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_client.h9
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc17
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc12
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h6
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h3
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc265
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h111
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc15
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc13
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc87
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h55
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc6
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h1
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc5
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc16
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h5
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc58
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc14
-rw-r--r--chromium/content/browser/renderer_host/pepper/ssl_context_helper.h10
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc113
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.h38
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc41
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc185
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h28
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_browsertest.cc6
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.h13
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate_view.h2
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc410
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h37
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc28
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.cc12
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h38
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc205
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h33
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc180
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.h27
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc47
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc222
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h33
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc414
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h63
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc924
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc54
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h59
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h115
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm397
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm14
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm134
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mus.cc25
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mus.h13
-rw-r--r--chromium/content/browser/renderer_host/sandbox_ipc_linux.cc5
-rw-r--r--chromium/content/browser/renderer_host/sandbox_ipc_linux.h3
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm2
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_message_filter.h5
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_message_filter.mm6
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.cc134
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.h120
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc13
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.h13
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.cc47
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc60
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aurawin.cc17
-rw-r--r--chromium/content/browser/renderer_host/websocket_blob_sender_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc110
-rw-r--r--chromium/content/browser/renderer_host/websocket_host.cc47
-rw-r--r--chromium/content/browser/renderer_host/websocket_host.h9
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper_unittest.cc4
-rw-r--r--chromium/content/browser/resource_context_impl.cc49
-rw-r--r--chromium/content/browser/resource_loading_browsertest.cc4
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc2
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc18
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc167
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h50
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc65
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.cc9
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_status.h19
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc153
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h31
-rw-r--r--chromium/content/browser/service_worker/foreign_fetch_request_handler.cc27
-rw-r--r--chromium/content/browser/service_worker/foreign_fetch_request_handler.h11
-rw-r--r--chromium/content/browser/service_worker/link_header_support.cc22
-rw-r--r--chromium/content/browser/service_worker/link_header_support_unittest.cc184
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc162
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.cc25
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_observer.h7
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc7
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc16
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.h9
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc4
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc72
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc75
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc195
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h21
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle_unittest.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_info.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_info.h6
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.cc48
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_unittest.cc157
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc216
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h36
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle.cc35
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle.h78
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc65
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle_core.h58
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.cc11
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.h18
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc25
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h11
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc61
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.h5
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc113
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h32
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc167
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.cc65
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.h27
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_response_info.cc8
-rw-r--r--chromium/content/browser/service_worker/service_worker_response_info.h7
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.cc85
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.h14
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc296
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc179
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h144
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc212
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc5
-rw-r--r--chromium/content/browser/session_history_browsertest.cc82
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.cc4
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc17
-rw-r--r--chromium/content/browser/shared_worker/worker_browsertest.cc2
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc3
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc1308
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc5
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_unittest.cc68
-rw-r--r--chromium/content/browser/ssl/ssl_policy.cc1
-rw-r--r--chromium/content/browser/storage_partition_impl.cc39
-rw-r--r--chromium/content/browser/storage_partition_impl.h8
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc320
-rw-r--r--chromium/content/browser/streams/stream_unittest.cc13
-rw-r--r--chromium/content/browser/streams/stream_url_request_job_unittest.cc5
-rw-r--r--chromium/content/browser/theme_helper_mac.mm19
-rw-r--r--chromium/content/browser/top_document_isolation_browsertest.cc6
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_impl.cc16
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_impl.h2
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_unittest.cc4
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.cc55
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.h7
-rw-r--r--chromium/content/browser/tracing/background_tracing_rule.cc2
-rw-r--r--chromium/content/browser/tracing/memory_tracing_browsertest.cc186
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.cc2
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc95
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.h16
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc33
-rw-r--r--chromium/content/browser/utility_process_host_impl.cc54
-rw-r--r--chromium/content/browser/utility_process_host_impl.h15
-rw-r--r--chromium/content/browser/utility_process_host_impl_browsertest.cc25
-rw-r--r--chromium/content/browser/utility_process_mojo_client_browsertest.cc143
-rw-r--r--chromium/content/browser/vibration_browsertest.cc10
-rw-r--r--chromium/content/browser/vr/OWNERS3
-rw-r--r--chromium/content/browser/vr/android/cardboard/cardboard_vr_device.cc167
-rw-r--r--chromium/content/browser/vr/android/cardboard/cardboard_vr_device.h38
-rw-r--r--chromium/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc29
-rw-r--r--chromium/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h33
-rw-r--r--chromium/content/browser/vr/vr_device.cc22
-rw-r--r--chromium/content/browser/vr/vr_device.h48
-rw-r--r--chromium/content/browser/vr/vr_device_manager.cc154
-rw-r--r--chromium/content/browser/vr/vr_device_manager.h81
-rw-r--r--chromium/content/browser/vr/vr_device_manager_unittest.cc100
-rw-r--r--chromium/content/browser/vr/vr_device_provider.h27
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_context.cc26
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_context.h15
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc15
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h2
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc35
-rw-r--r--chromium/content/browser/web_contents/opened_by_dom_browsertest.cc3
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc50
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h17
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc344
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h80
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc184
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc90
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc35
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h12
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc17
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm3
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mus.cc4
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac.mm12
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.cc9
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc132
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend_unittest.cc3
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.cc6
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.h2
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_unittest.cc2
-rw-r--r--chromium/content/browser/webui/web_ui_impl.cc69
-rw-r--r--chromium/content/browser/webui/web_ui_impl.h44
-rw-r--r--chromium/content/browser/webui/web_ui_message_handler.cc20
-rw-r--r--chromium/content/browser/webui/web_ui_message_handler_unittest.cc26
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc24
-rw-r--r--chromium/content/browser/zygote_host/zygote_communication_linux.cc122
-rw-r--r--chromium/content/browser/zygote_host/zygote_communication_linux.h14
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.cc177
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.h22
-rw-r--r--chromium/content/child/BUILD.gn4
-rw-r--r--chromium/content/child/DEPS4
-rw-r--r--chromium/content/child/OWNERS9
-rw-r--r--chromium/content/child/assert_matching_enums.cc10
-rw-r--r--chromium/content/child/background_sync/background_sync_provider.cc8
-rw-r--r--chromium/content/child/background_sync/background_sync_provider.h4
-rw-r--r--chromium/content/child/blink_platform_impl.cc15
-rw-r--r--chromium/content/child/blink_platform_impl.h2
-rw-r--r--chromium/content/child/blob_storage/blob_consolidation.cc43
-rw-r--r--chromium/content/child/blob_storage/blob_consolidation.h38
-rw-r--r--chromium/content/child/blob_storage/blob_consolidation_unittest.cc100
-rw-r--r--chromium/content/child/blob_storage/blob_message_filter.cc16
-rw-r--r--chromium/content/child/blob_storage/blob_message_filter.h11
-rw-r--r--chromium/content/child/blob_storage/blob_transport_controller.cc353
-rw-r--r--chromium/content/child/blob_storage/blob_transport_controller.h61
-rw-r--r--chromium/content/child/blob_storage/blob_transport_controller_unittest.cc295
-rw-r--r--chromium/content/child/blob_storage/webblobregistry_impl.h2
-rw-r--r--chromium/content/child/child_discardable_shared_memory_manager.cc20
-rw-r--r--chromium/content/child/child_process.cc3
-rw-r--r--chromium/content/child/child_thread_impl.cc87
-rw-r--r--chromium/content/child/child_thread_impl.h36
-rw-r--r--chromium/content/child/child_thread_impl_browsertest.cc2
-rw-r--r--chromium/content/child/database_util.cc7
-rw-r--r--chromium/content/child/database_util.h2
-rw-r--r--chromium/content/child/db_message_filter.cc40
-rw-r--r--chromium/content/child/db_message_filter.h12
-rw-r--r--chromium/content/child/dwrite_font_proxy/font_fallback_win_unittest.cc30
-rw-r--r--chromium/content/child/fileapi/OWNERS13
-rw-r--r--chromium/content/child/fileapi/webfilesystem_impl.cc184
-rw-r--r--chromium/content/child/fileapi/webfilewriter_impl.cc7
-rw-r--r--chromium/content/child/font_warmup_win.cc26
-rw-r--r--chromium/content/child/font_warmup_win_unittest.cc2
-rw-r--r--chromium/content/child/indexed_db/OWNERS13
-rw-r--r--chromium/content/child/mojo/mojo_application.cc38
-rw-r--r--chromium/content/child/mojo/mojo_application.h38
-rw-r--r--chromium/content/child/notifications/notification_manager.cc14
-rw-r--r--chromium/content/child/notifications/notification_manager.h2
-rw-r--r--chromium/content/child/permissions/permission_dispatcher.cc16
-rw-r--r--chromium/content/child/permissions/permission_dispatcher.h14
-rw-r--r--chromium/content/child/request_extra_data.cc3
-rw-r--r--chromium/content/child/request_extra_data.h15
-rw-r--r--chromium/content/child/request_info.cc5
-rw-r--r--chromium/content/child/request_info.h9
-rw-r--r--chromium/content/child/resource_dispatcher.cc10
-rw-r--r--chromium/content/child/resource_dispatcher.h8
-rw-r--r--chromium/content/child/resource_dispatcher_unittest.cc27
-rw-r--r--chromium/content/child/runtime_features.cc71
-rw-r--r--chromium/content/child/scoped_web_callbacks.h6
-rw-r--r--chromium/content/child/service_worker/service_worker_network_provider.cc65
-rw-r--r--chromium/content/child/service_worker/service_worker_network_provider.h10
-rw-r--r--chromium/content/child/shared_memory_data_consumer_handle_unittest.cc5
-rw-r--r--chromium/content/child/shared_memory_received_data_factory_unittest.cc6
-rw-r--r--chromium/content/child/site_isolation_stats_gatherer_browsertest.cc8
-rw-r--r--chromium/content/child/v8_value_converter_impl.cc93
-rw-r--r--chromium/content/child/v8_value_converter_impl.h27
-rw-r--r--chromium/content/child/v8_value_converter_impl_unittest.cc57
-rw-r--r--chromium/content/child/web_database_observer_impl.cc19
-rw-r--r--chromium/content/child/web_url_loader_impl.cc79
-rw-r--r--chromium/content/child/web_url_loader_impl.h2
-rw-r--r--chromium/content/child/web_url_loader_impl_unittest.cc36
-rw-r--r--chromium/content/child/web_url_request_util.cc68
-rw-r--r--chromium/content/child/web_url_request_util.h17
-rw-r--r--chromium/content/child/websocket_bridge.cc13
-rw-r--r--chromium/content/child/websocket_bridge.h2
-rw-r--r--chromium/content/child/websocket_dispatcher.cc36
-rw-r--r--chromium/content/child/websocket_dispatcher.h8
-rw-r--r--chromium/content/child/websocket_message_filter.cc36
-rw-r--r--chromium/content/child/websocket_message_filter.h50
-rw-r--r--chromium/content/common/BUILD.gn31
-rw-r--r--chromium/content/common/DEPS2
-rw-r--r--chromium/content/common/OWNERS64
-rw-r--r--chromium/content/common/all_messages.h2
-rw-r--r--chromium/content/common/android/OWNERS39
-rw-r--r--chromium/content/common/android/gin_java_bridge_value.cc11
-rw-r--r--chromium/content/common/android/gin_java_bridge_value.h2
-rw-r--r--chromium/content/common/android/resource_request_body_android.cc89
-rw-r--r--chromium/content/common/android/resource_request_body_android.h35
-rw-r--r--chromium/content/common/android/sync_compositor_messages.cc6
-rw-r--r--chromium/content/common/android/sync_compositor_messages.h45
-rw-r--r--chromium/content/common/application_setup.mojom13
-rw-r--r--chromium/content/common/ax_content_node_data.cc4
-rw-r--r--chromium/content/common/ax_content_node_data.h1
-rw-r--r--chromium/content/common/bluetooth/DEPS4
-rw-r--r--chromium/content/common/bluetooth/OWNERS16
-rw-r--r--chromium/content/common/bluetooth/PRESUBMIT.py14
-rw-r--r--chromium/content/common/bluetooth/bluetooth_device.cc37
-rw-r--r--chromium/content/common/bluetooth/bluetooth_device.h37
-rw-r--r--chromium/content/common/bluetooth/bluetooth_messages.h128
-rw-r--r--chromium/content/common/bluetooth/bluetooth_scan_filter.cc18
-rw-r--r--chromium/content/common/bluetooth/bluetooth_scan_filter.h30
-rw-r--r--chromium/content/common/browser_plugin/OWNERS12
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_messages.h1
-rw-r--r--chromium/content/common/cache_storage/OWNERS13
-rw-r--r--chromium/content/common/child_process_host_impl.cc28
-rw-r--r--chromium/content/common/child_process_host_impl.h5
-rw-r--r--chromium/content/common/content_message_generator.h3
-rw-r--r--chromium/content/common/content_switches_internal.cc29
-rw-r--r--chromium/content/common/content_switches_internal.h2
-rw-r--r--chromium/content/common/database_messages.h21
-rw-r--r--chromium/content/common/discardable_shared_memory_heap_unittest.cc3
-rw-r--r--chromium/content/common/dom_storage/OWNERS13
-rw-r--r--chromium/content/common/dom_storage/dom_storage_types.h3
-rw-r--r--chromium/content/common/drag_messages.h7
-rw-r--r--chromium/content/common/drag_traits.h9
-rw-r--r--chromium/content/common/dwrite_text_analysis_source_win.cc82
-rw-r--r--chromium/content/common/dwrite_text_analysis_source_win.h64
-rw-r--r--chromium/content/common/external_ipc_dumper.cc69
-rw-r--r--chromium/content/common/external_ipc_dumper.h17
-rw-r--r--chromium/content/common/fileapi/OWNERS12
-rw-r--r--chromium/content/common/font_config_ipc_linux.cc23
-rw-r--r--chromium/content/common/font_config_ipc_linux.h6
-rw-r--r--chromium/content/common/font_list_pango.cc9
-rw-r--r--chromium/content/common/frame.mojom23
-rw-r--r--chromium/content/common/frame_messages.h178
-rw-r--r--chromium/content/common/frame_replication_state.cc7
-rw-r--r--chromium/content/common/frame_replication_state.h11
-rw-r--r--chromium/content/common/gamepad_user_gesture.cc43
-rw-r--r--chromium/content/common/gamepad_user_gesture.h20
-rw-r--r--chromium/content/common/gpu/OWNERS12
-rw-r--r--chromium/content/common/gpu/client/command_buffer_metrics.cc1
-rw-r--r--chromium/content/common/gpu/client/context_provider_command_buffer.cc17
-rw-r--r--chromium/content/common/gpu/client/context_provider_command_buffer.h5
-rw-r--r--chromium/content/common/gpu_host_messages.h18
-rw-r--r--chromium/content/common/host_discardable_shared_memory_manager.cc10
-rw-r--r--chromium/content/common/image_downloader/OWNERS2
-rw-r--r--chromium/content/common/image_downloader/image_downloader.mojom7
-rw-r--r--chromium/content/common/indexed_db/OWNERS12
-rw-r--r--chromium/content/common/input/input_event_utils.cc17
-rw-r--r--chromium/content/common/input/input_event_utils.h17
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders.cc7
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders.h2
-rw-r--r--chromium/content/common/input/web_input_event_traits.cc41
-rw-r--r--chromium/content/common/input/web_input_event_traits.h2
-rw-r--r--chromium/content/common/input/web_input_event_traits_unittest.cc26
-rw-r--r--chromium/content/common/input_messages.h7
-rw-r--r--chromium/content/common/mac/font_loader.mm36
-rw-r--r--chromium/content/common/media/OWNERS25
-rw-r--r--chromium/content/common/media/media_stream_options.cc8
-rw-r--r--chromium/content/common/media/media_stream_options.h17
-rw-r--r--chromium/content/common/media/video_capture_messages.h2
-rw-r--r--chromium/content/common/mime_registry_messages.h19
-rw-r--r--chromium/content/common/mojo/OWNERS24
-rw-r--r--chromium/content/common/mojo/embedded_application_runner.cc12
-rw-r--r--chromium/content/common/mojo/mojo_shell_connection_impl.cc204
-rw-r--r--chromium/content/common/mojo/mojo_shell_connection_impl.h77
-rw-r--r--chromium/content/common/mojo/service_registry_impl.cc113
-rw-r--r--chromium/content/common/mojo/service_registry_impl.h70
-rw-r--r--chromium/content/common/navigation_params.cc24
-rw-r--r--chromium/content/common/navigation_params.h58
-rw-r--r--chromium/content/common/navigation_params_unittest.cc28
-rw-r--r--chromium/content/common/net/url_request_user_data.h2
-rw-r--r--chromium/content/common/origin_trials/trial_token_validator.cc13
-rw-r--r--chromium/content/common/origin_trials/trial_token_validator_unittest.cc55
-rw-r--r--chromium/content/common/page_messages.h6
-rw-r--r--chromium/content/common/page_state_serialization.cc239
-rw-r--r--chromium/content/common/page_state_serialization.h39
-rw-r--r--chromium/content/common/page_state_serialization_unittest.cc89
-rw-r--r--chromium/content/common/pepper_messages.h28
-rw-r--r--chromium/content/common/platform_notification_messages.h7
-rw-r--r--chromium/content/common/plugin_list.cc2
-rw-r--r--chromium/content/common/plugin_list.h4
-rw-r--r--chromium/content/common/render_frame_setup.mojom14
-rw-r--r--chromium/content/common/render_process_messages.h4
-rw-r--r--chromium/content/common/resource_messages.cc18
-rw-r--r--chromium/content/common/resource_messages.h15
-rw-r--r--chromium/content/common/resource_request.h13
-rw-r--r--chromium/content/common/resource_request_body_impl.cc (renamed from chromium/content/common/resource_request_body.cc)31
-rw-r--r--chromium/content/common/resource_request_body_impl.h (renamed from chromium/content/common/resource_request_body.h)22
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc2
-rw-r--r--chromium/content/common/sandbox_mac.mm9
-rw-r--r--chromium/content/common/service_worker/OWNERS18
-rw-r--r--chromium/content/common/service_worker/service_worker_messages.h31
-rw-r--r--chromium/content/common/service_worker/service_worker_types.cc6
-rw-r--r--chromium/content/common/service_worker/service_worker_types.h46
-rw-r--r--chromium/content/common/ssl_status_serialization.cc4
-rw-r--r--chromium/content/common/view_messages.h72
-rw-r--r--chromium/content/common/websocket_messages.h16
-rw-r--r--chromium/content/content.gyp39
-rw-r--r--chromium/content/content_app.gypi4
-rw-r--r--chromium/content/content_browser.gypi123
-rw-r--r--chromium/content/content_child.gypi4
-rw-r--r--chromium/content/content_common.gypi40
-rw-r--r--chromium/content/content_common_mojo_bindings.gyp9
-rw-r--r--chromium/content/content_jni.gypi6
-rw-r--r--chromium/content/content_renderer.gypi57
-rw-r--r--chromium/content/content_resources.grd32
-rw-r--r--chromium/content/content_resources.gypi2
-rw-r--r--chromium/content/content_shell.gypi9
-rw-r--r--chromium/content/content_tests.gypi40
-rw-r--r--chromium/content/content_utility.gypi2
-rw-r--r--chromium/content/gpu/gpu_child_thread.cc67
-rw-r--r--chromium/content/gpu/gpu_child_thread.h18
-rw-r--r--chromium/content/gpu/gpu_main.cc15
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.cc49
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.h10
-rw-r--r--chromium/content/ppapi_plugin/BUILD.gn10
-rw-r--r--chromium/content/public/android/BUILD.gn32
-rw-r--r--chromium/content/public/app/BUILD.gn12
-rw-r--r--chromium/content/public/app/mojo/content_browser_manifest.json7
-rw-r--r--chromium/content/public/app/mojo/content_gpu_manifest.json10
-rw-r--r--chromium/content/public/app/mojo/content_renderer_manifest.json8
-rw-r--r--chromium/content/public/app/mojo/content_utility_manifest.json10
-rw-r--r--chromium/content/public/browser/BUILD.gn3
-rw-r--r--chromium/content/public/browser/android/download_controller_android.cc13
-rw-r--r--chromium/content/public/browser/android/download_controller_android.h1
-rw-r--r--chromium/content/public/browser/android/service_registry_android.h10
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor.h5
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor_client.h26
-rw-r--r--chromium/content/public/browser/browser_child_process_host.h24
-rw-r--r--chromium/content/public/browser/browser_child_process_host_delegate.cc8
-rw-r--r--chromium/content/public/browser/browser_child_process_host_delegate.h16
-rw-r--r--chromium/content/public/browser/browser_context.h17
-rw-r--r--chromium/content/public/browser/browser_thread.h2
-rw-r--r--chromium/content/public/browser/content_browser_client.cc22
-rw-r--r--chromium/content/public/browser/content_browser_client.h58
-rw-r--r--chromium/content/public/browser/devtools_agent_host.h20
-rw-r--r--chromium/content/public/browser/download_manager_delegate.h12
-rw-r--r--chromium/content/public/browser/download_url_parameters.cc11
-rw-r--r--chromium/content/public/browser/download_url_parameters.h43
-rw-r--r--chromium/content/public/browser/geolocation_delegate.cc21
-rw-r--r--chromium/content/public/browser/geolocation_delegate.h38
-rw-r--r--chromium/content/public/browser/gpu_service_registry.cc4
-rw-r--r--chromium/content/public/browser/gpu_service_registry.h16
-rw-r--r--chromium/content/public/browser/gpu_utils.cc4
-rw-r--r--chromium/content/public/browser/media_device_id.cc15
-rw-r--r--chromium/content/public/browser/media_device_id.h15
-rw-r--r--chromium/content/public/browser/mojo_app_connection.h51
-rw-r--r--chromium/content/public/browser/native_web_keyboard_event.h7
-rw-r--r--chromium/content/public/browser/navigation_controller.cc6
-rw-r--r--chromium/content/public/browser/navigation_controller.h18
-rw-r--r--chromium/content/public/browser/navigation_entry.h14
-rw-r--r--chromium/content/public/browser/navigation_handle.h20
-rw-r--r--chromium/content/public/browser/navigation_throttle.h6
-rw-r--r--chromium/content/public/browser/page_navigator.h7
-rw-r--r--chromium/content/public/browser/pepper_vpn_provider_resource_host_proxy.h28
-rw-r--r--chromium/content/public/browser/power_save_blocker.h59
-rw-r--r--chromium/content/public/browser/render_frame_host.h37
-rw-r--r--chromium/content/public/browser/render_process_host.h12
-rw-r--r--chromium/content/public/browser/render_view_host.h30
-rw-r--r--chromium/content/public/browser/render_widget_host.h7
-rw-r--r--chromium/content/public/browser/render_widget_host_view.h11
-rw-r--r--chromium/content/public/browser/resource_context.h38
-rw-r--r--chromium/content/public/browser/resource_dispatcher_host_delegate.cc10
-rw-r--r--chromium/content/public/browser/resource_dispatcher_host_delegate.h10
-rw-r--r--chromium/content/public/browser/resource_hints.h13
-rw-r--r--chromium/content/public/browser/resource_request_info.h6
-rw-r--r--chromium/content/public/browser/screen_orientation_provider.cc2
-rw-r--r--chromium/content/public/browser/security_style_explanations.cc3
-rw-r--r--chromium/content/public/browser/security_style_explanations.h3
-rw-r--r--chromium/content/public/browser/site_instance.h21
-rw-r--r--chromium/content/public/browser/storage_partition.h1
-rw-r--r--chromium/content/public/browser/url_data_source.cc19
-rw-r--r--chromium/content/public/browser/url_data_source.h25
-rw-r--r--chromium/content/public/browser/utility_process_host.h21
-rw-r--r--chromium/content/public/browser/utility_process_mojo_client.h143
-rw-r--r--chromium/content/public/browser/vpn_service_proxy.h47
-rw-r--r--chromium/content/public/browser/web_contents.cc4
-rw-r--r--chromium/content/public/browser/web_contents.h28
-rw-r--r--chromium/content/public/browser/web_contents_delegate.h2
-rw-r--r--chromium/content/public/browser/web_contents_observer.h103
-rw-r--r--chromium/content/public/browser/web_ui.h37
-rw-r--r--chromium/content/public/browser/web_ui_data_source.h2
-rw-r--r--chromium/content/public/browser/web_ui_message_handler.h33
-rw-r--r--chromium/content/public/child/BUILD.gn5
-rw-r--r--chromium/content/public/child/child_thread.h19
-rw-r--r--chromium/content/public/child/v8_value_converter.h23
-rw-r--r--chromium/content/public/common/BUILD.gn3
-rw-r--r--chromium/content/public/common/OWNERS18
-rw-r--r--chromium/content/public/common/child_process_host.h4
-rw-r--r--chromium/content/public/common/common_param_traits_macros.h13
-rw-r--r--chromium/content/public/common/content_client.cc13
-rw-r--r--chromium/content/public/common/content_client.h15
-rw-r--r--chromium/content/public/common/content_descriptors.h4
-rw-r--r--chromium/content/public/common/content_features.cc48
-rw-r--r--chromium/content/public/common/content_features.h14
-rw-r--r--chromium/content/public/common/content_switches.cc50
-rw-r--r--chromium/content/public/common/content_switches.h23
-rw-r--r--chromium/content/public/common/drop_data.cc34
-rw-r--r--chromium/content/public/common/drop_data.h27
-rw-r--r--chromium/content/public/common/manifest.cc3
-rw-r--r--chromium/content/public/common/manifest.h3
-rw-r--r--chromium/content/public/common/mhtml_generation_params.cc18
-rw-r--r--chromium/content/public/common/mhtml_generation_params.h16
-rw-r--r--chromium/content/public/common/mojo_channel_switches.cc2
-rw-r--r--chromium/content/public/common/mojo_shell_connection.h103
-rw-r--r--chromium/content/public/common/origin_trial_policy.h24
-rw-r--r--chromium/content/public/common/page_state.cc23
-rw-r--r--chromium/content/public/common/resource_request_body.cc43
-rw-r--r--chromium/content/public/common/resource_request_body.h69
-rw-r--r--chromium/content/public/common/resource_response.cc1
-rw-r--r--chromium/content/public/common/resource_response_info.h4
-rw-r--r--chromium/content/public/common/service_registry.h99
-rw-r--r--chromium/content/public/common/ssl_status.cc6
-rw-r--r--chromium/content/public/common/ssl_status.h5
-rw-r--r--chromium/content/public/common/web_preferences.cc16
-rw-r--r--chromium/content/public/common/web_preferences.h15
-rw-r--r--chromium/content/public/gpu/content_gpu_client.h19
-rw-r--r--chromium/content/public/gpu/gpu_video_decode_accelerator_factory.cc3
-rw-r--r--chromium/content/public/gpu/gpu_video_decode_accelerator_factory.h7
-rw-r--r--chromium/content/public/renderer/content_renderer_client.h11
-rw-r--r--chromium/content/public/renderer/media_stream_renderer_factory.h6
-rw-r--r--chromium/content/public/renderer/media_stream_video_renderer.h (renamed from chromium/content/public/renderer/video_frame_provider.h)20
-rw-r--r--chromium/content/public/renderer/pepper_plugin_instance.h1
-rw-r--r--chromium/content/public/renderer/render_accessibility.h35
-rw-r--r--chromium/content/public/renderer/render_frame.h25
-rw-r--r--chromium/content/public/renderer/render_frame_observer.cc4
-rw-r--r--chromium/content/public/renderer/render_frame_observer.h7
-rw-r--r--chromium/content/public/renderer/render_thread.h4
-rw-r--r--chromium/content/public/renderer/render_view.h4
-rw-r--r--chromium/content/public/renderer/render_view_observer.cc4
-rw-r--r--chromium/content/public/renderer/render_view_observer.h7
-rw-r--r--chromium/content/public/renderer/resource_fetcher.h3
-rw-r--r--chromium/content/public/utility/content_utility_client.h8
-rw-r--r--chromium/content/renderer/BUILD.gn30
-rw-r--r--chromium/content/renderer/DEPS5
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc34
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_enum_conversion.h2
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_tree_source.cc68
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_tree_source.h2
-rw-r--r--chromium/content/renderer/accessibility/render_accessibility_impl.cc (renamed from chromium/content/renderer/accessibility/renderer_accessibility.cc)126
-rw-r--r--chromium/content/renderer/accessibility/render_accessibility_impl.h (renamed from chromium/content/renderer/accessibility/renderer_accessibility.h)35
-rw-r--r--chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc (renamed from chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc)58
-rw-r--r--chromium/content/renderer/android/disambiguation_popup_helper.cc29
-rw-r--r--chromium/content/renderer/android/renderer_date_time_picker.cc4
-rw-r--r--chromium/content/renderer/android/renderer_date_time_picker.h1
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc79
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.h60
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_filter.cc81
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_filter.h22
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_output_surface.cc45
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_output_surface.h11
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_proxy.cc121
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_proxy.h49
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_registry.h7
-rw-r--r--chromium/content/renderer/background_sync/background_sync_client_impl.h2
-rw-r--r--chromium/content/renderer/bluetooth/bluetooth_dispatcher.cc145
-rw-r--r--chromium/content/renderer/bluetooth/bluetooth_dispatcher.h84
-rw-r--r--chromium/content/renderer/bluetooth/bluetooth_message_filter.cc37
-rw-r--r--chromium/content/renderer/bluetooth/bluetooth_message_filter.h31
-rw-r--r--chromium/content/renderer/bluetooth/bluetooth_type_converters.cc60
-rw-r--r--chromium/content/renderer/bluetooth/bluetooth_type_converters.h43
-rw-r--r--chromium/content/renderer/bluetooth/web_bluetooth_impl.cc98
-rw-r--r--chromium/content/renderer/bluetooth/web_bluetooth_impl.h33
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.cc2
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.h2
-rw-r--r--chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc12
-rw-r--r--chromium/content/renderer/categorized_worker_pool.cc (renamed from chromium/content/renderer/raster_worker_pool.cc)92
-rw-r--r--chromium/content/renderer/categorized_worker_pool.h (renamed from chromium/content/renderer/raster_worker_pool.h)34
-rw-r--r--chromium/content/renderer/categorized_worker_pool_unittest.cc122
-rw-r--r--chromium/content/renderer/child_frame_compositing_helper.cc12
-rw-r--r--chromium/content/renderer/child_frame_compositing_helper.h12
-rw-r--r--chromium/content/renderer/devtools/devtools_agent.cc9
-rw-r--r--chromium/content/renderer/devtools/devtools_agent.h1
-rw-r--r--chromium/content/renderer/devtools/devtools_agent_filter.cc12
-rw-r--r--chromium/content/renderer/devtools/devtools_client.cc4
-rw-r--r--chromium/content/renderer/devtools/devtools_client.h1
-rw-r--r--chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc2
-rw-r--r--chromium/content/renderer/devtools/v8_sampling_profiler.cc4
-rw-r--r--chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc11
-rw-r--r--chromium/content/renderer/dom_automation_controller.cc4
-rw-r--r--chromium/content/renderer/dom_serializer_browsertest.cc3
-rw-r--r--chromium/content/renderer/external_popup_menu.cc6
-rw-r--r--chromium/content/renderer/external_popup_menu.h6
-rw-r--r--chromium/content/renderer/external_popup_menu_browsertest.cc16
-rw-r--r--chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc2
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.cc3
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.h3
-rw-r--r--chromium/content/renderer/frame_blame_context.cc2
-rw-r--r--chromium/content/renderer/gamepad_shared_memory_reader.cc1
-rw-r--r--chromium/content/renderer/gpu/compositor_dependencies.h2
-rw-r--r--chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc46
-rw-r--r--chromium/content/renderer/gpu/compositor_external_begin_frame_source.h13
-rw-r--r--chromium/content/renderer/gpu/compositor_forwarding_message_filter.cc1
-rw-r--r--chromium/content/renderer/gpu/compositor_output_surface.cc133
-rw-r--r--chromium/content/renderer/gpu/compositor_output_surface.h40
-rw-r--r--chromium/content/renderer/gpu/delegated_compositor_output_surface.cc28
-rw-r--r--chromium/content/renderer/gpu/delegated_compositor_output_surface.h31
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.cc4
-rw-r--r--chromium/content/renderer/gpu/mailbox_output_surface.cc239
-rw-r--r--chromium/content/renderer/gpu/mailbox_output_surface.h80
-rw-r--r--chromium/content/renderer/gpu/queue_message_swap_promise.cc17
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.cc431
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.h25
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor_delegate.h6
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor_unittest.cc292
-rw-r--r--chromium/content/renderer/history_controller.cc33
-rw-r--r--chromium/content/renderer/history_controller.h10
-rw-r--r--chromium/content/renderer/history_entry.cc6
-rw-r--r--chromium/content/renderer/history_serialization.cc75
-rw-r--r--chromium/content/renderer/idle_user_detector.cc4
-rw-r--r--chromium/content/renderer/idle_user_detector.h1
-rw-r--r--chromium/content/renderer/image_downloader/image_downloader_impl.cc22
-rw-r--r--chromium/content/renderer/image_downloader/image_downloader_impl.h5
-rw-r--r--chromium/content/renderer/input/input_event_filter.cc7
-rw-r--r--chromium/content/renderer/input/input_event_filter_unittest.cc58
-rw-r--r--chromium/content/renderer/input/input_handler_manager.cc43
-rw-r--r--chromium/content/renderer/input/input_handler_manager.h11
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.cc5
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.h3
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler.cc20
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler_delegate.h7
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_dispatcher.cc4
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_dispatcher.h3
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_value_converter.cc31
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_value_converter.h8
-rw-r--r--chromium/content/renderer/layout_test_dependencies.h38
-rw-r--r--chromium/content/renderer/manifest/manifest_manager.cc4
-rw-r--r--chromium/content/renderer/manifest/manifest_manager.h3
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.cc109
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.h6
-rw-r--r--chromium/content/renderer/manifest/manifest_parser_unittest.cc166
-rw-r--r--chromium/content/renderer/media/DEPS2
-rw-r--r--chromium/content/renderer/media/android/media_info_loader_unittest.cc5
-rw-r--r--chromium/content/renderer/media/android/renderer_media_player_manager.cc4
-rw-r--r--chromium/content/renderer/media/android/renderer_media_player_manager.h3
-rw-r--r--chromium/content/renderer/media/android/renderer_media_session_manager.cc4
-rw-r--r--chromium/content/renderer/media/android/renderer_media_session_manager.h3
-rw-r--r--chromium/content/renderer/media/android/renderer_surface_view_manager.cc11
-rw-r--r--chromium/content/renderer/media/android/renderer_surface_view_manager.h3
-rw-r--r--chromium/content/renderer/media/android/webmediaplayer_android.cc16
-rw-r--r--chromium/content/renderer/media/audio_device_factory.cc51
-rw-r--r--chromium/content/renderer/media/audio_device_factory.h12
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager.cc216
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager.h83
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc604
-rw-r--r--chromium/content/renderer/media/audio_renderer_sink_cache.h62
-rw-r--r--chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc253
-rw-r--r--chromium/content/renderer/media/audio_renderer_sink_cache_impl.h110
-rw-r--r--chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc374
-rw-r--r--chromium/content/renderer/media/audio_track_recorder.cc21
-rw-r--r--chromium/content/renderer/media/canvas_capture_handler.cc3
-rw-r--r--chromium/content/renderer/media/canvas_capture_handler.h4
-rw-r--r--chromium/content/renderer/media/canvas_capture_handler_unittest.cc2
-rw-r--r--chromium/content/renderer/media/cdm/renderer_cdm_manager.cc4
-rw-r--r--chromium/content/renderer/media/cdm/renderer_cdm_manager.h3
-rw-r--r--chromium/content/renderer/media/gpu/OWNERS2
-rw-r--r--chromium/content/renderer/media/gpu/rtc_video_decoder.cc (renamed from chromium/content/renderer/media/rtc_video_decoder.cc)41
-rw-r--r--chromium/content/renderer/media/gpu/rtc_video_decoder.h (renamed from chromium/content/renderer/media/rtc_video_decoder.h)13
-rw-r--r--chromium/content/renderer/media/gpu/rtc_video_decoder_factory.cc (renamed from chromium/content/renderer/media/rtc_video_decoder_factory.cc)4
-rw-r--r--chromium/content/renderer/media/gpu/rtc_video_decoder_factory.h (renamed from chromium/content/renderer/media/rtc_video_decoder_factory.h)6
-rw-r--r--chromium/content/renderer/media/gpu/rtc_video_decoder_unittest.cc (renamed from chromium/content/renderer/media/rtc_video_decoder_unittest.cc)20
-rw-r--r--chromium/content/renderer/media/gpu/rtc_video_encoder.cc (renamed from chromium/content/renderer/media/rtc_video_encoder.cc)49
-rw-r--r--chromium/content/renderer/media/gpu/rtc_video_encoder.h (renamed from chromium/content/renderer/media/rtc_video_encoder.h)6
-rw-r--r--chromium/content/renderer/media/gpu/rtc_video_encoder_factory.cc (renamed from chromium/content/renderer/media/rtc_video_encoder_factory.cc)4
-rw-r--r--chromium/content/renderer/media/gpu/rtc_video_encoder_factory.h (renamed from chromium/content/renderer/media/rtc_video_encoder_factory.h)6
-rw-r--r--chromium/content/renderer/media/html_audio_element_capturer_source.cc90
-rw-r--r--chromium/content/renderer/media/html_audio_element_capturer_source.h63
-rw-r--r--chromium/content/renderer/media/html_audio_element_capturer_source_unittest.cc154
-rw-r--r--chromium/content/renderer/media/html_video_element_capturer_source.cc30
-rw-r--r--chromium/content/renderer/media/html_video_element_capturer_source.h7
-rw-r--r--chromium/content/renderer/media/image_capture_frame_grabber.cc2
-rw-r--r--chromium/content/renderer/media/media_interface_provider.cc3
-rw-r--r--chromium/content/renderer/media/media_permission_dispatcher.cc2
-rw-r--r--chromium/content/renderer/media/media_recorder_handler.cc7
-rw-r--r--chromium/content/renderer/media/media_stream_audio_deliverer.h2
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor.cc33
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor.h18
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_options.cc86
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_options.h31
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_unittest.cc47
-rw-r--r--chromium/content/renderer/media/media_stream_audio_source.cc2
-rw-r--r--chromium/content/renderer/media/media_stream_audio_track.cc8
-rw-r--r--chromium/content/renderer/media/media_stream_audio_track.h2
-rw-r--r--chromium/content/renderer/media/media_stream_audio_unittest.cc7
-rw-r--r--chromium/content/renderer/media/media_stream_center.cc13
-rw-r--r--chromium/content/renderer/media/media_stream_renderer_factory_impl.cc8
-rw-r--r--chromium/content/renderer/media/media_stream_renderer_factory_impl.h4
-rw-r--r--chromium/content/renderer/media/media_stream_source.cc14
-rw-r--r--chromium/content/renderer/media/media_stream_source.h5
-rw-r--r--chromium/content/renderer/media/media_stream_track.cc2
-rw-r--r--chromium/content/renderer/media/media_stream_track.h5
-rw-r--r--chromium/content/renderer/media/media_stream_video_capturer_source.h3
-rw-r--r--chromium/content/renderer/media/media_stream_video_renderer_sink.cc2
-rw-r--r--chromium/content/renderer/media/media_stream_video_renderer_sink.h23
-rw-r--r--chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc2
-rw-r--r--chromium/content/renderer/media/media_stream_video_source.cc30
-rw-r--r--chromium/content/renderer/media/media_stream_video_source.h14
-rw-r--r--chromium/content/renderer/media/media_stream_video_source_unittest.cc22
-rw-r--r--chromium/content/renderer/media/media_stream_video_track.cc22
-rw-r--r--chromium/content/renderer/media/media_stream_video_track.h1
-rw-r--r--chromium/content/renderer/media/midi_dispatcher.cc14
-rw-r--r--chromium/content/renderer/media/midi_dispatcher.h3
-rw-r--r--chromium/content/renderer/media/mock_media_stream_registry.cc2
-rw-r--r--chromium/content/renderer/media/peer_connection_identity_store.h2
-rw-r--r--chromium/content/renderer/media/pepper_to_video_track_adapter.cc2
-rw-r--r--chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc2
-rw-r--r--chromium/content/renderer/media/remote_media_stream_impl.cc2
-rw-r--r--chromium/content/renderer/media/render_media_log.cc18
-rw-r--r--chromium/content/renderer/media/render_media_log.h7
-rw-r--r--chromium/content/renderer/media/render_media_log_unittest.cc8
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.cc2
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc4
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.h1
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc40
-rw-r--r--chromium/content/renderer/media/rtc_certificate_generator.cc151
-rw-r--r--chromium/content/renderer/media/rtc_certificate_generator.h6
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler.cc39
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler.h2
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc50
-rw-r--r--chromium/content/renderer/media/speech_recognition_audio_sink.cc2
-rw-r--r--chromium/content/renderer/media/speech_recognition_audio_sink.h2
-rw-r--r--chromium/content/renderer/media/track_audio_renderer.cc4
-rw-r--r--chromium/content/renderer/media/track_audio_renderer.h2
-rw-r--r--chromium/content/renderer/media/user_media_client_impl.cc4
-rw-r--r--chromium/content/renderer/media/user_media_client_impl.h3
-rw-r--r--chromium/content/renderer/media/video_capture_impl.cc46
-rw-r--r--chromium/content/renderer/media/video_capture_impl.h20
-rw-r--r--chromium/content/renderer/media/video_capture_impl_unittest.cc14
-rw-r--r--chromium/content/renderer/media/video_capture_message_filter.h15
-rw-r--r--chromium/content/renderer/media/video_capture_message_filter_unittest.cc8
-rw-r--r--chromium/content/renderer/media/video_track_recorder.cc358
-rw-r--r--chromium/content/renderer/media/video_track_recorder.h2
-rw-r--r--chromium/content/renderer/media/video_track_recorder_unittest.cc2
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms.cc6
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms.h14
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms_unittest.cc80
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc37
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc10
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc47
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h3
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc4
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_sink.h1
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc35
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h8
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_impl.cc9
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_impl.h7
-rw-r--r--chromium/content/renderer/media/webrtc_audio_renderer.cc49
-rw-r--r--chromium/content/renderer/media/webrtc_audio_renderer.h8
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider.cc4
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider.h2
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc2
-rw-r--r--chromium/content/renderer/mojo/blink_service_registry_impl.cc23
-rw-r--r--chromium/content/renderer/mojo/blink_service_registry_impl.h21
-rw-r--r--chromium/content/renderer/mojo/interface_provider_js_wrapper.cc112
-rw-r--r--chromium/content/renderer/mojo/interface_provider_js_wrapper.h75
-rw-r--r--chromium/content/renderer/mojo/service_registry_js_wrapper.cc115
-rw-r--r--chromium/content/renderer/mojo/service_registry_js_wrapper.h72
-rw-r--r--chromium/content/renderer/mojo_bindings_controller.cc4
-rw-r--r--chromium/content/renderer/mojo_bindings_controller.h1
-rw-r--r--chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc45
-rw-r--r--chromium/content/renderer/mus/BUILD.gn4
-rw-r--r--chromium/content/renderer/mus/compositor_mus_connection.cc14
-rw-r--r--chromium/content/renderer/mus/compositor_mus_connection.h14
-rw-r--r--chromium/content/renderer/mus/compositor_mus_connection_unittest.cc20
-rw-r--r--chromium/content/renderer/mus/render_widget_mus_connection.cc22
-rw-r--r--chromium/content/renderer/mus/render_widget_mus_connection.h3
-rw-r--r--chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc13
-rw-r--r--chromium/content/renderer/notification_permission_dispatcher.cc11
-rw-r--r--chromium/content/renderer/notification_permission_dispatcher.h3
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager.cc42
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager.h12
-rw-r--r--chromium/content/renderer/p2p/port_allocator.cc21
-rw-r--r--chromium/content/renderer/p2p/port_allocator.h20
-rw-r--r--chromium/content/renderer/pepper/message_channel.cc9
-rw-r--r--chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc8
-rw-r--r--chromium/content/renderer/pepper/mock_renderer_ppapi_host.h1
-rw-r--r--chromium/content/renderer/pepper/pepper_audio_controller.cc77
-rw-r--r--chromium/content/renderer/pepper/pepper_audio_controller.h57
-rw-r--r--chromium/content/renderer/pepper/pepper_browser_connection.cc4
-rw-r--r--chromium/content/renderer/pepper/pepper_browser_connection.h3
-rw-r--r--chromium/content/renderer/pepper/pepper_compositor_host.cc4
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host.cc7
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc21
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.h1
-rw-r--r--chromium/content/renderer/pepper/pepper_media_device_manager.cc21
-rw-r--r--chromium/content/renderer/pepper/pepper_media_device_manager.h3
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_output.cc17
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_output.h5
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc147
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.h71
-rw-r--r--chromium/content/renderer/pepper/pepper_url_loader_host.cc4
-rw-r--r--chromium/content/renderer/pepper/pepper_video_decoder_host.cc6
-rw-r--r--chromium/content/renderer/pepper/pepper_video_decoder_host.h1
-rw-r--r--chromium/content/renderer/pepper/pepper_video_encoder_host.cc10
-rw-r--r--chromium/content/renderer/pepper/pepper_video_encoder_host.h3
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.cc18
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.h2
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper.cc12
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper.h1
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc4
-rw-r--r--chromium/content/renderer/pepper/ppb_audio_impl.cc26
-rw-r--r--chromium/content/renderer/pepper/ppb_audio_impl.h2
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc71
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.h21
-rw-r--r--chromium/content/renderer/pepper/ppb_video_decoder_impl.cc1
-rw-r--r--chromium/content/renderer/pepper/ppb_video_decoder_impl.h1
-rw-r--r--chromium/content/renderer/pepper/video_encoder_shim.cc3
-rw-r--r--chromium/content/renderer/presentation/presentation_dispatcher.cc10
-rw-r--r--chromium/content/renderer/presentation/presentation_dispatcher.h1
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc4
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_dispatcher.h3
-rw-r--r--chromium/content/renderer/raster_worker_pool_unittest.cc120
-rw-r--r--chromium/content/renderer/render_frame_impl.cc858
-rw-r--r--chromium/content/renderer/render_frame_impl.h123
-rw-r--r--chromium/content/renderer/render_frame_impl_browsertest.cc51
-rw-r--r--chromium/content/renderer/render_frame_proxy.cc29
-rw-r--r--chromium/content/renderer/render_frame_proxy.h8
-rw-r--r--chromium/content/renderer/render_thread_impl.cc361
-rw-r--r--chromium/content/renderer/render_thread_impl.h78
-rw-r--r--chromium/content/renderer/render_view_browsertest.cc119
-rw-r--r--chromium/content/renderer/render_view_impl.cc374
-rw-r--r--chromium/content/renderer/render_view_impl.h58
-rw-r--r--chromium/content/renderer/render_view_mouse_lock_dispatcher.h40
-rw-r--r--chromium/content/renderer/render_widget.cc208
-rw-r--r--chromium/content/renderer/render_widget.h30
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.cc3
-rw-r--r--chromium/content/renderer/render_widget_mouse_lock_dispatcher.cc (renamed from chromium/content/renderer/render_view_mouse_lock_dispatcher.cc)35
-rw-r--r--chromium/content/renderer/render_widget_mouse_lock_dispatcher.h42
-rw-r--r--chromium/content/renderer/render_widget_unittest.cc13
-rw-r--r--chromium/content/renderer/renderer.sb12
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.cc92
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.h14
-rw-r--r--chromium/content/renderer/renderer_main.cc6
-rw-r--r--chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc4
-rw-r--r--chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h1
-rw-r--r--chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc5
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.cc74
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.h24
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_util.cc10
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_util.h4
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc13
-rw-r--r--chromium/content/renderer/shared_worker_repository.cc4
-rw-r--r--chromium/content/renderer/shared_worker_repository.h3
-rw-r--r--chromium/content/renderer/speech_recognition_dispatcher.cc4
-rw-r--r--chromium/content/renderer/speech_recognition_dispatcher.h1
-rw-r--r--chromium/content/renderer/stats_collection_observer.cc4
-rw-r--r--chromium/content/renderer/stats_collection_observer.h3
-rw-r--r--chromium/content/renderer/text_input_client_observer.cc4
-rw-r--r--chromium/content/renderer/text_input_client_observer.h3
-rw-r--r--chromium/content/renderer/visual_state_browsertest.cc3
-rw-r--r--chromium/content/renderer/web_ui_extension.cc11
-rw-r--r--chromium/content/renderer/web_ui_extension_data.cc4
-rw-r--r--chromium/content/renderer/web_ui_extension_data.h1
-rw-r--r--chromium/content/shell/common/shell_content_client.cc24
-rw-r--r--chromium/content/shell/common/shell_content_client.h8
-rw-r--r--chromium/content/shell/common/shell_origin_trial_policy.cc38
-rw-r--r--chromium/content/shell/common/shell_origin_trial_policy.h31
-rw-r--r--chromium/content/utility/BUILD.gn3
-rw-r--r--chromium/content/utility/utility_process_control_impl.h2
-rw-r--r--chromium/content/utility/utility_thread_impl.cc7
-rw-r--r--chromium/content/zygote/zygote_main_linux.cc3
1406 files changed, 35692 insertions, 30401 deletions
diff --git a/chromium/content/BUILD.gn b/chromium/content/BUILD.gn
index 2193f5455af..ba6346bb5ce 100644
--- a/chromium/content/BUILD.gn
+++ b/chromium/content/BUILD.gn
@@ -8,6 +8,7 @@ import("//build/config/nacl/config.gni")
# Applied by targets internal to content.
config("content_implementation") {
defines = [ "CONTENT_IMPLEMENTATION" ]
+ configs = [ "//build/config/compiler:wexit_time_destructors" ]
}
# When targets depend on, e.g. //content/public/browser, what happens? To
@@ -116,7 +117,9 @@ grit("resources") {
]
deps = [
"//content/public/app:browser_manifest",
+ "//content/public/app:gpu_manifest",
"//content/public/app:renderer_manifest",
+ "//content/public/app:utility_manifest",
"//services/catalog:manifest",
]
}
diff --git a/chromium/content/DEPS b/chromium/content/DEPS
index 3c3a18dc24c..7faf5b3418e 100644
--- a/chromium/content/DEPS
+++ b/chromium/content/DEPS
@@ -1,6 +1,5 @@
# Do NOT add chrome to the list below. We shouldn't be including files
-# from src/chrome in src/content. Also, we may only depend on files in
-# src/components that are shared with the mojo html_viewer.
+# from src/chrome in src/content.
include_rules = [
# The subdirectories in content/ will manually allow their own include
# directories in content/ so we disallow all of them.
@@ -12,7 +11,7 @@ include_rules = [
"+content/public/test",
"+content/test",
- "+blink",
+ "+blink/public/resources/grit",
"+cc",
"-cc/blink",
@@ -21,6 +20,16 @@ include_rules = [
"-cc/base/scoped_ptr_deque.h",
"-cc/base/scoped_ptr_vector.h",
+ "-components",
+ # Content can depend on components that are:
+ # 1) related to the implementation of the web platform
+ # 2) shared code between third_party/WebKit and content
+ # It should not depend on chrome features or implementation details, i.e. the
+ # original components/ directories which was code split out from chrome/ to be
+ # shared with iOS. This includes, but isn't limited to, browser features such
+ # as autofill or extensions, and chrome implementation details such as
+ # settings, packaging details, installation or crash reporting.
+
"+crypto",
"+grit/blink_resources.h",
"+grit/content_strings.h",
@@ -66,6 +75,7 @@ include_rules = [
"+third_party/sqlite",
"+third_party/khronos",
"+third_party/webrtc",
+ "+third_party/webrtc_overrides",
"+third_party/zlib/google",
"+third_party/WebKit/public/platform",
"+third_party/WebKit/public/web",
diff --git a/chromium/content/OWNERS b/chromium/content/OWNERS
index 2d7b39db9f0..f527939b057 100644
--- a/chromium/content/OWNERS
+++ b/chromium/content/OWNERS
@@ -1,4 +1,5 @@
avi@chromium.org
+clamy@chromium.org
creis@chromium.org
darin@chromium.org
jam@chromium.org
diff --git a/chromium/content/app/BUILD.gn b/chromium/content/app/BUILD.gn
index a7db1097360..b8a290162c8 100644
--- a/chromium/content/app/BUILD.gn
+++ b/chromium/content/app/BUILD.gn
@@ -8,8 +8,8 @@ import("//build/config/features.gni")
content_app_sources = [
"android/app_jni_registrar.cc",
"android/app_jni_registrar.h",
- "android/child_process_service.cc",
- "android/child_process_service.h",
+ "android/child_process_service_impl.cc",
+ "android/child_process_service_impl.h",
"android/content_jni_onload.cc",
"android/content_main.cc",
"android/content_main.h",
diff --git a/chromium/content/app/DEPS b/chromium/content/app/DEPS
index dc85fc197cd..961957d6826 100644
--- a/chromium/content/app/DEPS
+++ b/chromium/content/app/DEPS
@@ -3,6 +3,7 @@ include_rules = [
"+content",
"+device/battery",
"+device/bluetooth",
+ "+device/power_save_blocker",
"+device/usb",
"+device/vibration",
# For loading V8's initial snapshot from external files.
diff --git a/chromium/content/app/android/child_process_service.cc b/chromium/content/app/android/child_process_service_impl.cc
index e44974535dd..551efe94278 100644
--- a/chromium/content/app/android/child_process_service.cc
+++ b/chromium/content/app/android/child_process_service_impl.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/app/android/child_process_service.h"
+#include "content/app/android/child_process_service_impl.h"
#include <android/native_window_jni.h>
#include <cpu-features.h>
@@ -19,7 +19,7 @@
#include "gpu/ipc/common/android/surface_texture_peer.h"
#include "gpu/ipc/common/gpu_surface_lookup.h"
#include "ipc/ipc_descriptors.h"
-#include "jni/ChildProcessService_jni.h"
+#include "jni/ChildProcessServiceImpl_jni.h"
#include "ui/gl/android/scoped_java_surface.h"
using base::android::AttachCurrentThread;
@@ -36,11 +36,11 @@ class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
public gpu::SurfaceTexturePeer,
public gpu::GpuSurfaceLookup {
public:
- // |service| is the instance of
- // org.chromium.content.app.ChildProcessService.
+ // |service impl| is the instance of
+ // org.chromium.content.app.ChildProcessServiceImpl.
explicit SurfaceTextureManagerImpl(
- const base::android::JavaRef<jobject>& service)
- : service_(service) {
+ const base::android::JavaRef<jobject>& service_impl)
+ : service_impl_(service_impl) {
SurfaceTexturePeer::InitInstance(this);
gpu::GpuSurfaceLookup::InitInstance(this);
}
@@ -52,11 +52,11 @@ class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
// Overridden from SurfaceTextureManager:
void RegisterSurfaceTexture(int surface_texture_id,
int client_id,
- gfx::SurfaceTexture* surface_texture) override {
+ gl::SurfaceTexture* surface_texture) override {
JNIEnv* env = base::android::AttachCurrentThread();
- Java_ChildProcessService_createSurfaceTextureSurface(
+ Java_ChildProcessServiceImpl_createSurfaceTextureSurface(
env,
- service_.obj(),
+ service_impl_.obj(),
surface_texture_id,
client_id,
surface_texture->j_surface_texture().obj());
@@ -64,15 +64,15 @@ class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
void UnregisterSurfaceTexture(int surface_texture_id,
int client_id) override {
JNIEnv* env = base::android::AttachCurrentThread();
- Java_ChildProcessService_destroySurfaceTextureSurface(
- env, service_.obj(), surface_texture_id, client_id);
+ Java_ChildProcessServiceImpl_destroySurfaceTextureSurface(
+ env, service_impl_.obj(), surface_texture_id, client_id);
}
gfx::AcceleratedWidget AcquireNativeWidgetForSurfaceTexture(
int surface_texture_id) override {
JNIEnv* env = base::android::AttachCurrentThread();
- gfx::ScopedJavaSurface surface(
- Java_ChildProcessService_getSurfaceTextureSurface(env, service_.obj(),
- surface_texture_id));
+ gl::ScopedJavaSurface surface(
+ Java_ChildProcessServiceImpl_getSurfaceTextureSurface(
+ env, service_impl_.obj(), surface_texture_id));
if (surface.j_surface().is_null())
return NULL;
@@ -90,13 +90,13 @@ class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
// Overridden from SurfaceTexturePeer:
void EstablishSurfaceTexturePeer(
base::ProcessHandle pid,
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
+ scoped_refptr<gl::SurfaceTexture> surface_texture,
int primary_id,
int secondary_id) override {
JNIEnv* env = base::android::AttachCurrentThread();
- content::Java_ChildProcessService_establishSurfaceTexturePeer(
+ content::Java_ChildProcessServiceImpl_establishSurfaceTexturePeer(
env,
- service_.obj(),
+ service_impl_.obj(),
pid,
surface_texture->j_surface_texture().obj(),
primary_id,
@@ -106,9 +106,9 @@ class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
// Overridden from GpuSurfaceLookup:
gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) override {
JNIEnv* env = base::android::AttachCurrentThread();
- gfx::ScopedJavaSurface surface(
- content::Java_ChildProcessService_getViewSurface(
- env, service_.obj(), surface_id));
+ gl::ScopedJavaSurface surface(
+ content::Java_ChildProcessServiceImpl_getViewSurface(
+ env, service_impl_.obj(), surface_id));
if (surface.j_surface().is_null())
return NULL;
@@ -124,30 +124,30 @@ class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
}
// Overridden from GpuSurfaceLookup:
- gfx::ScopedJavaSurface AcquireJavaSurface(int surface_id) override {
+ gl::ScopedJavaSurface AcquireJavaSurface(int surface_id) override {
JNIEnv* env = base::android::AttachCurrentThread();
- return gfx::ScopedJavaSurface(
- content::Java_ChildProcessService_getViewSurface(env, service_.obj(),
- surface_id));
+ return gl::ScopedJavaSurface(
+ content::Java_ChildProcessServiceImpl_getViewSurface(
+ env, service_impl_.obj(), surface_id));
}
private:
- // The instance of org.chromium.content.app.ChildProcessService.
- base::android::ScopedJavaGlobalRef<jobject> service_;
+ // The instance of org.chromium.content.app.ChildProcessServiceImpl.
+ base::android::ScopedJavaGlobalRef<jobject> service_impl_;
DISALLOW_COPY_AND_ASSIGN(SurfaceTextureManagerImpl);
};
// Chrome actually uses the renderer code path for all of its child
// processes such as renderers, plugins, etc.
-void InternalInitChildProcess(JNIEnv* env,
- const JavaParamRef<jobject>& service,
- jint cpu_count,
- jlong cpu_features) {
+void InternalInitChildProcessImpl(JNIEnv* env,
+ const JavaParamRef<jobject>& service_impl,
+ jint cpu_count,
+ jlong cpu_features) {
// Set the CPU properties.
android_setCpu(cpu_count, cpu_features);
gpu::SurfaceTextureManager::SetInstance(
- new SurfaceTextureManagerImpl(service));
+ new SurfaceTextureManagerImpl(service_impl));
base::android::MemoryPressureListenerAndroid::RegisterSystemCallback(env);
}
@@ -164,21 +164,21 @@ void RegisterGlobalFileDescriptor(JNIEnv* env,
base::GlobalDescriptors::GetInstance()->Set(id, fd, region);
}
-void InitChildProcess(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jobject>& service,
- jint cpu_count,
- jlong cpu_features) {
- InternalInitChildProcess(env, service, cpu_count, cpu_features);
+void InitChildProcessImpl(JNIEnv* env,
+ const JavaParamRef<jclass>& clazz,
+ const JavaParamRef<jobject>& service_impl,
+ jint cpu_count,
+ jlong cpu_features) {
+ InternalInitChildProcessImpl(env, service_impl, cpu_count, cpu_features);
}
void ExitChildProcess(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
- VLOG(0) << "ChildProcessService: Exiting child process.";
+ VLOG(0) << "ChildProcessServiceImpl: Exiting child process.";
base::android::LibraryLoaderExitHook();
_exit(0);
}
-bool RegisterChildProcessService(JNIEnv* env) {
+bool RegisterChildProcessServiceImpl(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/chromium/content/app/android/child_process_service.h b/chromium/content/app/android/child_process_service_impl.h
index 5ba4b8ae598..d528445d12c 100644
--- a/chromium/content/app/android/child_process_service.h
+++ b/chromium/content/app/android/child_process_service_impl.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_APP_ANDROID_CHILD_PROCESS_SERVICE_H_
-#define CONTENT_APP_ANDROID_CHILD_PROCESS_SERVICE_H_
+#ifndef CONTENT_APP_ANDROID_CHILD_PROCESS_SERVICE_IMPL_H_
+#define CONTENT_APP_ANDROID_CHILD_PROCESS_SERVICE_IMPL_H_
#include <jni.h>
namespace content {
-bool RegisterChildProcessService(JNIEnv* env);
+bool RegisterChildProcessServiceImpl(JNIEnv* env);
} // namespace content
-#endif // CONTENT_APP_ANDROID_CHILD_PROCESS_SERVICE_H_
+#endif // CONTENT_APP_ANDROID_CHILD_PROCESS_SERVICE_IMPL_H_
diff --git a/chromium/content/app/android/library_loader_hooks.cc b/chromium/content/app/android/library_loader_hooks.cc
index 699d7e8e9b9..f26a706fee2 100644
--- a/chromium/content/app/android/library_loader_hooks.cc
+++ b/chromium/content/app/android/library_loader_hooks.cc
@@ -16,9 +16,9 @@
#include "base/strings/string_util.h"
#include "base/trace_event/trace_event.h"
#include "base/tracked_objects.h"
-#include "components/tracing/trace_config_file.h"
-#include "components/tracing/trace_to_console.h"
-#include "components/tracing/tracing_switches.h"
+#include "components/tracing/browser/trace_config_file.h"
+#include "components/tracing/common/trace_to_console.h"
+#include "components/tracing/common/tracing_switches.h"
#include "content/app/android/app_jni_registrar.h"
#include "content/browser/android/browser_jni_registrar.h"
#include "content/common/android/common_jni_registrar.h"
@@ -26,6 +26,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "device/bluetooth/android/bluetooth_jni_registrar.h"
+#include "device/power_save_blocker/power_save_blocker_jni_registrar.h"
#include "device/usb/android/usb_jni_registrar.h"
#include "media/base/android/media_jni_registrar.h"
#include "media/capture/video/android/capture_jni_registrar.h"
@@ -77,6 +78,9 @@ bool EnsureJniRegistered(JNIEnv* env) {
if (!device::android::RegisterBluetoothJni(env))
return false;
+ if (!device::android::RegisterPowerSaveBlockerJni(env))
+ return false;
+
if (!device::android::RegisterUsbJni(env))
return false;
diff --git a/chromium/content/app/content_main_runner.cc b/chromium/content/app/content_main_runner.cc
index 95b852619e5..49b94347769 100644
--- a/chromium/content/app/content_main_runner.cc
+++ b/chromium/content/app/content_main_runner.cc
@@ -39,9 +39,9 @@
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "components/tracing/trace_config_file.h"
-#include "components/tracing/trace_to_console.h"
-#include "components/tracing/tracing_switches.h"
+#include "components/tracing/browser/trace_config_file.h"
+#include "components/tracing/common/trace_to_console.h"
+#include "components/tracing/common/tracing_switches.h"
#include "content/app/mojo/mojo_init.h"
#include "content/browser/browser_main.h"
#include "content/browser/gpu/gpu_process_host.h"
@@ -178,10 +178,8 @@ base::LazyInstance<ContentUtilityClient>
#if defined(V8_USE_EXTERNAL_STARTUP_DATA) && defined(OS_ANDROID)
#if defined __LP64__
-#define kV8NativesDataDescriptor kV8NativesDataDescriptor64
#define kV8SnapshotDataDescriptor kV8SnapshotDataDescriptor64
#else
-#define kV8NativesDataDescriptor kV8NativesDataDescriptor32
#define kV8SnapshotDataDescriptor kV8SnapshotDataDescriptor32
#endif
#endif
diff --git a/chromium/content/app/mac/mac_init.mm b/chromium/content/app/mac/mac_init.mm
index 042663c7674..eea835a02a3 100644
--- a/chromium/content/app/mac/mac_init.mm
+++ b/chromium/content/app/mac/mac_init.mm
@@ -4,7 +4,7 @@
#include "content/app/mac/mac_init.h"
-#include <Cocoa/Cocoa.h>
+#import <Cocoa/Cocoa.h>
#include "base/mac/mac_util.h"
@@ -12,7 +12,16 @@ namespace content {
void InitializeMac() {
[[NSUserDefaults standardUserDefaults] registerDefaults:@{
+ // Exceptions routed to -[NSApplication reportException:] should crash
+ // immediately, as opposed being swallowed or presenting UI that gives the
+ // user a choice in the matter.
+ @"NSApplicationCrashOnExceptions": @YES,
+
+ // Prevent Cocoa from turning command-line arguments into -[NSApplication
+ // application:openFile:], because they are handled directly. @"NO" looks
+ // like a mistake, but the value really is supposed to be a string.
@"NSTreatUnknownArgumentsAsOpen": @"NO",
+
// CoreAnimation has poor performance and CoreAnimation and
// non-CoreAnimation exhibit window flickering when layers are not hosted
// in the window server, which is the default when not not using the
diff --git a/chromium/content/app/strings/translations/content_strings_hi.xtb b/chromium/content/app/strings/translations/content_strings_hi.xtb
index b5df5685719..99b4c013a90 100644
--- a/chromium/content/app/strings/translations/content_strings_hi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hi.xtb
@@ -3,7 +3,7 @@
<translationbundle lang="hi">
<translation id="1014825444426747588">खाली</translation>
<translation id="1018939186200882850">मेनू आइटम</translation>
-<translation id="1020833440720551630">ऑडियो ट्रैक म्यूट करें</translation>
+<translation id="1020833440720551630">ऑडियो ट्रैक की आवाज़ बंद करें</translation>
<translation id="10623998915015855">टॉगल बटन</translation>
<translation id="1088086359088493902">सेकंड</translation>
<translation id="1171774979989969504">कृपया ई-मेल पता दर्ज करें.</translation>
@@ -135,7 +135,7 @@
<translation id="6739588121953935928">पैमाना</translation>
<translation id="6755330956360078551">टूलटिप</translation>
<translation id="6820355525329141109">प्लग इन लोड नहीं किया जा सका.</translation>
-<translation id="6843725295806269523">म्यूट करें</translation>
+<translation id="6843725295806269523">आवाज़ बंद करें</translation>
<translation id="6845533974506654842">दबाएं</translation>
<translation id="6853785296079745596">बंद कैप्शन छिपाएं</translation>
<translation id="6885760532393684712">निर्देशिका</translation>
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index 37304695ff6..87664fbaf48 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/features.gni")
import("//build/config/ui.gni")
import("//content/browser/browser.gni")
import("//media/media_options.gni")
+import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
source_set("browser") {
# Only the public target should depend on this. All other targets (even
@@ -41,6 +42,7 @@ source_set("browser") {
"//components/tracing",
"//components/tracing:startup_tracing",
"//components/url_formatter",
+ "//components/webmessaging",
"//content:resources",
"//content/app/resources",
"//content/app/strings",
@@ -56,19 +58,21 @@ source_set("browser") {
"//crypto",
"//device/battery",
"//device/bluetooth",
+ "//device/gamepad",
+ "//device/power_save_blocker",
"//device/vibration",
"//gin",
"//google_apis",
"//gpu",
"//gpu/command_buffer/client:gles2_implementation",
"//gpu/command_buffer/client:gles2_interface",
- "//ipc/mojo",
"//media",
+ "//media/capture",
"//media/gpu/ipc/client",
"//media/midi",
+ "//media/mojo/interfaces:image_capture",
"//mojo/common",
- "//mojo/common:url_type_converters",
- "//mojo/converters/geometry",
+ "//mojo/edk/system",
"//mojo/public/cpp/bindings",
"//mojo/public/js",
"//net",
@@ -82,7 +86,6 @@ source_set("browser") {
"//services/user/public/cpp",
"//services/user/public/interfaces",
"//skia",
- "//skia/public",
"//sql",
"//storage/browser",
"//storage/common",
@@ -107,6 +110,7 @@ source_set("browser") {
"//ui/events/blink",
"//ui/gfx",
"//ui/gfx/geometry",
+ "//ui/gfx/geometry/mojo",
"//ui/gl",
"//ui/native_theme",
"//ui/resources",
@@ -154,10 +158,6 @@ source_set("browser") {
sources -= [ "renderer_host/web_input_event_aurawin.cc" ]
}
- if (!is_win && !is_mac && !is_android && (!is_linux || !use_udev)) {
- sources += [ "gamepad/gamepad_platform_data_fetcher.cc" ]
- }
-
if (enable_basic_printing || enable_print_preview) {
deps += [ "//printing" ]
}
@@ -245,10 +245,6 @@ source_set("browser") {
"//device/udev_linux",
"//media/capture",
]
- } else {
- if (is_linux) {
- sources -= [ "gamepad/gamepad_platform_data_fetcher_linux.cc" ]
- }
}
if (enable_plugins) {
@@ -289,22 +285,9 @@ source_set("browser") {
if (use_x11) {
configs += [ "//build/config/linux:x11" ]
- if (!is_chromeos) {
- configs += [ "//build/config/linux:xscrnsaver" ]
- }
deps += [ "//ui/gfx/x" ]
}
- # Dealing with power_save_blocker_{x11,ozone}.cc is a little complicated
- # given the interaction between os_chromeos and the feature flags for X11 and
- # ozone, so do it all in one spot.
- if (is_chromeos || !use_ozone) {
- sources -= [ "power_save_blocker_ozone.cc" ]
- }
- if (is_chromeos || !use_x11) {
- sources -= [ "power_save_blocker_x11.cc" ]
- }
-
# Dealing with *wifi_data_provider_*.cc is also a bit complicated given
# android, chromeos, linux and use_dbus.
if (is_android) {
@@ -360,6 +343,7 @@ source_set("browser") {
deps += [
"//content/public/android:jni",
"//media",
+ "//media/capture/video/android",
"//media/mojo/interfaces",
"//mojo/android:libsystem_java",
"//ui/android",
@@ -399,12 +383,12 @@ source_set("browser") {
if (use_aura) {
deps += [
"//components/bitmap_uploader",
+ "//components/mus/common:mus_common",
"//components/mus/public/cpp",
"//components/mus/public/interfaces",
"//ui/aura",
"//ui/aura_extra",
"//ui/strings",
- "//ui/views/mus:for_component",
"//ui/wm",
]
sources += [
@@ -502,25 +486,6 @@ source_set("browser") {
configs += [ "//media/mojo/services:mojo_media_config" ]
}
- if (enable_webvr) {
- sources += [
- "vr/vr_device.cc",
- "vr/vr_device.h",
- "vr/vr_device_manager.cc",
- "vr/vr_device_manager.h",
- "vr/vr_device_provider.h",
- ]
- }
-
- if (enable_webvr && is_android) {
- sources += [
- "vr/android/cardboard/cardboard_vr_device.cc",
- "vr/android/cardboard/cardboard_vr_device.h",
- "vr/android/cardboard/cardboard_vr_device_provider.cc",
- "vr/android/cardboard/cardboard_vr_device_provider.h",
- ]
- }
-
if (use_ozone) {
deps += [ "//ui/ozone" ]
}
@@ -531,6 +496,14 @@ source_set("browser") {
"gpu/gpu_surface_tracker.h",
]
}
+
+ if (enable_webvr) {
+ deps += [ "//device/vr" ]
+ }
+
+ if (enable_ipc_fuzzer) {
+ configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_config" ]
+ }
}
# See comment at the top of //content/BUILD.gn for how this works.
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index cce513a801d..a43e80c18c7 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -1,27 +1,32 @@
include_rules = [
- # Allow inclusion of specific components that we depend on. We may only
- # depend on components which we share with the mojo html_viewer.
+ # Allow inclusion of specific components that we depend on.
+ # See comment in content/DEPS for which components are allowed.
"+components/filesystem",
"+components/leveldb",
"+components/link_header_util",
"+components/mime_util",
+ "+components/mus/common",
"+components/mus/public/interfaces",
"+components/mus/public",
+ "+components/network_session_configurator/switches.h",
"+components/profile_service",
"+components/scheduler/common",
"+components/tracing",
"+components/url_formatter",
+ "+components/webmessaging",
"+content/app/strings/grit", # For generated headers
"+content/public/browser",
"+device/battery", # For battery status service.
+ "+device/gamepad", # For gamepad API
+ "+device/power_save_blocker",
"+device/vibration", # For Vibration API
+ "+device/vr", # For WebVR API
"+gin/v8_initializer.h",
"+mojo",
"+services",
"+sql",
"+ui/aura_extra",
- "+ui/views/mus", # http://crbug.com/555767
"+ui/webui",
"+win8/util",
@@ -53,9 +58,11 @@ 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/WebInsecureRequestPolicy.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
"+third_party/WebKit/public/platform/WebScreenInfo.h",
"+third_party/WebKit/public/platform/WebString.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/geolocation/geolocation.mojom.h",
"+third_party/WebKit/public/platform/modules/imagecapture/image_capture.mojom.h",
@@ -63,6 +70,7 @@ include_rules = [
"+third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h",
"+third_party/WebKit/public/platform/modules/notifications/WebNotificationConstants.h",
"+third_party/WebKit/public/platform/modules/notifications/notification.mojom.h",
+ "+third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom.h",
"+third_party/WebKit/public/platform/modules/permissions/permission.mojom.h",
"+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h",
"+third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h",
@@ -86,6 +94,7 @@ include_rules = [
"+third_party/WebKit/public/web/WebDeviceEmulationParams.h",
"+third_party/WebKit/public/web/WebDragStatus.h",
"+third_party/WebKit/public/web/WebFindOptions.h",
+ "+third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h",
"+third_party/WebKit/public/web/WebFrameOwnerProperties.h",
"+third_party/WebKit/public/web/WebInputEvent.h",
"+third_party/WebKit/public/web/WebMediaPlayerAction.h",
@@ -103,27 +112,9 @@ include_rules = [
# Until we define where mojo interfaces should live in blink we whitelist each
# one separately.
"+third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h",
- "+third_party/WebKit/public/platform/modules/vr/vr_service.mojom.h"
+ "+third_party/WebKit/public/platform/modules/notifications/notification_service.mojom.h",
# DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!!
# See https://sites.google.com/a/chromium.org/dev/developers/content-module
# for more information.
]
-
-specific_include_rules = {
- # See https://crbug.com/612337.
- "power_save_blocker.*\.(cc|h)": [
- "-content",
-
- # These will move to //device/power_save_blocker.
- "+content/browser/power_save_blocker_impl.h",
- "+content/public/browser/power_save_blocker.h",
-
- # These dependencies need to be removed.
- "!content/browser/android/content_view_core_impl.h",
- "!content/browser/web_contents/web_contents_impl.h",
- "!content/public/browser/android/content_view_core.h",
- "!content/public/browser/browser_thread.h",
- "!content/public/browser/web_contents_observer.h",
- ]
-}
diff --git a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
index 597631cc221..cba1d0c2c18 100644
--- a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -64,7 +64,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
// AccessibilityNotificationWaiter does this automatically) and wait for
// the first event.
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_LAYOUT_COMPLETE);
+ shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_LAYOUT_COMPLETE);
waiter.WaitForNotification();
}
@@ -84,10 +86,11 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
// Hide one of the elements on the page, and wait for an accessibility
// notification triggered by the hide.
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_LIVE_REGION_CHANGED);
- ASSERT_TRUE(ExecuteScript(
shell()->web_contents(),
- "document.getElementById('p1').style.display = 'none';"));
+ AccessibilityModeComplete,
+ ui::AX_EVENT_LIVE_REGION_CHANGED);
+ ASSERT_TRUE(ExecuteScript(
+ shell(), "document.getElementById('p1').style.display = 'none';"));
waiter.WaitForNotification();
}
@@ -101,10 +104,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
const ui::AXTree* tree = nullptr;
{
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_FOCUS);
- ASSERT_TRUE(ExecuteScript(
- shell()->web_contents(),
- "document.getElementById('button').focus();"));
+ shell()->web_contents(), AccessibilityModeComplete, ui::AX_EVENT_FOCUS);
+ ASSERT_TRUE(
+ ExecuteScript(shell(), "document.getElementById('button').focus();"));
waiter.WaitForNotification();
tree = &waiter.GetAXTree();
}
@@ -156,7 +158,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
// AccessibilityNotificationWaiter does this automatically) and wait for
// the first event.
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_LAYOUT_COMPLETE);
+ shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_LAYOUT_COMPLETE);
waiter.WaitForNotification();
}
@@ -184,7 +188,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
break;
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
+ shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
waiter.WaitForNotification();
}
diff --git a/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc b/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
index aa54862fa3d..11e2ad31b6d 100644
--- a/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
@@ -75,7 +75,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeComplete) {
ASSERT_EQ(CorrectedAccessibility(AccessibilityModeOff),
web_contents()->GetAccessibilityMode());
- AccessibilityNotificationWaiter waiter(shell());
+ AccessibilityNotificationWaiter waiter(shell()->web_contents());
web_contents()->AddAccessibilityMode(AccessibilityModeComplete);
EXPECT_EQ(AccessibilityModeComplete, web_contents()->GetAccessibilityMode());
waiter.WaitForNotification();
@@ -88,7 +88,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeTreeOnly) {
ASSERT_EQ(CorrectedAccessibility(AccessibilityModeOff),
web_contents()->GetAccessibilityMode());
- AccessibilityNotificationWaiter waiter(shell());
+ AccessibilityNotificationWaiter waiter(shell()->web_contents());
web_contents()->AddAccessibilityMode(AccessibilityModeTreeOnly);
EXPECT_EQ(CorrectedAccessibility(AccessibilityModeTreeOnly),
web_contents()->GetAccessibilityMode());
@@ -101,7 +101,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeTreeOnly) {
IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AddingModes) {
NavigateToURL(shell(), GURL(kMinimalPageDataURL));
- AccessibilityNotificationWaiter waiter(shell());
+ AccessibilityNotificationWaiter waiter(shell()->web_contents());
web_contents()->AddAccessibilityMode(AccessibilityModeTreeOnly);
EXPECT_EQ(CorrectedAccessibility(AccessibilityModeTreeOnly),
web_contents()->GetAccessibilityMode());
@@ -111,7 +111,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AddingModes) {
"Should be no BrowserAccessibilityManager "
"for AccessibilityModeTreeOnly");
- AccessibilityNotificationWaiter waiter2(shell());
+ AccessibilityNotificationWaiter waiter2(shell()->web_contents());
web_contents()->AddAccessibilityMode(AccessibilityModeComplete);
EXPECT_EQ(AccessibilityModeComplete, web_contents()->GetAccessibilityMode());
waiter2.WaitForNotification();
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
index 4953ee46529..2a92601850b 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <string>
+#include <utility>
#include "base/files/file_path.h"
#include "base/strings/string_number_conversions.h"
diff --git a/chromium/content/browser/accessibility/accessibility_ui.cc b/chromium/content/browser/accessibility/accessibility_ui.cc
index 05f49dea617..0f985192281 100644
--- a/chromium/content/browser/accessibility/accessibility_ui.cc
+++ b/chromium/content/browser/accessibility/accessibility_ui.cc
@@ -230,7 +230,8 @@ void AccessibilityUI::RequestAccessibilityTree(const base::ListValue* args) {
result->SetInteger(kProcessIdField, process_id);
result->SetInteger(kRouteIdField, route_id);
result->Set("error", new base::StringValue("Renderer no longer exists."));
- web_ui()->CallJavascriptFunction("accessibility.showTree", *(result.get()));
+ web_ui()->CallJavascriptFunctionUnsafe("accessibility.showTree",
+ *(result.get()));
return;
}
@@ -254,7 +255,8 @@ void AccessibilityUI::RequestAccessibilityTree(const base::ListValue* args) {
result->Set("tree",
new base::StringValue(
base::UTF16ToUTF8(accessibility_contents_utf16)));
- web_ui()->CallJavascriptFunction("accessibility.showTree", *(result.get()));
+ web_ui()->CallJavascriptFunctionUnsafe("accessibility.showTree",
+ *(result.get()));
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 214f4782e7b..546286e42ee 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -105,7 +105,7 @@ AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() {
void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml(
const std::string& html) {
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(), AccessibilityModeComplete,
ui::AX_EVENT_LOAD_COMPLETE);
GURL html_data_url("data:text/html," + html);
NavigateToURL(shell(), html_data_url);
@@ -163,7 +163,7 @@ void AccessibilityWinBrowserTest::SetUpInputField(
// Set the caret on the last character.
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(), AccessibilityModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
std::wstring caret_offset = base::UTF16ToWide(base::IntToString16(
static_cast<int>(CONTENTS_LENGTH - 1)));
@@ -215,7 +215,7 @@ void AccessibilityWinBrowserTest::SetUpTextareaField(
// Set the caret on the last character.
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(), AccessibilityModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
std::wstring caret_offset = base::UTF16ToWide(base::IntToString16(
static_cast<int>(CONTENTS_LENGTH - 1)));
@@ -673,7 +673,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Set focus to the radio group.
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
- new AccessibilityNotificationWaiter(shell(), AccessibilityModeComplete,
+ new AccessibilityNotificationWaiter(shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_FOCUS));
ExecuteScript(L"document.body.children[0].focus()");
waiter->WaitForNotification();
@@ -685,7 +686,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Set the active descendant of the radio group
waiter.reset(new AccessibilityNotificationWaiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(), AccessibilityModeComplete,
ui::AX_EVENT_FOCUS));
ExecuteScript(
L"document.body.children[0].setAttribute('aria-activedescendant', 'li')");
@@ -717,7 +718,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Check the checkbox.
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
- new AccessibilityNotificationWaiter(shell(), AccessibilityModeComplete,
+ new AccessibilityNotificationWaiter(shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_CHECKED_STATE_CHANGED));
ExecuteScript(L"document.body.children[0].checked=true");
waiter->WaitForNotification();
@@ -743,7 +745,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Change the children of the document body.
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
- new AccessibilityNotificationWaiter(shell(), AccessibilityModeComplete,
+ new AccessibilityNotificationWaiter(shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_CHILDREN_CHANGED));
ExecuteScript(L"document.body.innerHTML='<b>new text</b>'");
waiter->WaitForNotification();
@@ -768,7 +771,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Change the children of the document body.
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
- new AccessibilityNotificationWaiter(shell(), AccessibilityModeComplete,
+ new AccessibilityNotificationWaiter(shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_CHILDREN_CHANGED));
ExecuteScript(L"document.body.children[0].style.visibility='visible'");
waiter->WaitForNotification();
@@ -800,7 +804,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Focus the div in the document
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
- new AccessibilityNotificationWaiter(shell(), AccessibilityModeComplete,
+ new AccessibilityNotificationWaiter(shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_FOCUS));
ExecuteScript(L"document.body.children[0].focus()");
waiter->WaitForNotification();
@@ -814,7 +819,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Focus the document accessible. This will un-focus the current node.
waiter.reset(
new AccessibilityNotificationWaiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(), AccessibilityModeComplete,
ui::AX_EVENT_BLUR));
base::win::ScopedComPtr<IAccessible> document_accessible(
GetRendererAccessible());
@@ -849,7 +854,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Set the value of the text control
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
- new AccessibilityNotificationWaiter(shell(), AccessibilityModeComplete,
+ new AccessibilityNotificationWaiter(shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_VALUE_CHANGED));
ExecuteScript(L"document.body.children[0].value='new value'");
waiter->WaitForNotification();
@@ -1090,7 +1096,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetCaretOffset) {
EXPECT_EQ(CONTENTS_LENGTH - 1, caret_offset);
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
caret_offset = 0;
hr = input_text->setCaretOffset(caret_offset);
@@ -1113,7 +1120,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_EQ(CONTENTS_LENGTH - 1, caret_offset);
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
caret_offset = 0;
hr = textarea_text->setCaretOffset(caret_offset);
@@ -1707,7 +1715,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestIAccessibleAction) {
image_name.Release();
// Cllicking the image will change its name.
EXPECT_HRESULT_SUCCEEDED(image_action->doAction(0));
- AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete,
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_TEXT_CHANGED);
waiter.WaitForNotification();
EXPECT_HRESULT_SUCCEEDED(
@@ -1735,7 +1744,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, HasHWNDAfterNavigation) {
// Navigate to a new page and wait for the accessibility tree to load.
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_LOAD_COMPLETE);
NavigateToURL(shell(), embedded_test_server()->GetURL(
"/accessibility/html/article.html"));
diff --git a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
index 6ddf830423e..e03b7ae3f5e 100644
--- a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
+++ b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
@@ -40,7 +40,7 @@ class AndroidGranularityMovementBrowserTest : public ContentBrowserTest {
// Load the page.
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(), AccessibilityModeComplete,
ui::AX_EVENT_LOAD_COMPLETE);
NavigateToURL(shell(), url);
waiter.WaitForNotification();
@@ -70,7 +70,7 @@ class AndroidGranularityMovementBrowserTest : public ContentBrowserTest {
BrowserAccessibility* node,
int granularity) {
AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
+ shell()->web_contents(), AccessibilityModeComplete,
ui::AX_EVENT_TREE_CHANGED);
node->manager()->delegate()->AccessibilitySetAccessibilityFocus(
node->GetId());
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index 93d7828694f..bead70f80cb 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -131,10 +131,9 @@ bool BrowserAccessibility::IsTextOnlyObject() const {
BrowserAccessibility* BrowserAccessibility::PlatformGetChild(
uint32_t child_index) const {
- DCHECK_LT(child_index, PlatformChildCount());
BrowserAccessibility* result = nullptr;
- if (HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
+ if (child_index == 0 && HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
BrowserAccessibilityManager* child_manager =
BrowserAccessibilityManager::FromID(
GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
index 992373453e6..39d89e11830 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -61,8 +61,8 @@
// Swap the children array with the given scoped_nsobject.
- (void)swapChildren:(base::scoped_nsobject<NSMutableArray>*)other;
-// Returns the requested text range from this object's value attribute.
- (NSString*)valueForRange:(NSRange)range;
+- (NSAttributedString*)attributedValueForRange:(NSRange)range;
// Internally-used property.
@property(nonatomic, readonly) NSPoint origin;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index 1ae72bd2e30..6b6a156d06e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -196,6 +196,36 @@ bool GetTextMarkerRange(AXTextMarkerRangeRef marker_range,
GetTextMarkerData(end_marker.get(), end_object, end_offset);
}
+void AddMisspelledTextAttributes(
+ const std::vector<const BrowserAccessibility*>& text_only_objects,
+ NSMutableAttributedString* attributed_string) {
+ [attributed_string beginEditing];
+ for (const BrowserAccessibility* text_object : text_only_objects) {
+ const std::vector<int32_t>& marker_types =
+ text_object->GetIntListAttribute(ui::AX_ATTR_MARKER_TYPES);
+ const std::vector<int>& marker_starts =
+ text_object->GetIntListAttribute(ui::AX_ATTR_MARKER_STARTS);
+ const std::vector<int>& marker_ends =
+ text_object->GetIntListAttribute(ui::AX_ATTR_MARKER_ENDS);
+ for (size_t i = 0; i < marker_types.size(); ++i) {
+ if (!(static_cast<ui::AXMarkerType>(marker_types[i]) &
+ ui::AX_MARKER_TYPE_SPELLING)) {
+ continue;
+ }
+
+ int misspelling_start = marker_starts[i];
+ int misspelling_end = marker_ends[i];
+ int misspelling_length = misspelling_end - misspelling_start;
+ DCHECK_GT(misspelling_length, 0);
+ [attributed_string
+ addAttribute:NSAccessibilityMarkedMisspelledTextAttribute
+ value:@YES
+ range:NSMakeRange(misspelling_start, misspelling_length)];
+ }
+ }
+ [attributed_string endEditing];
+}
+
NSString* GetTextForTextMarkerRange(AXTextMarkerRangeRef marker_range) {
BrowserAccessibility* start_object;
BrowserAccessibility* end_object;
@@ -212,6 +242,44 @@ NSString* GetTextForTextMarkerRange(AXTextMarkerRangeRef marker_range) {
*start_object, start_offset, *end_object, end_offset));
}
+NSAttributedString* GetAttributedTextForTextMarkerRange(
+ AXTextMarkerRangeRef marker_range) {
+ BrowserAccessibility* start_object;
+ BrowserAccessibility* end_object;
+ int start_offset, end_offset;
+ if (!GetTextMarkerRange(marker_range, &start_object, &start_offset,
+ &end_object, &end_offset)) {
+ return nil;
+ }
+
+ NSString* text = base::SysUTF16ToNSString(
+ BrowserAccessibilityManager::GetTextForRange(*start_object, *end_object));
+ if ([text length] == 0)
+ return nil;
+
+ // Be permissive with the start and end offsets.
+ if (start_object == end_object && end_offset < start_offset)
+ std::swap(start_offset, end_offset);
+
+ int trim_length = 0;
+ if ((end_object->IsSimpleTextControl() || end_object->IsTextOnlyObject()) &&
+ end_offset < static_cast<int>(end_object->GetText().length())) {
+ trim_length = static_cast<int>(end_object->GetText().length()) - end_offset;
+ }
+ int range_length = [text length] - start_offset - trim_length;
+ DCHECK_GE(range_length, 0);
+ NSRange range = NSMakeRange(start_offset, range_length);
+ DCHECK_LE(NSMaxRange(range), [text length]);
+
+ NSMutableAttributedString* attributed_text =
+ [[[NSMutableAttributedString alloc] initWithString:text] autorelease];
+ std::vector<const BrowserAccessibility*> text_only_objects =
+ BrowserAccessibilityManager::FindTextOnlyObjectsInRange(*start_object,
+ *end_object);
+ AddMisspelledTextAttributes(text_only_objects, attributed_text);
+ return [attributed_text attributedSubstringFromRange:range];
+}
+
// Returns an autoreleased copy of the AXNodeData's attribute.
NSString* NSStringForStringAttribute(
BrowserAccessibility* browserAccessibility,
@@ -1093,9 +1161,11 @@ bool InitializeAccessibilityTreeSearch(
} else {
// Hook back up to RenderWidgetHostViewCocoa.
BrowserAccessibilityManagerMac* manager =
- static_cast<BrowserAccessibilityManagerMac*>(
- browserAccessibility_->manager());
- return manager->parent_view();
+ browserAccessibility_->manager()->GetRootManager()
+ ->ToBrowserAccessibilityManagerMac();
+ if (manager)
+ return manager->parent_view();
+ return nil;
}
}
@@ -1573,14 +1643,14 @@ bool InitializeAccessibilityTreeSearch(
ui::AXRole browserAccessibilityRole = [self internalRole];
if (browserAccessibilityRole == ui::AX_ROLE_TEXT_FIELD &&
GetState(browserAccessibility_, ui::AX_STATE_PROTECTED)) {
- return @"AXSecureTextField";
+ return NSAccessibilitySecureTextFieldSubrole;
}
if (browserAccessibilityRole == ui::AX_ROLE_DESCRIPTION_LIST)
- return @"AXDefinitionList";
+ return NSAccessibilityDefinitionListSubrole;
if (browserAccessibilityRole == ui::AX_ROLE_LIST)
- return @"AXContentList";
+ return NSAccessibilityContentListSubrole;
return [AXPlatformNodeCocoa nativeSubroleFromAXRole:browserAccessibilityRole];
}
@@ -1801,8 +1871,8 @@ bool InitializeAccessibilityTreeSearch(
return nil;
BrowserAccessibilityManagerMac* manager =
- static_cast<BrowserAccessibilityManagerMac*>(
- browserAccessibility_->manager());
+ browserAccessibility_->manager()->GetRootManager()
+ ->ToBrowserAccessibilityManagerMac();
if (!manager || !manager->parent_view())
return nil;
@@ -1817,18 +1887,33 @@ bool InitializeAccessibilityTreeSearch(
children_.swap(*other);
}
-// Returns the requested text range from this object's value attribute.
- (NSString*)valueForRange:(NSRange)range {
if (![self instanceActive])
return nil;
base::string16 value = browserAccessibility_->GetValue();
- if (NSMaxRange(range) > value.size())
+ if (NSMaxRange(range) > value.length())
return nil;
return base::SysUTF16ToNSString(value.substr(range.location, range.length));
}
+- (NSAttributedString*)attributedValueForRange:(NSRange)range {
+ if (![self instanceActive])
+ return nil;
+
+ // We need to get the whole text because a spelling mistake might start or end
+ // outside our range.
+ NSString* value = base::SysUTF16ToNSString(browserAccessibility_->GetValue());
+ NSMutableAttributedString* attributedValue =
+ [[[NSMutableAttributedString alloc] initWithString:value] autorelease];
+ std::vector<const BrowserAccessibility*> textOnlyObjects =
+ BrowserAccessibilityManager::FindTextOnlyObjectsInRange(
+ *browserAccessibility_, *browserAccessibility_);
+ AddMisspelledTextAttributes(textOnlyObjects, attributedValue);
+ return [attributedValue attributedSubstringFromRange:range];
+}
+
// Returns the accessibility value for the given attribute. If the value isn't
// supported this will return nil.
- (id)accessibilityAttributeValue:(NSString*)attribute {
@@ -1864,8 +1949,7 @@ bool InitializeAccessibilityTreeSearch(
if ([attribute
isEqualToString:
NSAccessibilityAttributedStringForRangeParameterizedAttribute]) {
- NSString* value = [self valueForRange:[(NSValue*)parameter rangeValue]];
- return [[[NSAttributedString alloc] initWithString:value] autorelease];
+ return [self attributedValueForRange:[(NSValue*)parameter rangeValue]];
}
if ([attribute isEqualToString:
@@ -1961,12 +2045,10 @@ bool InitializeAccessibilityTreeSearch(
}
if ([attribute isEqualToString:@"AXStringForTextMarkerRange"])
- return GetTextForTextMarkerRange(parameter);
+ GetTextForTextMarkerRange(parameter);
- if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) {
- NSString* text = GetTextForTextMarkerRange(parameter);
- return [[[NSAttributedString alloc] initWithString:text] autorelease];
- }
+ if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])
+ return GetAttributedTextForTextMarkerRange(parameter);
if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
BrowserAccessibility* object;
@@ -2018,6 +2100,63 @@ bool InitializeAccessibilityTreeSearch(
return CreateTextMarker(*object, offset);
}
+ // Currently we approximate end offsets of words and do not actually calculate
+ // end offsets of lines, but use the start offset of the next line instead.
+ // This seems to work in simple text fields.
+ // TODO(nektar): Fix end offsets of words and lines.
+ if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
+ BrowserAccessibility* object;
+ int original_offset;
+ if (!GetTextMarkerData(parameter, &object, &original_offset))
+ return nil;
+
+ int start_offset =
+ object->GetWordStartBoundary(original_offset, ui::BACKWARDS_DIRECTION);
+ DCHECK_GE(start_offset, 0);
+
+ int end_offset =
+ object->GetWordStartBoundary(start_offset, ui::FORWARDS_DIRECTION);
+ DCHECK_GE(end_offset, 0);
+ if (start_offset < end_offset &&
+ end_offset < static_cast<int>(object->GetText().length())) {
+ --end_offset;
+ }
+ return CreateTextMarkerRange(*object, start_offset, *object, end_offset);
+ }
+
+ if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
+ BrowserAccessibility* object;
+ int original_offset;
+ if (!GetTextMarkerData(parameter, &object, &original_offset))
+ return nil;
+
+ int start_offset =
+ object->GetWordStartBoundary(original_offset, ui::FORWARDS_DIRECTION);
+ DCHECK_GE(start_offset, 0);
+
+ int end_offset =
+ object->GetWordStartBoundary(start_offset, ui::FORWARDS_DIRECTION);
+ DCHECK_GE(end_offset, 0);
+ if (start_offset < end_offset &&
+ end_offset < static_cast<int>(object->GetText().length())) {
+ --end_offset;
+ }
+ return CreateTextMarkerRange(*object, start_offset, *object, end_offset);
+ }
+
+ if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
+ BrowserAccessibility* object;
+ int offset;
+ if (!GetTextMarkerData(parameter, &object, &offset))
+ return nil;
+
+ offset = object->GetWordStartBoundary(offset, ui::FORWARDS_DIRECTION);
+ DCHECK_GE(offset, 0);
+ if (offset > 0 && offset < static_cast<int>(object->GetText().length()))
+ --offset;
+ return CreateTextMarker(*object, offset);
+ }
+
if ([attribute
isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
BrowserAccessibility* object;
@@ -2025,8 +2164,31 @@ bool InitializeAccessibilityTreeSearch(
if (!GetTextMarkerData(parameter, &object, &offset))
return nil;
- DCHECK(object);
offset = object->GetWordStartBoundary(offset, ui::BACKWARDS_DIRECTION);
+ DCHECK_GE(offset, 0);
+ return CreateTextMarker(*object, offset);
+ }
+
+ if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
+ BrowserAccessibility* object;
+ int offset;
+ if (!GetTextMarkerData(parameter, &object, &offset))
+ return nil;
+
+ offset = object->GetLineStartBoundary(offset, ui::FORWARDS_DIRECTION);
+ DCHECK_GE(offset, 0);
+ return CreateTextMarker(*object, offset);
+ }
+
+ if ([attribute
+ isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {
+ BrowserAccessibility* object;
+ int offset;
+ if (!GetTextMarkerData(parameter, &object, &offset))
+ return nil;
+
+ offset = object->GetLineStartBoundary(offset, ui::BACKWARDS_DIRECTION);
+ DCHECK_GE(offset, 0);
return CreateTextMarker(*object, offset);
}
@@ -2071,6 +2233,22 @@ bool InitializeAccessibilityTreeSearch(
return nil;
}
+ if ([attribute
+ isEqualToString:
+ NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute]) {
+ BrowserAccessibility* object;
+ int offset;
+ if (!GetTextMarkerData(parameter, &object, &offset))
+ return nil;
+
+ DCHECK(object);
+ int start_offset =
+ object->GetLineStartBoundary(offset, ui::BACKWARDS_DIRECTION);
+ int end_offset =
+ object->GetLineStartBoundary(offset, ui::FORWARDS_DIRECTION);
+ return CreateTextMarkerRange(*object, start_offset, *object, end_offset);
+ }
+
return nil;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 84c2ec0ef05..6e7bf7a42de 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -387,18 +387,12 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
if (event_type == ui::AX_EVENT_FOCUS ||
event_type == ui::AX_EVENT_BLUR) {
if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN &&
- osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED)
+ osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED) {
osk_state_ = OSK_ALLOWED;
+ }
- bool is_menu_list_option =
- node->data().role == ui::AX_ROLE_MENU_LIST_OPTION;
-
- // Skip all focus events other than ones on menu list options;
- // we've already handled them, above. Menu list options are a weird
- // exception because the menu list itself has focus but we need to fire
- // focus events on the individual options.
- if (!is_menu_list_option)
- continue;
+ // We already handled all focus events above.
+ continue;
}
// Fire the native event.
@@ -489,19 +483,35 @@ void BrowserAccessibilityManager::ActivateFindInPageResult(
node);
}
-BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus(
+BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendant(
BrowserAccessibility* focus) {
if (!focus)
- return NULL;
+ return nullptr;
- int active_descendant_id;
+ int32_t active_descendant_id;
+ BrowserAccessibility* active_descendant = nullptr;
if (focus->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
&active_descendant_id)) {
- BrowserAccessibility* active_descendant =
- focus->manager()->GetFromID(active_descendant_id);
- if (active_descendant)
- return active_descendant;
+ active_descendant = focus->manager()->GetFromID(active_descendant_id);
}
+
+ if (focus->GetRole() == ui::AX_ROLE_POP_UP_BUTTON) {
+ BrowserAccessibility* child = focus->InternalGetChild(0);
+ if (child && child->GetRole() == ui::AX_ROLE_MENU_LIST_POPUP) {
+ // The active descendant is found on the menu list popup, i.e. on the
+ // actual list and not on the button that opens it.
+ // If there is no active descendant, focus should stay on the button so
+ // that Windows screen readers would enable their virtual cursor.
+ if (child->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
+ &active_descendant_id)) {
+ active_descendant = child->manager()->GetFromID(active_descendant_id);
+ }
+ }
+ }
+
+ if (active_descendant)
+ return active_descendant;
+
return focus;
}
@@ -521,6 +531,9 @@ BrowserAccessibility* BrowserAccessibilityManager::GetFocus() {
BrowserAccessibilityManager* focused_manager = nullptr;
if (focused_tree_id)
focused_manager =BrowserAccessibilityManager::FromID(focused_tree_id);
+
+ // BrowserAccessibilityManager::FromID(focused_tree_id) may return nullptr
+ // if the tree is not created or has been destroyed.
if (!focused_manager)
focused_manager = root_manager;
@@ -615,6 +628,7 @@ gfx::Rect BrowserAccessibilityManager::GetViewBounds() {
}
// static
+// Next object in tree using depth-first pre-order traversal.
BrowserAccessibility* BrowserAccessibilityManager::NextInTreeOrder(
const BrowserAccessibility* object) {
if (!object)
@@ -635,6 +649,7 @@ BrowserAccessibility* BrowserAccessibilityManager::NextInTreeOrder(
}
// static
+// Previous object in tree using depth-first pre-order traversal.
BrowserAccessibility* BrowserAccessibilityManager::PreviousInTreeOrder(
const BrowserAccessibility* object) {
if (!object)
@@ -705,34 +720,18 @@ bool BrowserAccessibilityManager::FindIndicesInCommonParent(
}
// static
-base::string16 BrowserAccessibilityManager::GetTextForRange(
+std::vector<const BrowserAccessibility*>
+BrowserAccessibilityManager::FindTextOnlyObjectsInRange(
const BrowserAccessibility& start_object,
- int start_offset,
- const BrowserAccessibility& end_object,
- int end_offset) {
- DCHECK_GE(start_offset, 0);
- DCHECK_GE(end_offset, 0);
-
- if (&start_object == &end_object && start_object.IsSimpleTextControl()) {
- if (start_offset > end_offset)
- std::swap(start_offset, end_offset);
-
- if (start_offset >= static_cast<int>(start_object.GetValue().length()) ||
- end_offset > static_cast<int>(start_object.GetValue().length())) {
- return base::string16();
- }
-
- return start_object.GetValue().substr(start_offset,
- end_offset - start_offset);
- }
-
+ const BrowserAccessibility& end_object) {
+ std::vector<const BrowserAccessibility*> text_only_objects;
int child_index1 = -1;
int child_index2 = -1;
if (&start_object != &end_object) {
BrowserAccessibility* common_parent;
if (!FindIndicesInCommonParent(start_object, end_object, &common_parent,
&child_index1, &child_index2)) {
- return base::string16();
+ return text_only_objects;
}
DCHECK(common_parent);
@@ -746,8 +745,16 @@ base::string16 BrowserAccessibilityManager::GetTextForRange(
const BrowserAccessibility* start_text_object = nullptr;
const BrowserAccessibility* end_text_object = nullptr;
- if (child_index1 <= child_index2 ||
- end_object.IsDescendantOf(&start_object)) {
+ if (&start_object == &end_object && start_object.IsSimpleTextControl()) {
+ // We need to get to the shadow DOM that is inside the text control in order
+ // to find the text-only objects.
+ if (!start_object.InternalChildCount())
+ return text_only_objects;
+ start_text_object = start_object.InternalGetChild(0);
+ end_text_object =
+ start_object.InternalGetChild(start_object.InternalChildCount() - 1);
+ } else if (child_index1 <= child_index2 ||
+ end_object.IsDescendantOf(&start_object)) {
start_text_object = &start_object;
end_text_object = &end_object;
} else if (child_index1 > child_index2 ||
@@ -756,8 +763,8 @@ base::string16 BrowserAccessibilityManager::GetTextForRange(
end_text_object = &start_object;
}
- if (!start_text_object->PlatformIsLeaf())
- start_text_object = start_text_object->PlatformDeepestFirstChild();
+ // Pre-order traversal might leave some text-only objects behind if we don't
+ // start from the deepest children of the end object.
if (!end_text_object->PlatformIsLeaf())
end_text_object = end_text_object->PlatformDeepestLastChild();
@@ -767,36 +774,92 @@ base::string16 BrowserAccessibilityManager::GetTextForRange(
end_text_object = PreviousTextOnlyObject(end_text_object);
if (!start_text_object || !end_text_object)
+ return text_only_objects;
+
+ while (start_text_object && start_text_object != end_text_object) {
+ text_only_objects.push_back(start_text_object);
+ start_text_object = NextTextOnlyObject(start_text_object);
+ }
+ text_only_objects.push_back(end_text_object);
+
+ return text_only_objects;
+}
+
+// static
+base::string16 BrowserAccessibilityManager::GetTextForRange(
+ const BrowserAccessibility& start_object,
+ const BrowserAccessibility& end_object) {
+ return GetTextForRange(start_object, 0, end_object,
+ end_object.GetText().length());
+}
+
+// static
+base::string16 BrowserAccessibilityManager::GetTextForRange(
+ const BrowserAccessibility& start_object,
+ int start_offset,
+ const BrowserAccessibility& end_object,
+ int end_offset) {
+ DCHECK_GE(start_offset, 0);
+ DCHECK_GE(end_offset, 0);
+
+ if (&start_object == &end_object && start_object.IsSimpleTextControl()) {
+ if (start_offset > end_offset)
+ std::swap(start_offset, end_offset);
+
+ if (start_offset >= static_cast<int>(start_object.GetText().length()) ||
+ end_offset > static_cast<int>(start_object.GetText().length())) {
+ return base::string16();
+ }
+
+ return start_object.GetText().substr(start_offset,
+ end_offset - start_offset);
+ }
+
+ std::vector<const BrowserAccessibility*> text_only_objects =
+ FindTextOnlyObjectsInRange(start_object, end_object);
+ if (text_only_objects.empty())
return base::string16();
- // Be a little permissive with the start and end offsets.
- if (start_text_object == end_text_object) {
+ if (text_only_objects.size() == 1) {
+ // Be a little permissive with the start and end offsets.
if (start_offset > end_offset)
std::swap(start_offset, end_offset);
- if (start_offset <
- static_cast<int>(start_text_object->GetText().length()) &&
- end_offset <= static_cast<int>(end_text_object->GetText().length())) {
- return start_text_object->GetText().substr(start_offset,
- end_offset - start_offset);
+ const BrowserAccessibility* text_object = text_only_objects[0];
+ if (start_offset < static_cast<int>(text_object->GetText().length()) &&
+ end_offset <= static_cast<int>(text_object->GetText().length())) {
+ return text_object->GetText().substr(start_offset,
+ end_offset - start_offset);
}
- return start_text_object->GetText();
+ return text_object->GetText();
}
base::string16 text;
- if (start_offset < static_cast<int>(start_text_object->GetText().length()))
+ const BrowserAccessibility* start_text_object = text_only_objects[0];
+ // Figure out if the start and end positions have been reversed.
+ const BrowserAccessibility* first_object = &start_object;
+ if (!first_object->IsTextOnlyObject())
+ first_object = NextTextOnlyObject(first_object);
+ if (!first_object || first_object != start_text_object)
+ std::swap(start_offset, end_offset);
+
+ if (start_offset < static_cast<int>(start_text_object->GetText().length())) {
text += start_text_object->GetText().substr(start_offset);
- else
- text += start_text_object->GetText();
- start_text_object = NextTextOnlyObject(start_text_object);
- while (start_text_object && start_text_object != end_text_object) {
+ } else {
text += start_text_object->GetText();
- start_text_object = NextTextOnlyObject(start_text_object);
}
- if (end_offset <= static_cast<int>(end_text_object->GetText().length()))
+
+ for (size_t i = 1; i < text_only_objects.size() - 1; ++i) {
+ text += text_only_objects[i]->GetText();
+ }
+
+ const BrowserAccessibility* end_text_object =
+ text_only_objects[text_only_objects.size() - 1];
+ if (end_offset <= static_cast<int>(end_text_object->GetText().length())) {
text += end_text_object->GetText().substr(0, end_offset);
- else
+ } else {
text += end_text_object->GetText();
+ }
return text;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index d875e8aedba..45957d9acbd 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -35,6 +35,8 @@ class BrowserAccessibilityManagerAndroid;
class BrowserAccessibilityManagerWin;
#elif defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_X11)
class BrowserAccessibilityManagerAuraLinux;
+#elif defined(OS_MACOSX)
+class BrowserAccessibilityManagerMac;
#endif
class SiteInstance;
@@ -276,6 +278,10 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
ToBrowserAccessibilityManagerAuraLinux();
#endif
+#if defined(OS_MACOSX)
+ BrowserAccessibilityManagerMac* ToBrowserAccessibilityManagerMac();
+#endif
+
// Return the object that has focus, starting at the top of the frame tree.
virtual BrowserAccessibility* GetFocus();
@@ -285,7 +291,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// Given a focused node |focus|, returns a descendant of that node if it
// has an active descendant, otherwise returns |focus|.
- BrowserAccessibility* GetActiveDescendantFocus(BrowserAccessibility* focus);
+ BrowserAccessibility* GetActiveDescendant(BrowserAccessibility* focus);
// Returns true if native focus is anywhere in this WebContents or not.
bool NativeViewHasFocus();
@@ -294,7 +300,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// scroll offsets separately.
virtual bool UseRootScrollOffsetsWhenComputingBounds();
- // Walk the tree.
+ // Walk the tree using depth-first pre-order traversal.
static BrowserAccessibility* NextInTreeOrder(
const BrowserAccessibility* object);
static BrowserAccessibility* PreviousInTreeOrder(
@@ -314,9 +320,16 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
int* child_index1,
int* child_index2);
- // Returns all the text found between the given start and end locations.
+ static std::vector<const BrowserAccessibility*> FindTextOnlyObjectsInRange(
+ const BrowserAccessibility& start_object,
+ const BrowserAccessibility& end_object);
+
+ static base::string16 GetTextForRange(
+ const BrowserAccessibility& start_object,
+ const BrowserAccessibility& end_object);
+
// If start and end offsets are greater than the text's length, returns all
- // the text until text length.
+ // the text.
static base::string16 GetTextForRange(
const BrowserAccessibility& start_object,
int start_offset,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index 0575e94d12b..cdb5bbbd84f 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -192,6 +192,11 @@ bool BrowserAccessibilityManagerAndroid::ShouldExposePasswordText() {
env, obj.obj());
}
+BrowserAccessibility* BrowserAccessibilityManagerAndroid::GetFocus() {
+ BrowserAccessibility* focus = BrowserAccessibilityManager::GetFocus();
+ return GetActiveDescendant(focus);
+}
+
void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
BrowserAccessibilityEvent::Source source,
ui::AXEvent event_type,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
index 90d0064f7bd..d17a6754821 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -77,6 +77,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
bool ShouldExposePasswordText();
// BrowserAccessibilityManager overrides.
+ BrowserAccessibility* GetFocus() override;
void NotifyAccessibilityEvent(
BrowserAccessibilityEvent::Source source,
ui::AXEvent event_type,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index c389a5c2f3c..604e42008fa 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -105,6 +105,11 @@ BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
NULL, initial_tree, delegate, factory);
}
+BrowserAccessibilityManagerMac*
+BrowserAccessibilityManager::ToBrowserAccessibilityManagerMac() {
+ return static_cast<BrowserAccessibilityManagerMac*>(this);
+}
+
BrowserAccessibilityManagerMac::BrowserAccessibilityManagerMac(
NSView* parent_view,
const ui::AXTreeUpdate& initial_tree,
@@ -132,14 +137,20 @@ ui::AXTreeUpdate
}
BrowserAccessibility* BrowserAccessibilityManagerMac::GetFocus() {
+ BrowserAccessibility* focus = BrowserAccessibilityManager::GetFocus();
+
// On Mac, list boxes should always get focus on the whole list, otherwise
// information about the number of selected items will never be reported.
- BrowserAccessibility* node = BrowserAccessibilityManager::GetFocus();
- if (node && node->GetRole() == ui::AX_ROLE_LIST_BOX)
- return node;
+ // For editable combo boxes, focus should stay on the combo box so the user
+ // will not be taken out of the combo box while typing.
+ if (focus && (focus->GetRole() == ui::AX_ROLE_LIST_BOX ||
+ (focus->GetRole() == ui::AX_ROLE_COMBO_BOX &&
+ focus->HasState(ui::AX_STATE_EDITABLE)))) {
+ return focus;
+ }
// For other roles, follow the active descendant.
- return GetActiveDescendantFocus(node);
+ return GetActiveDescendant(focus);
}
void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
@@ -149,20 +160,6 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
if (!node->IsNative())
return;
- if (event_type == ui::AX_EVENT_FOCUS) {
- BrowserAccessibility* active_descendant = GetActiveDescendantFocus(node);
- if (active_descendant)
- node = active_descendant;
-
- if (node->GetRole() == ui::AX_ROLE_LIST_BOX_OPTION &&
- node->HasState(ui::AX_STATE_SELECTED) &&
- node->GetParent() &&
- node->GetParent()->GetRole() == ui::AX_ROLE_LIST_BOX) {
- node = node->GetParent();
- SetFocus(*node);
- }
- }
-
auto native_node = ToBrowserAccessibilityCocoa(node);
DCHECK(native_node);
@@ -178,7 +175,10 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
// the combo box where the user might be typing.
mac_notification = NSAccessibilitySelectedChildrenChangedNotification;
} else {
- mac_notification = NSAccessibilityFocusedUIElementChangedNotification;
+ // In all other cases we should post
+ // |NSAccessibilityFocusedUIElementChangedNotification|, but this is
+ // handled elsewhere.
+ return;
}
break;
case ui::AX_EVENT_AUTOCORRECTION_OCCURED:
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index 609a4b6646d..bb214c590ee 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -1321,6 +1321,21 @@ TEST(BrowserAccessibilityManagerTest, TestGetTextForRange) {
paragraph_text_accessible->InternalGetChild(1);
ASSERT_NE(nullptr, paragraph_line2_accessible);
+ std::vector<const BrowserAccessibility*> text_only_objects =
+ BrowserAccessibilityManager::FindTextOnlyObjectsInRange(*root_accessible,
+ *root_accessible);
+ EXPECT_EQ(3U, text_only_objects.size());
+ EXPECT_EQ(button_text_accessible, text_only_objects[0]);
+ EXPECT_EQ(line_break_accessible, text_only_objects[1]);
+ EXPECT_EQ(paragraph_text_accessible, text_only_objects[2]);
+
+ text_only_objects = BrowserAccessibilityManager::FindTextOnlyObjectsInRange(
+ *div_accessible, *paragraph_accessible);
+ EXPECT_EQ(3U, text_only_objects.size());
+ EXPECT_EQ(button_text_accessible, text_only_objects[0]);
+ EXPECT_EQ(line_break_accessible, text_only_objects[1]);
+ EXPECT_EQ(paragraph_text_accessible, text_only_objects[2]);
+
EXPECT_EQ(base::ASCIIToUTF16("Button\nHello world."),
BrowserAccessibilityManager::GetTextForRange(*root_accessible, 0,
*root_accessible, 19));
@@ -1380,6 +1395,11 @@ TEST(BrowserAccessibilityManagerTest, TestGetTextForRange) {
base::ASCIIToUTF16("Hello world."),
BrowserAccessibilityManager::GetTextForRange(
*paragraph_line1_accessible, 0, *paragraph_line2_accessible, 6));
+ // Start and end positions could be reversed.
+ EXPECT_EQ(
+ base::ASCIIToUTF16("Hello world."),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_line2_accessible, 6, *paragraph_line1_accessible, 0));
}
TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash) {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index f09eea99cd4..f5bf163e6e2 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -104,6 +104,11 @@ void BrowserAccessibilityManagerWin::UserIsReloading() {
}
}
+BrowserAccessibility* BrowserAccessibilityManagerWin::GetFocus() {
+ BrowserAccessibility* focus = BrowserAccessibilityManager::GetFocus();
+ return GetActiveDescendant(focus);
+}
+
void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
BrowserAccessibilityEvent::Source source,
ui::AXEvent event_type,
@@ -231,6 +236,7 @@ bool BrowserAccessibilityManagerWin::CanFireEvents() {
void BrowserAccessibilityManagerWin::FireFocusEvent(
BrowserAccessibilityEvent::Source source,
BrowserAccessibility* node) {
+ DCHECK(node);
// On Windows, we always fire a FOCUS event on the root of a frame before
// firing a focus event within that frame.
if (node->manager() != last_focused_manager_ &&
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
index 35603bbf73c..3ebdec02e41 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -43,6 +43,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// BrowserAccessibilityManager methods
void UserIsReloading() override;
+ BrowserAccessibility* GetFocus() override;
void NotifyAccessibilityEvent(
BrowserAccessibilityEvent::Source source,
ui::AXEvent event_type,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.cc b/chromium/content/browser/accessibility/browser_accessibility_win.cc
index 3a83c0eb13a..3439cafbf16 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.cc
@@ -8,6 +8,8 @@
#include <UIAutomationCoreApi.h>
#include <algorithm>
+#include <iterator>
+#include <utility>
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -64,6 +66,11 @@ class BrowserAccessibilityRelation
CONTENT_EXPORT void Initialize(BrowserAccessibilityWin* owner,
const base::string16& type);
CONTENT_EXPORT void AddTarget(int target_id);
+ CONTENT_EXPORT void RemoveTarget(int target_id);
+
+ // Accessors.
+ const base::string16& get_type() const { return type_; }
+ const std::vector<int>& get_target_ids() const { return target_ids_; }
// IAccessibleRelation methods.
CONTENT_EXPORT STDMETHODIMP get_relationType(BSTR* relation_type) override;
@@ -95,6 +102,12 @@ void BrowserAccessibilityRelation::AddTarget(int target_id) {
target_ids_.push_back(target_id);
}
+void BrowserAccessibilityRelation::RemoveTarget(int target_id) {
+ target_ids_.erase(
+ std::remove(target_ids_.begin(), target_ids_.end(), target_id),
+ target_ids_.end());
+}
+
STDMETHODIMP BrowserAccessibilityRelation::get_relationType(
BSTR* relation_type) {
if (!relation_type)
@@ -209,8 +222,8 @@ BrowserAccessibilityWin::BrowserAccessibilityWin()
}
BrowserAccessibilityWin::~BrowserAccessibilityWin() {
- for (size_t i = 0; i < relations_.size(); ++i)
- relations_[i]->Release();
+ for (BrowserAccessibilityRelation* relation : relations_)
+ relation->Release();
}
//
@@ -729,7 +742,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_uniqueID(LONG* unique_id) {
if (!unique_id)
return E_INVALIDARG;
- *unique_id = -unique_id_;
+ *unique_id = -this->unique_id();
return S_OK;
}
@@ -2409,7 +2422,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_hyperlink(
}
int32_t id = hyperlinks()[index];
- BrowserAccessibilityWin* link = GetFromID(id);
+ BrowserAccessibilityWin* link =
+ ToBrowserAccessibilityWin(GetFromUniqueID(id));
if (!link)
return E_FAIL;
@@ -2775,7 +2789,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nodeInfo(
*name_space_id = 0;
*node_value = SysAllocString(value().c_str());
*num_children = PlatformChildCount();
- *unique_id = -unique_id_;
+ *unique_id = -this->unique_id();
if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA ||
GetRole() == ui::AX_ROLE_WEB_AREA) {
@@ -3314,6 +3328,26 @@ void BrowserAccessibilityWin::ComputeStylesIfNeeded() {
std::map<int, std::vector<base::string16>> attributes_map;
if (PlatformIsLeaf()) {
attributes_map[0] = ComputeTextAttributes();
+ std::map<int, std::vector<base::string16>> spelling_attributes =
+ GetSpellingAttributes();
+ for (auto& spelling_attribute : spelling_attributes) {
+ auto attributes_iterator = attributes_map.find(spelling_attribute.first);
+ if (attributes_iterator == attributes_map.end()) {
+ attributes_map[spelling_attribute.first] =
+ std::move(spelling_attribute.second);
+ } else {
+ std::vector<base::string16>& existing_attributes =
+ attributes_iterator->second;
+ auto existing_spelling_attribute =
+ std::find(existing_attributes.begin(), existing_attributes.end(),
+ L"invalid:false");
+ if (existing_spelling_attribute != existing_attributes.end())
+ existing_attributes.erase(existing_spelling_attribute);
+ existing_attributes.insert(existing_attributes.end(),
+ spelling_attribute.second.begin(),
+ spelling_attribute.second.end());
+ }
+ }
win_attributes_->offset_to_text_attributes.swap(attributes_map);
return;
}
@@ -3487,30 +3521,32 @@ void BrowserAccessibilityWin::UpdateStep1ComputeWinAttributes() {
win_attributes_->description = GetString16Attribute(ui::AX_ATTR_DESCRIPTION);
base::string16 value = GetValue();
-
// On Windows, the value of a document should be its url.
if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA ||
GetRole() == ui::AX_ROLE_WEB_AREA) {
value = base::UTF8ToUTF16(manager()->GetTreeData().url);
}
-
// If this doesn't have a value and is linked then set its value to the url
// attribute. This allows screen readers to read an empty link's destination.
if (value.empty() && (ia_state() & STATE_SYSTEM_LINKED))
value = GetString16Attribute(ui::AX_ATTR_URL);
-
win_attributes_->value = value;
- // Clear any old relationships between this node and other nodes.
- for (size_t i = 0; i < relations_.size(); ++i)
- relations_[i]->Release();
- relations_.clear();
-
- // Handle title UI element.
- AddRelations(ui::AX_ATTR_CONTROLS_IDS, IA2_RELATION_CONTROLLER_FOR);
- AddRelations(ui::AX_ATTR_DESCRIBEDBY_IDS, IA2_RELATION_DESCRIBED_BY);
- AddRelations(ui::AX_ATTR_FLOWTO_IDS, IA2_RELATION_FLOWS_TO);
- AddRelations(ui::AX_ATTR_LABELLEDBY_IDS, IA2_RELATION_LABELLED_BY);
+ ClearOwnRelations();
+ AddBidirectionalRelations(IA2_RELATION_CONTROLLER_FOR,
+ IA2_RELATION_CONTROLLED_BY,
+ ui::AX_ATTR_CONTROLS_IDS);
+ AddBidirectionalRelations(IA2_RELATION_DESCRIBED_BY,
+ IA2_RELATION_DESCRIPTION_FOR,
+ ui::AX_ATTR_DESCRIBEDBY_IDS);
+ AddBidirectionalRelations(IA2_RELATION_FLOWS_TO, IA2_RELATION_FLOWS_FROM,
+ ui::AX_ATTR_FLOWTO_IDS);
+ AddBidirectionalRelations(IA2_RELATION_LABELLED_BY, IA2_RELATION_LABEL_FOR,
+ ui::AX_ATTR_LABELLEDBY_IDS);
+
+ int member_of_id;
+ if (GetIntAttribute(ui::AX_ATTR_MEMBER_OF_ID, &member_of_id))
+ AddRelation(IA2_RELATION_MEMBER_OF, member_of_id);
UpdateRequiredAttributes();
// If this is a web area for a presentational iframe, give it a role of
@@ -3523,10 +3559,13 @@ void BrowserAccessibilityWin::UpdateStep1ComputeWinAttributes() {
}
void BrowserAccessibilityWin::UpdateStep2ComputeHypertext() {
- if (PlatformIsLeaf()) {
- if (IsSimpleTextControl())
+ if (!PlatformChildCount()) {
+ if (IsSimpleTextControl()) {
win_attributes_->hypertext = value();
- else {
+ } else if (IsRichTextControl()) {
+ // We don't want to expose any associated label in IA2 Hypertext.
+ return;
+ } else {
win_attributes_->hypertext = name();
}
@@ -3546,10 +3585,10 @@ void BrowserAccessibilityWin::UpdateStep2ComputeHypertext() {
win_attributes_->hypertext += child->name();
} else {
int32_t char_offset = static_cast<int32_t>(GetText().size());
- int32_t child_id = child->GetId();
+ int32_t child_unique_id = child->unique_id();
int32_t index = hyperlinks().size();
win_attributes_->hyperlink_offset_to_index[char_offset] = index;
- win_attributes_->hyperlinks.push_back(child_id);
+ win_attributes_->hyperlinks.push_back(child_unique_id);
win_attributes_->hypertext += kEmbeddedCharacter;
}
}
@@ -3582,18 +3621,6 @@ void BrowserAccessibilityWin::UpdateStep3FireEvents(bool is_subtree_creation) {
if (ia_state() != old_win_attributes_->ia_state)
FireNativeEvent(EVENT_OBJECT_STATECHANGE);
- // Normally focus events are handled elsewhere, however
- // focus for managed descendants is platform-specific.
- // Fire a focus event if the focused descendant in a multi-select
- // list box changes.
- if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION &&
- (ia_state() & STATE_SYSTEM_FOCUSABLE) &&
- (ia_state() & STATE_SYSTEM_SELECTABLE) &&
- (ia_state() & STATE_SYSTEM_FOCUSED) &&
- !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) {
- FireNativeEvent(EVENT_OBJECT_FOCUS);
- }
-
// Handle selection being added or removed.
bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0;
bool was_selected_before =
@@ -3744,11 +3771,14 @@ std::vector<base::string16> BrowserAccessibilityWin::ComputeTextAttributes()
auto text_style =
static_cast<ui::AXTextStyle>(GetIntAttribute(ui::AX_ATTR_TEXT_STYLE));
if (text_style == ui::AX_TEXT_STYLE_NONE) {
- attributes.push_back(L"font-style:normal");
attributes.push_back(L"font-weight:normal");
+ attributes.push_back(L"font-style:normal");
} else {
- if (text_style & ui::AX_TEXT_STYLE_BOLD)
+ if (text_style & ui::AX_TEXT_STYLE_BOLD) {
attributes.push_back(L"font-weight:bold");
+ } else {
+ attributes.push_back(L"font-weight:normal");
+ }
base::string16 font_style;
if (text_style & ui::AX_TEXT_STYLE_ITALIC)
@@ -3856,6 +3886,60 @@ BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() {
return this;
}
+std::map<int, std::vector<base::string16>>
+BrowserAccessibilityWin::GetSpellingAttributes() const {
+ std::map<int, std::vector<base::string16>> spelling_attributes;
+
+ // It doesn't make sense to expose spelling error information on anything
+ // other than a leaf object, because non-leaf objects do not expose text
+ // directly.
+ if (!PlatformIsLeaf())
+ return spelling_attributes;
+
+ if (IsTextOnlyObject()) {
+ const std::vector<int32_t>& marker_types =
+ GetIntListAttribute(ui::AX_ATTR_MARKER_TYPES);
+ const std::vector<int>& marker_starts =
+ GetIntListAttribute(ui::AX_ATTR_MARKER_STARTS);
+ const std::vector<int>& marker_ends =
+ GetIntListAttribute(ui::AX_ATTR_MARKER_ENDS);
+ for (size_t i = 0; i < marker_types.size(); ++i) {
+ if (!(static_cast<ui::AXMarkerType>(marker_types[i]) &
+ ui::AX_MARKER_TYPE_SPELLING))
+ continue;
+ int start_offset = marker_starts[i];
+ int end_offset = marker_ends[i];
+ std::vector<base::string16> start_attributes;
+ start_attributes.push_back(L"invalid:spelling");
+ std::vector<base::string16> end_attributes;
+ end_attributes.push_back(L"invalid:false");
+ spelling_attributes[start_offset] = start_attributes;
+ spelling_attributes[end_offset] = end_attributes;
+ }
+ }
+
+ if (IsSimpleTextControl()) {
+ int start_offset = 0;
+ for (const BrowserAccessibility* static_text =
+ BrowserAccessibilityManager::NextTextOnlyObject(
+ InternalGetChild(0));
+ static_text; static_text = static_text->GetNextSibling()) {
+ auto text_win = ToBrowserAccessibilityWin(static_text);
+ if (text_win) {
+ std::map<int, std::vector<base::string16>> text_spelling_attributes =
+ text_win->GetSpellingAttributes();
+ for (auto& attribute : text_spelling_attributes) {
+ spelling_attributes[start_offset + attribute.first] =
+ std::move(attribute.second);
+ }
+ start_offset += static_cast<int>(text_win->GetText().length());
+ }
+ }
+ }
+
+ return spelling_attributes;
+}
+
BrowserAccessibilityWin* BrowserAccessibilityWin::GetTargetFromChildID(
const VARIANT& var_id) {
if (var_id.vt != VT_I4)
@@ -3965,7 +4049,8 @@ BrowserAccessibilityWin::GetHyperlinkFromHypertextOffset(int offset) const {
DCHECK_GE(index, 0);
DCHECK_LT(index, static_cast<int32_t>(hyperlinks().size()));
int32_t id = hyperlinks()[index];
- BrowserAccessibilityWin* hyperlink = GetFromID(id);
+ BrowserAccessibilityWin* hyperlink =
+ ToBrowserAccessibilityWin(GetFromUniqueID(id));
if (!hyperlink)
return nullptr;
return hyperlink;
@@ -3976,8 +4061,8 @@ int32_t BrowserAccessibilityWin::GetHyperlinkIndexFromChild(
if (hyperlinks().empty())
return -1;
- auto iterator = std::find(
- hyperlinks().begin(), hyperlinks().end(), child.GetId());
+ auto iterator =
+ std::find(hyperlinks().begin(), hyperlinks().end(), child.unique_id());
if (iterator == hyperlinks().end())
return -1;
@@ -4337,6 +4422,7 @@ LONG BrowserAccessibilityWin::FindStartOfStyle(
}
}
+ NOTREACHED();
return start_offset;
}
@@ -4366,22 +4452,122 @@ bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() {
return false;
}
-void BrowserAccessibilityWin::AddRelations(
- ui::AXIntListAttribute src_attr,
- const base::string16& iaccessiblerelation_type) {
- if (!HasIntListAttribute(src_attr))
+void BrowserAccessibilityWin::AddRelation(const base::string16& relation_type,
+ int target_id) {
+ // Reflexive relations don't need to be exposed through IA2.
+ if (target_id == GetId())
return;
- const std::vector<int32_t>& ids = GetIntListAttribute(src_attr);
- for (size_t i = 0; i < ids.size(); ++i) {
- CComObject<BrowserAccessibilityRelation>* relation;
- HRESULT hr =
- CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation);
- DCHECK(SUCCEEDED(hr));
- relation->AddRef();
- relation->Initialize(this, iaccessiblerelation_type);
- relation->AddTarget(ids[i]);
- relations_.push_back(relation);
+ CComObject<BrowserAccessibilityRelation>* relation;
+ HRESULT hr =
+ CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation);
+ DCHECK(SUCCEEDED(hr));
+ relation->AddRef();
+ relation->Initialize(this, relation_type);
+ relation->AddTarget(target_id);
+ relations_.push_back(relation);
+}
+
+void BrowserAccessibilityWin::AddBidirectionalRelations(
+ const base::string16& relation_type,
+ const base::string16& reverse_relation_type,
+ ui::AXIntListAttribute attribute) {
+ if (!HasIntListAttribute(attribute))
+ return;
+
+ const std::vector<int32_t>& target_ids = GetIntListAttribute(attribute);
+ // Reflexive relations don't need to be exposed through IA2.
+ std::vector<int32_t> filtered_target_ids;
+ int32_t current_id = GetId();
+ std::copy_if(target_ids.begin(), target_ids.end(),
+ std::back_inserter(filtered_target_ids),
+ [current_id](int32_t id) { return id != current_id; });
+ if (filtered_target_ids.empty())
+ return;
+
+ CComObject<BrowserAccessibilityRelation>* relation;
+ HRESULT hr =
+ CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation);
+ DCHECK(SUCCEEDED(hr));
+ relation->AddRef();
+ relation->Initialize(this, relation_type);
+
+ for (int target_id : filtered_target_ids) {
+ BrowserAccessibilityWin* target =
+ GetFromID(static_cast<int32_t>(target_id));
+ if (!target || !target->instance_active())
+ continue;
+ relation->AddTarget(target_id);
+ target->AddRelation(reverse_relation_type, GetId());
+ }
+
+ relations_.push_back(relation);
+}
+
+// Clears all the forward relations from this object to any other object and the
+// associated reverse relations on the other objects, but leaves any reverse
+// relations on this object alone.
+void BrowserAccessibilityWin::ClearOwnRelations() {
+ RemoveBidirectionalRelationsOfType(IA2_RELATION_CONTROLLER_FOR,
+ IA2_RELATION_CONTROLLED_BY);
+ RemoveBidirectionalRelationsOfType(IA2_RELATION_DESCRIBED_BY,
+ IA2_RELATION_DESCRIPTION_FOR);
+ RemoveBidirectionalRelationsOfType(IA2_RELATION_FLOWS_TO,
+ IA2_RELATION_FLOWS_FROM);
+ RemoveBidirectionalRelationsOfType(IA2_RELATION_LABELLED_BY,
+ IA2_RELATION_LABEL_FOR);
+
+ relations_.erase(
+ std::remove_if(relations_.begin(), relations_.end(),
+ [](BrowserAccessibilityRelation* relation) {
+ if (relation->get_type() == IA2_RELATION_MEMBER_OF) {
+ relation->Release();
+ return true;
+ }
+ return false;
+ }),
+ relations_.end());
+}
+
+void BrowserAccessibilityWin::RemoveBidirectionalRelationsOfType(
+ const base::string16& relation_type,
+ const base::string16& reverse_relation_type) {
+ for (auto iter = relations_.begin(); iter != relations_.end();) {
+ BrowserAccessibilityRelation* relation = *iter;
+ DCHECK(relation);
+ if (relation->get_type() == relation_type) {
+ for (int target_id : relation->get_target_ids()) {
+ BrowserAccessibilityWin* target =
+ GetFromID(static_cast<int32_t>(target_id));
+ if (!target || !target->instance_active())
+ continue;
+ DCHECK_NE(target, this);
+ target->RemoveTargetFromRelation(reverse_relation_type, GetId());
+ }
+ iter = relations_.erase(iter);
+ relation->Release();
+ } else {
+ ++iter;
+ }
+ }
+}
+
+void BrowserAccessibilityWin::RemoveTargetFromRelation(
+ const base::string16& relation_type,
+ int target_id) {
+ for (auto iter = relations_.begin(); iter != relations_.end();) {
+ BrowserAccessibilityRelation* relation = *iter;
+ DCHECK(relation);
+ if (relation->get_type() == relation_type) {
+ // If |target_id| is not present, |RemoveTarget| will do nothing.
+ relation->RemoveTarget(target_id);
+ }
+ if (relation->get_target_ids().empty()) {
+ iter = relations_.erase(iter);
+ relation->Release();
+ } else {
+ ++iter;
+ }
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.h b/chromium/content/browser/accessibility/browser_accessibility_win.h
index 3e3d076b4b5..d7bd920a894 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.h
@@ -752,6 +752,11 @@ BrowserAccessibilityWin
// an output parameter to a COM interface, never use it otherwise.
BrowserAccessibilityWin* NewReference();
+ // Returns a list of IA2 attributes indicating the offsets in the text of a
+ // leaf object, such as a text field or static text, where spelling errors are
+ // present.
+ std::map<int, std::vector<base::string16>> GetSpellingAttributes() const;
+
// Many MSAA methods take a var_id parameter indicating that the operation
// should be performed on a particular child ID, rather than this object.
// This method tries to figure out the target object from |var_id| and
@@ -881,10 +886,21 @@ BrowserAccessibilityWin
// or a menu list option with a parent of type menu list popup.
bool IsListBoxOptionOrMenuListOption();
- // Given an int list attribute containing the ids of related elements,
- // add a new IAccessibleRelation for this object with the given type name.
- void AddRelations(ui::AXIntListAttribute src_attr,
- const base::string16& iaccessiblerelation_type);
+ // For adding / removing IA2 relations.
+
+ void AddRelation(const base::string16& relation_type, int target_id);
+ void AddBidirectionalRelations(const base::string16& relation_type,
+ const base::string16& reverse_relation_type,
+ ui::AXIntListAttribute attribute);
+ // Clears all the forward relations from this object to any other object and
+ // the associated reverse relations on the other objects, but leaves any
+ // reverse relations on this object alone.
+ void ClearOwnRelations();
+ void RemoveBidirectionalRelationsOfType(
+ const base::string16& relation_type,
+ const base::string16& reverse_relation_type);
+ void RemoveTargetFromRelation(const base::string16& relation_type,
+ int target_id);
// Updates object attributes of IA2 with html attributes.
void UpdateRequiredAttributes();
@@ -923,8 +939,10 @@ BrowserAccessibilityWin
// |hyperlinks_|.
std::map<int32_t, int32_t> hyperlink_offset_to_index;
- // The id of a BrowserAccessibilityWin for each hyperlink.
- // TODO(nektar): Replace object IDs with child indices.
+ // The unique id of a BrowserAccessibilityWin for each hyperlink.
+ // TODO(nektar): Replace object IDs with child indices if we decide that
+ // we are not implementing IA2 hyperlinks for anything other than IA2
+ // Hypertext.
std::vector<int32_t> hyperlinks;
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index 3f60adb5a40..e10e8195583 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -149,7 +149,7 @@ TEST_F(BrowserAccessibilityTest, TestNoLeaks) {
CountedBrowserAccessibility::reset();
std::unique_ptr<BrowserAccessibilityManager> manager(
BrowserAccessibilityManager::Create(
- MakeAXTreeUpdate(root, button, checkbox), NULL,
+ MakeAXTreeUpdate(root, button, checkbox), nullptr,
new CountedBrowserAccessibilityFactory()));
ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
@@ -160,8 +160,8 @@ TEST_F(BrowserAccessibilityTest, TestNoLeaks) {
// Construct a manager again, and this time use the IAccessible interface
// to get new references to two of the three nodes in the tree.
manager.reset(BrowserAccessibilityManager::Create(
- MakeAXTreeUpdate(root, button, checkbox),
- NULL, new CountedBrowserAccessibilityFactory()));
+ MakeAXTreeUpdate(root, button, checkbox), nullptr,
+ new CountedBrowserAccessibilityFactory()));
ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
IAccessible* root_accessible = ToBrowserAccessibilityWin(manager->GetRoot());
IDispatch* root_iaccessible = NULL;
@@ -209,7 +209,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
CountedBrowserAccessibility::reset();
std::unique_ptr<BrowserAccessibilityManager> manager(
BrowserAccessibilityManager::Create(
- MakeAXTreeUpdate(root, text), NULL,
+ MakeAXTreeUpdate(root, text), nullptr,
new CountedBrowserAccessibilityFactory()));
// Query for the text IAccessible and verify that it returns "old text" as its
@@ -305,7 +305,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
CountedBrowserAccessibility::reset();
std::unique_ptr<BrowserAccessibilityManager> manager(
BrowserAccessibilityManager::Create(
- MakeAXTreeUpdate(root, div, text3, text4), NULL,
+ MakeAXTreeUpdate(root, div, text3, text4), nullptr,
new CountedBrowserAccessibilityFactory()));
ASSERT_EQ(4, CountedBrowserAccessibility::num_instances());
@@ -736,7 +736,7 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
const int32_t enabled_state = 1 << ui::AX_STATE_ENABLED;
std::unique_ptr<BrowserAccessibilityManager> manager(
new BrowserAccessibilityManagerWin(
- BrowserAccessibilityManagerWin::GetEmptyDocument(), NULL,
+ BrowserAccessibilityManagerWin::GetEmptyDocument(), nullptr,
new CountedBrowserAccessibilityFactory()));
// Verify the root is as we expect by default.
@@ -816,7 +816,7 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
TEST_F(BrowserAccessibilityTest, EmptyDocHasUniqueIdWin) {
std::unique_ptr<BrowserAccessibilityManagerWin> manager(
new BrowserAccessibilityManagerWin(
- BrowserAccessibilityManagerWin::GetEmptyDocument(), NULL,
+ BrowserAccessibilityManagerWin::GetEmptyDocument(), nullptr,
new CountedBrowserAccessibilityFactory()));
// Verify the root is as we expect by default.
@@ -1253,11 +1253,11 @@ TEST_F(BrowserAccessibilityTest, TestCaretAndSelectionInSimpleFields) {
// Test get_caretOffset.
HRESULT hr = combo_box_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, caret_offset);
+ EXPECT_EQ(1, caret_offset);
// The caret should be at the end of the selection.
hr = text_field_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(2L, caret_offset);
+ EXPECT_EQ(2, caret_offset);
// Move the focus to the text field.
manager->SetFocusLocallyForTesting(text_field_accessible);
@@ -1267,28 +1267,28 @@ TEST_F(BrowserAccessibilityTest, TestCaretAndSelectionInSimpleFields) {
// The caret should not have moved.
hr = text_field_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(2L, caret_offset);
+ EXPECT_EQ(2, caret_offset);
// Test get_nSelections.
hr = combo_box_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(0L, n_selections);
+ EXPECT_EQ(0, n_selections);
hr = text_field_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, n_selections);
+ EXPECT_EQ(1, n_selections);
// Test get_selection.
hr = combo_box_accessible->get_selection(
0L /* selection_index */, &selection_start, &selection_end);
EXPECT_EQ(E_INVALIDARG, hr); // No selections available.
// Invalid in_args should not modify out_args.
- EXPECT_EQ(-2L, selection_start);
- EXPECT_EQ(-2L, selection_end);
+ EXPECT_EQ(-2, selection_start);
+ EXPECT_EQ(-2, selection_end);
hr = text_field_accessible->get_selection(
0L /* selection_index */, &selection_start, &selection_end);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, selection_start);
- EXPECT_EQ(2L, selection_end);
+ EXPECT_EQ(1, selection_start);
+ EXPECT_EQ(2, selection_end);
manager.reset();
ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
@@ -1365,12 +1365,12 @@ TEST_F(BrowserAccessibilityTest, TestCaretInContentEditables) {
// No selection should be present.
HRESULT hr = div_editable_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(0L, n_selections);
+ EXPECT_EQ(0, n_selections);
// The caret should be on the embedded object character.
hr = div_editable_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(6L, caret_offset);
+ EXPECT_EQ(6, caret_offset);
// Move the focus to the content editable.
manager->SetFocusLocallyForTesting(div_editable_accessible);
@@ -1392,24 +1392,24 @@ TEST_F(BrowserAccessibilityTest, TestCaretInContentEditables) {
// The caret should not have moved.
hr = div_editable_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(0L, n_selections);
+ EXPECT_EQ(0, n_selections);
hr = div_editable_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(6L, caret_offset);
+ EXPECT_EQ(6, caret_offset);
hr = link_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(0L, n_selections);
+ EXPECT_EQ(0, n_selections);
hr = link_text_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(0L, n_selections);
+ EXPECT_EQ(0, n_selections);
hr = link_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, caret_offset);
+ EXPECT_EQ(1, caret_offset);
hr = link_text_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, caret_offset);
+ EXPECT_EQ(1, caret_offset);
manager.reset();
ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
@@ -1424,23 +1424,27 @@ TEST_F(BrowserAccessibilityTest, TestSelectionInContentEditables) {
ui::AXNodeData div_editable;
div_editable.id = 2;
div_editable.role = ui::AX_ROLE_DIV;
- div_editable.state = (1 << ui::AX_STATE_FOCUSABLE);
+ div_editable.state =
+ (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_EDITABLE);
ui::AXNodeData text;
text.id = 3;
text.role = ui::AX_ROLE_STATIC_TEXT;
+ text.state = (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_EDITABLE);
text.SetName("Click ");
ui::AXNodeData link;
link.id = 4;
link.role = ui::AX_ROLE_LINK;
- link.state = (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_LINKED);
+ link.state = (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_EDITABLE) |
+ (1 << ui::AX_STATE_LINKED);
link.SetName("here");
ui::AXNodeData link_text;
link_text.id = 5;
link_text.role = ui::AX_ROLE_STATIC_TEXT;
- link_text.state = (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_LINKED);
+ link_text.state = (1 << ui::AX_STATE_FOCUSABLE) |
+ (1 << ui::AX_STATE_EDITABLE) | (1 << ui::AX_STATE_LINKED);
link_text.SetName("here");
root.child_ids.push_back(2);
@@ -1496,46 +1500,46 @@ TEST_F(BrowserAccessibilityTest, TestSelectionInContentEditables) {
// get_nSelections should work on all objects.
HRESULT hr = div_editable_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, n_selections);
+ EXPECT_EQ(1, n_selections);
hr = text_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, n_selections);
+ EXPECT_EQ(1, n_selections);
hr = link_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, n_selections);
+ EXPECT_EQ(1, n_selections);
hr = link_text_accessible->get_nSelections(&n_selections);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, n_selections);
+ EXPECT_EQ(1, n_selections);
// get_selection should be unaffected by focus placement.
hr = div_editable_accessible->get_selection(
0L /* selection_index */, &selection_start, &selection_end);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, selection_start);
+ EXPECT_EQ(1, selection_start);
// selection_end should be after embedded object character.
- EXPECT_EQ(7L, selection_end);
+ EXPECT_EQ(7, selection_end);
hr = text_accessible->get_selection(
0L /* selection_index */, &selection_start, &selection_end);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, selection_start);
+ EXPECT_EQ(1, selection_start);
// No embedded character on this object, only the first part of the text.
- EXPECT_EQ(6L, selection_end);
+ EXPECT_EQ(6, selection_end);
hr = link_accessible->get_selection(
0L /* selection_index */, &selection_start, &selection_end);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(0L, selection_start);
- EXPECT_EQ(4L, selection_end);
+ EXPECT_EQ(0, selection_start);
+ EXPECT_EQ(4, selection_end);
hr = link_text_accessible->get_selection(
0L /* selection_index */, &selection_start, &selection_end);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(0L, selection_start);
- EXPECT_EQ(4L, selection_end);
+ EXPECT_EQ(0, selection_start);
+ EXPECT_EQ(4, selection_end);
// The caret should be at the focus (the end) of the selection.
hr = div_editable_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(7L, caret_offset);
+ EXPECT_EQ(7, caret_offset);
// Move the focus to the content editable.
manager->SetFocusLocallyForTesting(div_editable_accessible);
@@ -1545,22 +1549,22 @@ TEST_F(BrowserAccessibilityTest, TestSelectionInContentEditables) {
// The caret should not have moved.
hr = div_editable_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(7L, caret_offset);
+ EXPECT_EQ(7, caret_offset);
// The caret offset should reflect the position of the selection's focus in
// any given object.
hr = link_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(4L, caret_offset);
+ EXPECT_EQ(4, caret_offset);
hr = link_text_accessible->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(4L, caret_offset);
+ EXPECT_EQ(4, caret_offset);
hr = div_editable_accessible->get_selection(
0L /* selection_index */, &selection_start, &selection_end);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(1L, selection_start);
- EXPECT_EQ(7L, selection_end);
+ EXPECT_EQ(1, selection_start);
+ EXPECT_EQ(7, selection_end);
manager.reset();
ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
@@ -1720,6 +1724,333 @@ TEST_F(BrowserAccessibilityTest, TestIAccessibleHyperlink) {
EXPECT_EQ(7, end_index);
}
+TEST_F(BrowserAccessibilityTest, TestTextAttributesInContentEditables) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ui::AX_ROLE_ROOT_WEB_AREA;
+ root.state = (1 << ui::AX_STATE_READ_ONLY) | (1 << ui::AX_STATE_FOCUSABLE);
+
+ ui::AXNodeData div_editable;
+ div_editable.id = 2;
+ div_editable.role = ui::AX_ROLE_DIV;
+ div_editable.state =
+ (1 << ui::AX_STATE_EDITABLE) | (1 << ui::AX_STATE_FOCUSABLE);
+ div_editable.AddStringAttribute(ui::AX_ATTR_FONT_FAMILY, "Helvetica");
+
+ ui::AXNodeData text_before;
+ text_before.id = 3;
+ text_before.role = ui::AX_ROLE_STATIC_TEXT;
+ text_before.state = (1 << ui::AX_STATE_EDITABLE);
+ text_before.SetName("Before ");
+ text_before.AddIntAttribute(
+ ui::AX_ATTR_TEXT_STYLE,
+ (ui::AX_TEXT_STYLE_BOLD | ui::AX_TEXT_STYLE_ITALIC));
+
+ ui::AXNodeData link;
+ link.id = 4;
+ link.role = ui::AX_ROLE_LINK;
+ link.state = (1 << ui::AX_STATE_EDITABLE) | (1 << ui::AX_STATE_FOCUSABLE) |
+ (1 << ui::AX_STATE_LINKED);
+ link.SetName("lnk");
+ link.AddIntAttribute(ui::AX_ATTR_TEXT_STYLE, ui::AX_TEXT_STYLE_UNDERLINE);
+
+ ui::AXNodeData link_text;
+ link_text.id = 5;
+ link_text.role = ui::AX_ROLE_STATIC_TEXT;
+ link_text.state = (1 << ui::AX_STATE_EDITABLE) |
+ (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_LINKED);
+ link_text.SetName("lnk");
+ link_text.AddIntAttribute(ui::AX_ATTR_TEXT_STYLE,
+ ui::AX_TEXT_STYLE_UNDERLINE);
+
+ // The name "lnk" is misspelled.
+ std::vector<int32_t> marker_types;
+ marker_types.push_back(static_cast<int32_t>(ui::AX_MARKER_TYPE_SPELLING));
+ std::vector<int32_t> marker_starts;
+ marker_starts.push_back(0);
+ std::vector<int32_t> marker_ends;
+ marker_ends.push_back(3);
+ link_text.AddIntListAttribute(ui::AX_ATTR_MARKER_TYPES, marker_types);
+ link_text.AddIntListAttribute(ui::AX_ATTR_MARKER_STARTS, marker_starts);
+ link_text.AddIntListAttribute(ui::AX_ATTR_MARKER_ENDS, marker_ends);
+
+ ui::AXNodeData text_after;
+ text_after.id = 6;
+ text_after.role = ui::AX_ROLE_STATIC_TEXT;
+ text_after.state = (1 << ui::AX_STATE_EDITABLE);
+ text_after.SetName(" after.");
+ // Leave text style as normal.
+
+ root.child_ids.push_back(div_editable.id);
+ div_editable.child_ids.push_back(text_before.id);
+ div_editable.child_ids.push_back(link.id);
+ div_editable.child_ids.push_back(text_after.id);
+ link.child_ids.push_back(link_text.id);
+
+ ui::AXTreeUpdate update = MakeAXTreeUpdate(root, div_editable, text_before,
+ link, link_text, text_after);
+
+ CountedBrowserAccessibility::reset();
+ std::unique_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ update, nullptr, new CountedBrowserAccessibilityFactory()));
+ ASSERT_EQ(6, CountedBrowserAccessibility::num_instances());
+
+ ASSERT_NE(nullptr, manager->GetRoot());
+ BrowserAccessibilityWin* ax_root =
+ ToBrowserAccessibilityWin(manager->GetRoot());
+ ASSERT_NE(nullptr, ax_root);
+ ASSERT_EQ(1U, ax_root->PlatformChildCount());
+
+ BrowserAccessibilityWin* ax_div =
+ ToBrowserAccessibilityWin(ax_root->PlatformGetChild(0));
+ ASSERT_NE(nullptr, ax_div);
+ ASSERT_EQ(3U, ax_div->PlatformChildCount());
+
+ BrowserAccessibilityWin* ax_before =
+ ToBrowserAccessibilityWin(ax_div->PlatformGetChild(0));
+ ASSERT_NE(nullptr, ax_before);
+ BrowserAccessibilityWin* ax_link =
+ ToBrowserAccessibilityWin(ax_div->PlatformGetChild(1));
+ ASSERT_NE(nullptr, ax_link);
+ ASSERT_EQ(1U, ax_link->PlatformChildCount());
+ BrowserAccessibilityWin* ax_after =
+ ToBrowserAccessibilityWin(ax_div->PlatformGetChild(2));
+ ASSERT_NE(nullptr, ax_after);
+
+ BrowserAccessibilityWin* ax_link_text =
+ ToBrowserAccessibilityWin(ax_link->PlatformGetChild(0));
+ ASSERT_NE(nullptr, ax_link_text);
+
+ HRESULT hr;
+ LONG n_characters, start_offset, end_offset;
+ base::win::ScopedBstr text_attributes;
+
+ ASSERT_HRESULT_SUCCEEDED(ax_root->get_nCharacters(&n_characters));
+ ASSERT_EQ(1, n_characters);
+ ASSERT_HRESULT_SUCCEEDED(ax_div->get_nCharacters(&n_characters));
+ ASSERT_EQ(15, n_characters);
+
+ // Test the style of the root.
+ hr = ax_root->get_attributes(0, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(0, start_offset);
+ EXPECT_EQ(1, end_offset);
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-family:Helvetica"));
+ text_attributes.Reset();
+
+ // Test the style of text_before.
+ for (LONG offset = 0; offset < 7; ++offset) {
+ hr = ax_div->get_attributes(0, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(0, start_offset);
+ EXPECT_EQ(7, end_offset);
+ base::string16 attributes(text_attributes);
+ EXPECT_NE(base::string16::npos, attributes.find(L"font-family:Helvetica"));
+ EXPECT_NE(base::string16::npos, attributes.find(L"font-weight:bold"));
+ EXPECT_NE(base::string16::npos, attributes.find(L"font-style:italic"));
+ text_attributes.Reset();
+ }
+
+ // Test the style of the link.
+ hr = ax_link->get_attributes(0, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(0, start_offset);
+ EXPECT_EQ(3, end_offset);
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-family:Helvetica"));
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-weight:normal"));
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-style:underline"));
+ text_attributes.Reset();
+
+ hr = ax_link_text->get_attributes(2, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(0, start_offset);
+ EXPECT_EQ(3, end_offset);
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-family:Helvetica"));
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-weight:normal"));
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-style:underline"));
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"invalid:spelling"));
+ text_attributes.Reset();
+
+ // Test the style of text_after.
+ for (LONG offset = 8; offset < 15; ++offset) {
+ hr = ax_div->get_attributes(offset, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(8, start_offset);
+ EXPECT_EQ(15, end_offset);
+ base::string16 attributes(text_attributes);
+ EXPECT_NE(base::string16::npos, attributes.find(L"font-family:Helvetica"));
+ EXPECT_NE(base::string16::npos, attributes.find(L"font-weight:normal"));
+ EXPECT_NE(base::string16::npos, attributes.find(L"font-style:normal"));
+ EXPECT_EQ(base::string16::npos, attributes.find(L"invalid:spelling"));
+ text_attributes.Reset();
+ }
+
+ // Test the style of the static text nodes.
+ hr = ax_before->get_attributes(6, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(0, start_offset);
+ EXPECT_EQ(7, end_offset);
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-family:Helvetica"));
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-weight:bold"));
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-style:italic"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"invalid:spelling"));
+ text_attributes.Reset();
+
+ hr = ax_after->get_attributes(6, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(0, start_offset);
+ EXPECT_EQ(7, end_offset);
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-family:Helvetica"));
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-weight:normal"));
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"font-style:normal"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"invalid:spelling"));
+ text_attributes.Reset();
+
+ manager.reset();
+ ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
+}
+
+TEST_F(BrowserAccessibilityTest, TestMisspellingsInSimpleTextFields) {
+ std::string value1("Testing .");
+ // The word "helo" is misspelled.
+ std::string value2("Helo there.");
+
+ LONG value1_length = static_cast<LONG>(value1.length());
+ LONG value2_length = static_cast<LONG>(value2.length());
+ LONG combo_box_value_length = value1_length + value2_length;
+
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ui::AX_ROLE_ROOT_WEB_AREA;
+ root.state = (1 << ui::AX_STATE_READ_ONLY) | (1 << ui::AX_STATE_FOCUSABLE);
+
+ ui::AXNodeData combo_box;
+ combo_box.id = 2;
+ combo_box.role = ui::AX_ROLE_COMBO_BOX;
+ combo_box.state =
+ (1 << ui::AX_STATE_EDITABLE) | (1 << ui::AX_STATE_FOCUSABLE);
+ combo_box.SetValue(value1 + value2);
+
+ ui::AXNodeData combo_box_div;
+ combo_box_div.id = 3;
+ combo_box_div.role = ui::AX_ROLE_DIV;
+ combo_box_div.state = 1 << ui::AX_STATE_EDITABLE;
+
+ ui::AXNodeData static_text1;
+ static_text1.id = 4;
+ static_text1.role = ui::AX_ROLE_STATIC_TEXT;
+ static_text1.state = 1 << ui::AX_STATE_EDITABLE;
+ static_text1.SetName(value1);
+
+ ui::AXNodeData static_text2;
+ static_text2.id = 5;
+ static_text2.role = ui::AX_ROLE_STATIC_TEXT;
+ static_text2.state = 1 << ui::AX_STATE_EDITABLE;
+ static_text2.SetName(value2);
+
+ std::vector<int32_t> marker_types;
+ marker_types.push_back(static_cast<int32_t>(ui::AX_MARKER_TYPE_SPELLING));
+ std::vector<int32_t> marker_starts;
+ marker_starts.push_back(0);
+ std::vector<int32_t> marker_ends;
+ marker_ends.push_back(4);
+ static_text2.AddIntListAttribute(ui::AX_ATTR_MARKER_TYPES, marker_types);
+ static_text2.AddIntListAttribute(ui::AX_ATTR_MARKER_STARTS, marker_starts);
+ static_text2.AddIntListAttribute(ui::AX_ATTR_MARKER_ENDS, marker_ends);
+
+ root.child_ids.push_back(combo_box.id);
+ combo_box.child_ids.push_back(combo_box_div.id);
+ combo_box_div.child_ids.push_back(static_text1.id);
+ combo_box_div.child_ids.push_back(static_text2.id);
+
+ CountedBrowserAccessibility::reset();
+ std::unique_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, combo_box, combo_box_div, static_text1,
+ static_text2),
+ nullptr, new CountedBrowserAccessibilityFactory()));
+ ASSERT_EQ(5, CountedBrowserAccessibility::num_instances());
+
+ ASSERT_NE(nullptr, manager->GetRoot());
+ BrowserAccessibilityWin* ax_root =
+ ToBrowserAccessibilityWin(manager->GetRoot());
+ ASSERT_NE(nullptr, ax_root);
+ ASSERT_EQ(1U, ax_root->PlatformChildCount());
+
+ BrowserAccessibilityWin* ax_combo_box =
+ ToBrowserAccessibilityWin(ax_root->PlatformGetChild(0));
+ ASSERT_NE(nullptr, ax_combo_box);
+ ASSERT_EQ(0U, ax_combo_box->PlatformChildCount());
+
+ HRESULT hr;
+ LONG start_offset, end_offset;
+ base::win::ScopedBstr text_attributes;
+
+ // Ensure that the first part of the value is not marked misspelled.
+ for (LONG offset = 0; offset < value1_length; ++offset) {
+ hr = ax_combo_box->get_attributes(offset, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(0, start_offset);
+ EXPECT_EQ(value1_length, end_offset);
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"invalid:spelling"));
+ text_attributes.Reset();
+ }
+
+ // Ensure that "helo" is marked misspelled.
+ for (LONG offset = value1_length; offset < value1_length + 4; ++offset) {
+ hr = ax_combo_box->get_attributes(offset, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(value1_length, start_offset);
+ EXPECT_EQ(value1_length + 4, end_offset);
+ EXPECT_NE(base::string16::npos,
+ base::string16(text_attributes).find(L"invalid:spelling"));
+ text_attributes.Reset();
+ }
+
+ // Ensure that the last part of the value is not marked misspelled.
+ for (LONG offset = value1_length + 4; offset < combo_box_value_length;
+ ++offset) {
+ hr = ax_combo_box->get_attributes(offset, &start_offset, &end_offset,
+ text_attributes.Receive());
+ EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(value1_length + 4, start_offset);
+ EXPECT_EQ(combo_box_value_length, end_offset);
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"invalid:spelling"));
+ text_attributes.Reset();
+ }
+
+ manager.reset();
+ ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
+}
+
TEST_F(BrowserAccessibilityTest, TestDeepestFirstLastChild) {
ui::AXNodeData root;
root.id = 1;
@@ -2009,4 +2340,136 @@ TEST_F(BrowserAccessibilityTest, AccChildOnlyReturnsDescendants) {
child_unique_id_variant, result.Receive()));
}
+TEST_F(BrowserAccessibilityTest, TestIAccessible2Relations) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ui::AX_ROLE_ROOT_WEB_AREA;
+ // Reflexive relations should be ignored.
+ std::vector<int32_t> describedby_ids = {1, 2, 3};
+ root.AddIntListAttribute(ui::AX_ATTR_DESCRIBEDBY_IDS, describedby_ids);
+
+ ui::AXNodeData child1;
+ child1.id = 2;
+ child1.role = ui::AX_ROLE_STATIC_TEXT;
+ root.child_ids.push_back(2);
+
+ ui::AXNodeData child2;
+ child2.id = 3;
+ child2.role = ui::AX_ROLE_STATIC_TEXT;
+ root.child_ids.push_back(3);
+
+ std::unique_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, child1, child2), nullptr,
+ new CountedBrowserAccessibilityFactory()));
+
+ BrowserAccessibilityWin* ax_root =
+ ToBrowserAccessibilityWin(manager->GetRoot());
+ ASSERT_NE(nullptr, ax_root);
+ BrowserAccessibilityWin* ax_child1 =
+ ToBrowserAccessibilityWin(ax_root->PlatformGetChild(0));
+ ASSERT_NE(nullptr, ax_child1);
+ BrowserAccessibilityWin* ax_child2 =
+ ToBrowserAccessibilityWin(ax_root->PlatformGetChild(1));
+ ASSERT_NE(nullptr, ax_child2);
+
+ LONG n_relations = 0;
+ LONG n_targets = 0;
+ LONG unique_id = 0;
+ base::win::ScopedBstr relation_type;
+ base::win::ScopedComPtr<IAccessibleRelation> describedby_relation;
+ base::win::ScopedComPtr<IAccessibleRelation> description_for_relation;
+ base::win::ScopedComPtr<IUnknown> target;
+ base::win::ScopedComPtr<IAccessible2> ax_target;
+
+ EXPECT_HRESULT_SUCCEEDED(ax_root->get_nRelations(&n_relations));
+ EXPECT_EQ(1, n_relations);
+
+ EXPECT_HRESULT_SUCCEEDED(
+ ax_root->get_relation(0, describedby_relation.Receive()));
+ EXPECT_HRESULT_SUCCEEDED(
+ describedby_relation->get_relationType(relation_type.Receive()));
+ EXPECT_EQ(L"describedBy", base::string16(relation_type));
+ relation_type.Reset();
+
+ EXPECT_HRESULT_SUCCEEDED(describedby_relation->get_nTargets(&n_targets));
+ EXPECT_EQ(2, n_targets);
+
+ EXPECT_HRESULT_SUCCEEDED(
+ describedby_relation->get_target(0, target.Receive()));
+ target.QueryInterface(ax_target.Receive());
+ EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
+ EXPECT_EQ(-ax_child1->unique_id(), unique_id);
+ ax_target.Release();
+ target.Release();
+
+ EXPECT_HRESULT_SUCCEEDED(
+ describedby_relation->get_target(1, target.Receive()));
+ target.QueryInterface(ax_target.Receive());
+ EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
+ EXPECT_EQ(-ax_child2->unique_id(), unique_id);
+ ax_target.Release();
+ target.Release();
+ describedby_relation.Release();
+
+ // Test the reverse relations.
+ EXPECT_HRESULT_SUCCEEDED(ax_child1->get_nRelations(&n_relations));
+ EXPECT_EQ(1, n_relations);
+
+ EXPECT_HRESULT_SUCCEEDED(
+ ax_child1->get_relation(0, description_for_relation.Receive()));
+ EXPECT_HRESULT_SUCCEEDED(
+ description_for_relation->get_relationType(relation_type.Receive()));
+ EXPECT_EQ(L"descriptionFor", base::string16(relation_type));
+ relation_type.Reset();
+
+ EXPECT_HRESULT_SUCCEEDED(description_for_relation->get_nTargets(&n_targets));
+ EXPECT_EQ(1, n_targets);
+
+ EXPECT_HRESULT_SUCCEEDED(
+ description_for_relation->get_target(0, target.Receive()));
+ target.QueryInterface(ax_target.Receive());
+ EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
+ EXPECT_EQ(-ax_root->unique_id(), unique_id);
+ ax_target.Release();
+ target.Release();
+ description_for_relation.Release();
+
+ EXPECT_HRESULT_SUCCEEDED(ax_child2->get_nRelations(&n_relations));
+ EXPECT_EQ(1, n_relations);
+
+ EXPECT_HRESULT_SUCCEEDED(
+ ax_child2->get_relation(0, description_for_relation.Receive()));
+ EXPECT_HRESULT_SUCCEEDED(
+ description_for_relation->get_relationType(relation_type.Receive()));
+ EXPECT_EQ(L"descriptionFor", base::string16(relation_type));
+ relation_type.Reset();
+
+ EXPECT_HRESULT_SUCCEEDED(description_for_relation->get_nTargets(&n_targets));
+ EXPECT_EQ(1, n_targets);
+
+ EXPECT_HRESULT_SUCCEEDED(
+ description_for_relation->get_target(0, target.Receive()));
+ target.QueryInterface(ax_target.Receive());
+ EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
+ EXPECT_EQ(-ax_root->unique_id(), unique_id);
+ ax_target.Release();
+ target.Release();
+
+ // Try adding one more relation.
+ std::vector<int32_t> labelledby_ids = {3};
+ child1.AddIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS, labelledby_ids);
+ AXEventNotificationDetails event;
+ event.event_type = ui::AX_EVENT_ARIA_ATTRIBUTE_CHANGED;
+ event.update.nodes.push_back(child1);
+ event.id = child1.id;
+ std::vector<AXEventNotificationDetails> events = {event};
+ manager->OnAccessibilityEvents(events);
+
+ EXPECT_HRESULT_SUCCEEDED(ax_child1->get_nRelations(&n_relations));
+ EXPECT_EQ(2, n_relations);
+ EXPECT_HRESULT_SUCCEEDED(ax_child2->get_nRelations(&n_relations));
+ EXPECT_EQ(2, n_relations);
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index fb5526bc3bc..dc3e99ea96d 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -47,7 +47,9 @@ class CrossPlatformAccessibilityBrowserTest : public ContentBrowserTest {
const ui::AXTree& GetAXTree(
AccessibilityMode accessibility_mode = AccessibilityModeComplete) {
AccessibilityNotificationWaiter waiter(
- shell(), accessibility_mode, ui::AX_EVENT_LAYOUT_COMPLETE);
+ shell()->web_contents(),
+ accessibility_mode,
+ ui::AX_EVENT_LAYOUT_COMPLETE);
waiter.WaitForNotification();
return waiter.GetAXTree();
}
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 0c096817522..d4eab1b3874 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -242,7 +242,7 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
GURL url(embedded_test_server()->GetURL(
"/" + std::string(file_dir) + "/" + file_path.BaseName().MaybeAsASCII()));
AccessibilityNotificationWaiter accessibility_waiter(
- shell(),
+ shell()->web_contents(),
AccessibilityModeComplete,
ui::AX_EVENT_LOAD_COMPLETE);
NavigateToURL(shell(), url);
@@ -267,12 +267,10 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
// We won't get the correct coordinate transformations for
// out-of-process iframes until each frame's surface is ready.
RenderFrameHostImpl* current_frame_host = node->current_frame_host();
- if (!current_frame_host)
+ if (!current_frame_host || !current_frame_host->is_local_root())
continue;
- RenderWidgetHostImpl* rwh = current_frame_host->GetRenderWidgetHost();
- if (!rwh)
- continue;
- RenderWidgetHostViewBase* rwhv = rwh->GetView();
+ RenderWidgetHostViewBase* rwhv =
+ static_cast<RenderWidgetHostViewBase*>(current_frame_host->GetView());
if (rwhv && rwhv->IsChildFrameForTesting()) {
SurfaceHitTestReadyNotifier notifier(
static_cast<RenderWidgetHostViewChildFrame*>(rwhv));
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index 082fc2adc9f..813daa564dd 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -89,7 +89,7 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
// a result of this function.
std::unique_ptr<AccessibilityNotificationWaiter> waiter;
waiter.reset(new AccessibilityNotificationWaiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_NONE));
+ shell()->web_contents(), AccessibilityModeComplete, ui::AX_EVENT_NONE));
web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
@@ -104,7 +104,7 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
// sentinel by calling AccessibilityHitTest and waiting for a HOVER
// event in response.
waiter.reset(new AccessibilityNotificationWaiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_HOVER));
+ shell()->web_contents(), AccessibilityModeComplete, ui::AX_EVENT_HOVER));
BrowserAccessibilityManager* manager =
web_contents->GetRootBrowserAccessibilityManager();
manager->delegate()->AccessibilityHitTest(gfx::Point(0, 0));
@@ -150,7 +150,36 @@ void DumpAccessibilityEventsTest::RunEventTest(
}
// TODO(dmazzoni): port these tests to run on all platforms.
-#if defined(OS_WIN) || defined(OS_MACOSX)
+// TODO(crbug.com/617146): All tests flaky on Windows 8.
+#if /*defined(OS_WIN) ||*/ defined(OS_MACOSX)
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaComboBoxCollapse) {
+ RunEventTest(FILE_PATH_LITERAL("aria-combo-box-collapse.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaComboBoxExpand) {
+ RunEventTest(FILE_PATH_LITERAL("aria-combo-box-expand.html"));
+}
+
+#if defined(OS_MACOSX)
+// crbug.com/615411
+#define MAYBE_AccessibilityEventsAriaComboBoxFocus \
+ DISABLED_AccessibilityEventsAriaComboBoxFocus
+#else
+#define MAYBE_AccessibilityEventsAriaComboBoxFocus \
+ AccessibilityEventsAriaComboBoxFocus
+#endif
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ MAYBE_AccessibilityEventsAriaComboBoxFocus) {
+ RunEventTest(FILE_PATH_LITERAL("aria-combo-box-focus.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaComboBoxNext) {
+ RunEventTest(FILE_PATH_LITERAL("aria-combo-box-next.html"));
+}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
AccessibilityEventsAddAlert) {
@@ -228,17 +257,42 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
// Flaky on Windows: http://crbug.com/486861
// Flaky on Mac: http://crbug.com/588271
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
- DISABLED_AccessibilityEventsListboxNext) {
+ AccessibilityEventsListboxNext) {
RunEventTest(FILE_PATH_LITERAL("listbox-next.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsMenuListCollapse) {
+ RunEventTest(FILE_PATH_LITERAL("menulist-collapse.html"));
+}
+
+#if defined(OS_MACOSX)
+// crbug.com/615411
+#define MAYBE_AccessibilityEventsMenuListExpand \
+ DISABLED_AccessibilityEventsMenuListExpand
+#else
+#define MAYBE_AccessibilityEventsMenuListExpand \
+ AccessibilityEventsMenuListExpand
+#endif
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ MAYBE_AccessibilityEventsMenuListExpand) {
+ RunEventTest(FILE_PATH_LITERAL("menulist-expand.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
AccessibilityEventsMenuListFocus) {
RunEventTest(FILE_PATH_LITERAL("menulist-focus.html"));
}
+#if defined(OS_MACOSX)
+// crbug.com/615411
+#define MAYBE_AccessibilityEventsMenuListNext \
+ DISABLED_AccessibilityEventsMenuListNext
+#else
+#define MAYBE_AccessibilityEventsMenuListNext AccessibilityEventsMenuListNext
+#endif
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
- AccessibilityEventsMenuListNext) {
+ MAYBE_AccessibilityEventsMenuListNext) {
RunEventTest(FILE_PATH_LITERAL("menulist-next.html"));
}
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 42cd98f8182..d36cd388636 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -798,6 +798,11 @@ IN_PROC_BROWSER_TEST_F(
FILE_PATH_LITERAL("contenteditable-with-embedded-contenteditables.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityContenteditableWithNoDescendants) {
+ RunHtmlTest(FILE_PATH_LITERAL("contenteditable-with-no-descendants.html"));
+}
+
#if defined(OS_ANDROID)
// Flaky failures: http://crbug.com/515053.
#define MAYBE_AccessibilityEm DISABLED_AccessibilityEm
@@ -879,8 +884,14 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("iframe-coordinates-cross-process.html"));
}
+// Flaky on Win7. http://crbug.com/610744
+#ifdef OS_WIN
+#define MAYBE_AccessibilityIframePresentational DISABLED_AccessibilityIframePresentational
+#else
+#define MAYBE_AccessibilityIframePresentational AccessibilityIframePresentational
+#endif
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityIframePresentational) {
+ MAYBE_AccessibilityIframePresentational) {
RunHtmlTest(FILE_PATH_LITERAL("iframe-presentational.html"));
}
diff --git a/chromium/content/browser/accessibility/hit_testing_browsertest.cc b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
index 7610f73da1d..f1e6d9e3179 100644
--- a/chromium/content/browser/accessibility/hit_testing_browsertest.cc
+++ b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
@@ -21,6 +21,7 @@
#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/shell/browser/shell.h"
@@ -30,23 +31,6 @@
namespace content {
-namespace {
-
-bool AXTreeContainsNodeWithName(BrowserAccessibility* node,
- const std::string& name) {
- if (node->GetStringAttribute(ui::AX_ATTR_NAME) == name)
- return true;
-
- for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
- if (AXTreeContainsNodeWithName(node->PlatformGetChild(i), name))
- return true;
- }
-
- return false;
-}
-
-} // namespace
-
class AccessibilityHitTestingBrowserTest : public ContentBrowserTest {
public:
AccessibilityHitTestingBrowserTest() {}
@@ -61,7 +45,7 @@ class AccessibilityHitTestingBrowserTest : public ContentBrowserTest {
web_contents->GetRootBrowserAccessibilityManager();
AccessibilityNotificationWaiter hover_waiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_HOVER);
+ 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);
@@ -82,7 +66,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
// Load the page.
- AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete,
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_LOAD_COMPLETE);
const char url_str[] =
"data:text/html,"
@@ -110,27 +95,18 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete,
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ AccessibilityModeComplete,
ui::AX_EVENT_LOAD_COMPLETE);
GURL url(embedded_test_server()->GetURL(
"/accessibility/html/iframe-coordinates.html"));
NavigateToURL(shell(), url);
waiter.WaitForNotification();
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- FrameTree* frame_tree = web_contents->GetFrameTree();
- BrowserAccessibilityManager* manager =
- web_contents->GetRootBrowserAccessibilityManager();
- BrowserAccessibility* root = manager->GetRoot();
- while (!AXTreeContainsNodeWithName(root, "Ordinary Button") ||
- !AXTreeContainsNodeWithName(root, "Scrolled Button")) {
- AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete,
- ui::AX_EVENT_NONE);
- for (FrameTreeNode* node : frame_tree->Nodes())
- waiter.ListenToAdditionalFrame(node->current_frame_host());
- waiter.WaitForNotification();
- }
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(), "Ordinary Button");
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(), "Scrolled Button");
// Send a series of hit test requests, and for each one
// wait for the hover event in response, verifying we hit the
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 1a0239eb58b..4923e25ef9b 100644
--- a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
+++ b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
@@ -103,8 +103,7 @@ BrowserAccessibility* OneShotAccessibilityTreeSearch::GetMatchAtIndex(
return matches_[index];
}
-void OneShotAccessibilityTreeSearch::Search()
-{
+void OneShotAccessibilityTreeSearch::Search() {
if (immediate_descendants_only_) {
SearchByIteratingOverChildren();
} else {
diff --git a/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc b/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
index 75833ff9aa8..0909e3a9da4 100644
--- a/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
@@ -21,6 +21,7 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
@@ -43,23 +44,6 @@
namespace content {
-namespace {
-
-// Searches recursively and returns true if any node's accessible name
-// is equal to the given text.
-bool AccessibilityTreeContainsText(BrowserAccessibility* node,
- const std::string& text) {
- if (node->GetStringAttribute(ui::AX_ATTR_NAME) == text)
- return true;
- for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
- if (AccessibilityTreeContainsText(node->PlatformGetChild(i), text))
- return true;
- }
- return false;
-}
-
-} // namespace
-
class MAYBE_SitePerProcessAccessibilityBrowserTest
: public SitePerProcessBrowserTest {
public:
@@ -83,34 +67,6 @@ class MAYBE_SitePerProcessAccessibilityBrowserTest
// Wait until the iframe completes the swap.
deleted_observer.WaitUntilDeleted();
}
-
- // This is intended to be a robust way to assert that the accessibility
- // tree eventually gets into the correct state, without worrying about
- // the exact ordering of events received while getting there.
- //
- // Searches the accessibility tree to see if any node's accessible name
- // is equal to the given text. If not, sets up a notification waiter
- // that listens for any accessibility event in any frame, and checks again
- // after each event. Keeps looping until the text is found (or the
- // test times out).
- void WaitForAccessibilityTreeToContainText(const std::string& text) {
- RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
- shell()->web_contents()->GetMainFrame());
- BrowserAccessibilityManager* main_frame_manager =
- main_frame->browser_accessibility_manager();
- FrameTree* frame_tree =
- static_cast<WebContentsImpl*>(shell()->web_contents())->GetFrameTree();
- while (!AccessibilityTreeContainsText(
- main_frame_manager->GetRoot(), text)) {
- AccessibilityNotificationWaiter accessibility_waiter(main_frame,
- ui::AX_EVENT_NONE);
- for (FrameTreeNode* node : frame_tree->Nodes())
- accessibility_waiter.ListenToAdditionalFrame(
- node->current_frame_host());
-
- accessibility_waiter.WaitForNotification();
- }
- }
};
IN_PROC_BROWSER_TEST_F(MAYBE_SitePerProcessAccessibilityBrowserTest,
@@ -134,7 +90,9 @@ IN_PROC_BROWSER_TEST_F(MAYBE_SitePerProcessAccessibilityBrowserTest,
// Load cross-site page into iframe and wait for text from that
// page to appear in the accessibility tree.
LoadCrossSitePageIntoFrame(child, "/title2.html", "foo.com");
- WaitForAccessibilityTreeToContainText("Title Of Awesomeness");
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(),
+ "Title Of Awesomeness");
RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
shell()->web_contents()->GetMainFrame());
@@ -194,13 +152,17 @@ IN_PROC_BROWSER_TEST_F(MAYBE_SitePerProcessAccessibilityBrowserTest,
// page to appear in the accessibility tree.
FrameTreeNode* child = root->child_at(0);
LoadCrossSitePageIntoFrame(child, "/title1.html", "foo.com");
- WaitForAccessibilityTreeToContainText("This page has no title.");
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(),
+ "This page has no title.");
// Load second cross-site page into iframe and wait for text from that
// page to appear in the accessibility tree. If this succeeds and doesn't
// time out, the test passes.
LoadCrossSitePageIntoFrame(child, "/title2.html", "bar.com");
- WaitForAccessibilityTreeToContainText("Title Of Awesomeness");
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(),
+ "Title Of Awesomeness");
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc b/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
index 89bc0db4d06..60a4639c360 100644
--- a/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
+++ b/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
@@ -11,6 +11,8 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
@@ -24,6 +26,34 @@ class TouchAccessibilityBrowserTest : public ContentBrowserTest {
public:
TouchAccessibilityBrowserTest() {}
+ protected:
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ SetupCrossSiteRedirector(embedded_test_server());
+ }
+
+ void NavigateToUrlAndWaitForAccessibilityTree(const GURL& url) {
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+ }
+
+ void SendTouchExplorationEvent(int x, int y) {
+ aura::Window* window = shell()->web_contents()->GetContentNativeView();
+ ui::EventProcessor* dispatcher = window->GetHost()->event_processor();
+ gfx::Rect bounds = window->GetBoundsInRootWindow();
+ gfx::Point location(bounds.x() + x, bounds.y() + y);
+ int flags = ui::EF_TOUCH_ACCESSIBILITY;
+ std::unique_ptr<ui::Event> mouse_move_event(
+ new ui::MouseEvent(ui::ET_MOUSE_MOVED, location, location,
+ ui::EventTimeForNow(), flags, 0));
+ ignore_result(dispatcher->OnEventFromSource(mouse_move_event.get()));
+ }
+
DISALLOW_COPY_AND_ASSIGN(TouchAccessibilityBrowserTest);
};
@@ -50,12 +80,7 @@ IN_PROC_BROWSER_TEST_F(TouchAccessibilityBrowserTest,
}
html_url += "</table></body>";
- // Navigate to the url and load the accessibility tree.
- AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
- GURL url(html_url);
- NavigateToURL(shell(), url);
- waiter.WaitForNotification();
+ NavigateToUrlAndWaitForAccessibilityTree(GURL(html_url));
// Get the BrowserAccessibilityManager.
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
@@ -67,34 +92,21 @@ IN_PROC_BROWSER_TEST_F(TouchAccessibilityBrowserTest,
// Loop over all of the cells in the table. For each one, send a simulated
// touch exploration event in the center of that cell, and assert that we
// get an accessibility hover event fired in the correct cell.
- AccessibilityNotificationWaiter waiter2(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_HOVER);
- aura::Window* window = web_contents->GetContentNativeView();
- ui::EventProcessor* dispatcher = window->GetHost()->event_processor();
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), AccessibilityModeComplete, ui::AX_EVENT_HOVER);
for (int row = 0; row < 5; ++row) {
for (int col = 0; col < 7; ++col) {
std::string expected_cell_text = base::IntToString(row * 7 + col);
VLOG(1) << "Sending event in row " << row << " col " << col
<< " with text " << expected_cell_text;
-
- // Send a touch exploration event to the center of the particular grid
- // cell. A touch exploration event is just a mouse move event with
- // the ui::EF_TOUCH_ACCESSIBILITY flag set.
- gfx::Rect bounds = window->GetBoundsInRootWindow();
- gfx::Point location(bounds.x() + 50 * col + 25,
- bounds.y() + 50 * row + 25);
- int flags = ui::EF_TOUCH_ACCESSIBILITY;
- std::unique_ptr<ui::Event> mouse_move_event(
- new ui::MouseEvent(ui::ET_MOUSE_MOVED, location, location,
- ui::EventTimeForNow(), flags, 0));
- ignore_result(dispatcher->OnEventFromSource(mouse_move_event.get()));
+ SendTouchExplorationEvent(50 * col + 25, 50 * row + 25);
// Wait until we get a hover event in the expected grid cell.
// Tolerate additional events, keep looping until we get the expected one.
std::string cell_text;
do {
- waiter2.WaitForNotification();
- int target_id = waiter2.event_target_id();
+ waiter.WaitForNotification();
+ int target_id = waiter.event_target_id();
BrowserAccessibility* hit = manager->GetFromID(target_id);
BrowserAccessibility* child = hit->PlatformGetChild(0);
ASSERT_NE(nullptr, child);
@@ -105,4 +117,68 @@ IN_PROC_BROWSER_TEST_F(TouchAccessibilityBrowserTest,
}
}
+IN_PROC_BROWSER_TEST_F(TouchAccessibilityBrowserTest,
+ TouchExplorationInIframe) {
+ NavigateToUrlAndWaitForAccessibilityTree(
+ embedded_test_server()->GetURL(
+ "/accessibility/html/iframe-coordinates.html"));
+
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(), "Ordinary Button");
+
+ // Get the BrowserAccessibilityManager for the first child frame.
+ RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ RenderFrameHostImpl* child_frame =
+ main_frame->frame_tree_node()->child_at(0)->current_frame_host();
+ BrowserAccessibilityManager* child_manager =
+ child_frame->GetOrCreateBrowserAccessibilityManager();
+ ASSERT_NE(nullptr, child_manager);
+
+ // Send a touch exploration event to the button in the first iframe.
+ // A touch exploration event is just a mouse move event with
+ // the ui::EF_TOUCH_ACCESSIBILITY flag set.
+ AccessibilityNotificationWaiter waiter(
+ child_frame, ui::AX_EVENT_HOVER);
+ SendTouchExplorationEvent(50, 350);
+ waiter.WaitForNotification();
+ int target_id = waiter.event_target_id();
+ BrowserAccessibility* hit = child_manager->GetFromID(target_id);
+ EXPECT_EQ(ui::AX_ROLE_BUTTON, hit->GetData().role);
+ std::string text = hit->GetData().GetStringAttribute(ui::AX_ATTR_NAME);
+ EXPECT_EQ("Ordinary Button", text);
+}
+
+IN_PROC_BROWSER_TEST_F(TouchAccessibilityBrowserTest,
+ TouchExplorationInCrossSiteIframe) {
+ NavigateToUrlAndWaitForAccessibilityTree(
+ embedded_test_server()->GetURL(
+ "/accessibility/html/iframe-coordinates-cross-process.html"));
+
+ WaitForAccessibilityTreeToContainNodeWithName(
+ shell()->web_contents(), "Ordinary Button");
+
+ // Get the BrowserAccessibilityManager for the first child frame.
+ RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ RenderFrameHostImpl* child_frame =
+ main_frame->frame_tree_node()->child_at(0)->current_frame_host();
+ BrowserAccessibilityManager* child_manager =
+ child_frame->GetOrCreateBrowserAccessibilityManager();
+ ASSERT_NE(nullptr, child_manager);
+
+ // Send a touch exploration event to the button in the first iframe.
+ // A touch exploration event is just a mouse move event with
+ // the ui::EF_TOUCH_ACCESSIBILITY flag set.
+ AccessibilityNotificationWaiter waiter(
+ child_frame, ui::AX_EVENT_HOVER);
+ SendTouchExplorationEvent(50, 350);
+ waiter.WaitForNotification();
+ int target_id = waiter.event_target_id();
+ BrowserAccessibility* hit = child_manager->GetFromID(target_id);
+ EXPECT_EQ(ui::AX_ROLE_BUTTON, hit->GetData().role);
+ std::string text = hit->GetData().GetStringAttribute(ui::AX_ATTR_NAME);
+ EXPECT_EQ("Ordinary Button", text);
+}
+
} // namespace content
diff --git a/chromium/content/browser/android/browser_surface_texture_manager.cc b/chromium/content/browser/android/browser_surface_texture_manager.cc
index 476ebf2ab02..63178244a52 100644
--- a/chromium/content/browser/android/browser_surface_texture_manager.cc
+++ b/chromium/content/browser/android/browser_surface_texture_manager.cc
@@ -27,7 +27,7 @@ BrowserSurfaceTextureManager* BrowserSurfaceTextureManager::GetInstance() {
void BrowserSurfaceTextureManager::RegisterSurfaceTexture(
int surface_texture_id,
int client_id,
- gfx::SurfaceTexture* surface_texture) {
+ gl::SurfaceTexture* surface_texture) {
content::CreateSurfaceTextureSurface(
surface_texture_id, client_id, surface_texture);
}
@@ -41,10 +41,9 @@ void BrowserSurfaceTextureManager::UnregisterSurfaceTexture(
gfx::AcceleratedWidget
BrowserSurfaceTextureManager::AcquireNativeWidgetForSurfaceTexture(
int surface_texture_id) {
- gfx::ScopedJavaSurface surface(
- content::GetSurfaceTextureSurface(
- surface_texture_id,
- BrowserGpuChannelHostFactory::instance()->GetGpuChannelId()));
+ gl::ScopedJavaSurface surface(content::GetSurfaceTextureSurface(
+ surface_texture_id,
+ BrowserGpuChannelHostFactory::instance()->GetGpuChannelId()));
if (surface.j_surface().is_null())
return NULL;
diff --git a/chromium/content/browser/android/browser_surface_texture_manager.h b/chromium/content/browser/android/browser_surface_texture_manager.h
index 4529c9ce8c7..9e3ac010f73 100644
--- a/chromium/content/browser/android/browser_surface_texture_manager.h
+++ b/chromium/content/browser/android/browser_surface_texture_manager.h
@@ -20,7 +20,7 @@ class CONTENT_EXPORT BrowserSurfaceTextureManager
// Overridden from SurfaceTextureManager:
void RegisterSurfaceTexture(int surface_texture_id,
int client_id,
- gfx::SurfaceTexture* surface_texture) override;
+ gl::SurfaceTexture* surface_texture) override;
void UnregisterSurfaceTexture(int surface_texture_id, int client_id) override;
gfx::AcceleratedWidget AcquireNativeWidgetForSurfaceTexture(
int surface_texture_id) override;
diff --git a/chromium/content/browser/android/child_process_launcher_android.cc b/chromium/content/browser/android/child_process_launcher_android.cc
index ef312a27e7b..f7e8437a8e4 100644
--- a/chromium/content/browser/android/child_process_launcher_android.cc
+++ b/chromium/content/browser/android/child_process_launcher_android.cc
@@ -84,7 +84,7 @@ static void SetSurfacePeer(
}
if (player != player_manager->GetFullscreenPlayer()) {
- gfx::ScopedJavaSurface scoped_surface(surface);
+ gl::ScopedJavaSurface scoped_surface(surface);
player->SetVideoSurface(std::move(scoped_surface));
}
}
@@ -247,16 +247,16 @@ void UnregisterViewSurface(int surface_id) {
Java_ChildProcessLauncher_unregisterViewSurface(env, surface_id);
}
-gfx::ScopedJavaSurface GetViewSurface(int surface_id) {
+gl::ScopedJavaSurface GetViewSurface(int surface_id) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
- return gfx::ScopedJavaSurface::AcquireExternalSurface(
+ return gl::ScopedJavaSurface::AcquireExternalSurface(
Java_ChildProcessLauncher_getViewSurface(env, surface_id).obj());
}
void CreateSurfaceTextureSurface(int surface_texture_id,
int client_id,
- gfx::SurfaceTexture* surface_texture) {
+ gl::SurfaceTexture* surface_texture) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
Java_ChildProcessLauncher_createSurfaceTextureSurface(
@@ -273,13 +273,14 @@ void DestroySurfaceTextureSurface(int surface_texture_id, int client_id) {
env, surface_texture_id, client_id);
}
-gfx::ScopedJavaSurface GetSurfaceTextureSurface(int surface_texture_id,
- int client_id) {
+gl::ScopedJavaSurface GetSurfaceTextureSurface(int surface_texture_id,
+ int client_id) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
- return gfx::ScopedJavaSurface::AcquireExternalSurface(
+ return gl::ScopedJavaSurface::AcquireExternalSurface(
Java_ChildProcessLauncher_getSurfaceTextureSurface(
- env, surface_texture_id, client_id).obj());
+ env, surface_texture_id, client_id)
+ .obj());
}
jboolean IsSingleProcess(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
diff --git a/chromium/content/browser/android/child_process_launcher_android.h b/chromium/content/browser/android/child_process_launcher_android.h
index c9ef4fd9f42..bf1584fedb4 100644
--- a/chromium/content/browser/android/child_process_launcher_android.h
+++ b/chromium/content/browser/android/child_process_launcher_android.h
@@ -48,16 +48,16 @@ void RegisterViewSurface(int surface_id, jobject j_surface);
void UnregisterViewSurface(int surface_id);
-gfx::ScopedJavaSurface GetViewSurface(int surface_id);
+gl::ScopedJavaSurface GetViewSurface(int surface_id);
void CreateSurfaceTextureSurface(int surface_texture_id,
int client_id,
- gfx::SurfaceTexture* surface_texture);
+ gl::SurfaceTexture* surface_texture);
void DestroySurfaceTextureSurface(int surface_texture_id, int client_id);
-gfx::ScopedJavaSurface GetSurfaceTextureSurface(int surface_texture_id,
- int client_id);
+gl::ScopedJavaSurface GetSurfaceTextureSurface(int surface_texture_id,
+ int client_id);
bool RegisterChildProcessLauncher(JNIEnv* env);
diff --git a/chromium/content/browser/android/content_video_view.cc b/chromium/content/browser/android/content_video_view.cc
index 4b14959ba5f..e0d1a12e849 100644
--- a/chromium/content/browser/android/content_video_view.cc
+++ b/chromium/content/browser/android/content_video_view.cc
@@ -108,7 +108,7 @@ void ContentVideoView::SetSurface(JNIEnv*,
const JavaParamRef<jobject>&,
const JavaParamRef<jobject>& surface) {
client_->SetVideoSurface(
- gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
+ gl::ScopedJavaSurface::AcquireExternalSurface(surface));
}
void ContentVideoView::DidExitFullscreen(JNIEnv*,
diff --git a/chromium/content/browser/android/content_video_view.h b/chromium/content/browser/android/content_video_view.h
index 292f818d927..f54a29fd76e 100644
--- a/chromium/content/browser/android/content_video_view.h
+++ b/chromium/content/browser/android/content_video_view.h
@@ -32,7 +32,7 @@ class ContentVideoView {
// For receiving notififcations when the SurfaceView surface is created and
// destroyed. When |surface.IsEmpty()| the surface was destroyed and
// the client should not hold any references to it once this returns.
- virtual void SetVideoSurface(gfx::ScopedJavaSurface surface) = 0;
+ virtual void SetVideoSurface(gl::ScopedJavaSurface surface) = 0;
// Called after the ContentVideoView has been hidden because we're exiting
// fullscreen.
diff --git a/chromium/content/browser/android/content_view_core_impl.cc b/chromium/content/browser/android/content_view_core_impl.cc
index 133cf940558..7d636b6f9cd 100644
--- a/chromium/content/browser/android/content_view_core_impl.cc
+++ b/chromium/content/browser/android/content_view_core_impl.cc
@@ -19,7 +19,6 @@
#include "cc/layers/layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/output/begin_frame_args.h"
-#include "cc/output/viewport_selection_bound.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/android/gesture_event_type.h"
@@ -58,6 +57,7 @@
#include "ui/android/window_android.h"
#include "ui/events/android/motion_event_android.h"
#include "ui/events/blink/blink_event_util.h"
+#include "ui/events/event_utils.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
@@ -423,7 +423,7 @@ void ContentViewCoreImpl::UpdateFrameInfo(
const gfx::Vector2dF& controls_offset,
const gfx::Vector2dF& content_offset,
bool is_mobile_optimized_hint,
- const cc::ViewportSelectionBound& selection_start) {
+ const gfx::SelectionBound& selection_start) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null() || !window_android_)
@@ -437,14 +437,14 @@ void ContentViewCoreImpl::UpdateFrameInfo(
// The CursorAnchorInfo API in Android only supports zero width selection
// bounds.
const jboolean has_insertion_marker =
- selection_start.type == cc::SELECTION_BOUND_CENTER;
- const jboolean is_insertion_marker_visible = selection_start.visible;
+ selection_start.type() == gfx::SelectionBound::CENTER;
+ const jboolean is_insertion_marker_visible = selection_start.visible();
const jfloat insertion_marker_horizontal =
- has_insertion_marker ? selection_start.edge_top.x() : 0.0f;
+ has_insertion_marker ? selection_start.edge_top().x() : 0.0f;
const jfloat insertion_marker_top =
- has_insertion_marker ? selection_start.edge_top.y() : 0.0f;
+ has_insertion_marker ? selection_start.edge_top().y() : 0.0f;
const jfloat insertion_marker_bottom =
- has_insertion_marker ? selection_start.edge_bottom.y() : 0.0f;
+ has_insertion_marker ? selection_start.edge_bottom().y() : 0.0f;
Java_ContentViewCore_updateFrameInfo(
env, obj.obj(),
@@ -598,6 +598,10 @@ void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
event.x * dpi_scale(),
event.y * dpi_scale());
break;
+ case WebInputEvent::GestureLongPress:
+ if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
+ Java_ContentViewCore_performLongPressHapticFeedback(env, j_obj.obj());
+ break;
default:
break;
}
@@ -1035,6 +1039,14 @@ jboolean ContentViewCoreImpl::SendMouseWheelEvent(
if (!ticks_x && !ticks_y)
return false;
+ // Compute Event.Latency.OS.MOUSE_WHEEL histogram.
+ base::TimeTicks current_time = ui::EventTimeForNow();
+ base::TimeTicks event_time = base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(time_ms);
+ base::TimeDelta delta = current_time - event_time;
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.MOUSE_WHEEL",
+ delta.InMicroseconds(), 1, 1000000, 50);
+
blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
ticks_x, ticks_y, pixels_per_tick / dpi_scale(), time_ms / 1000.0,
x / dpi_scale(), y / dpi_scale());
diff --git a/chromium/content/browser/android/content_view_core_impl.h b/chromium/content/browser/android/content_view_core_impl.h
index ee5bd7aaf85..3a445e8517b 100644
--- a/chromium/content/browser/android/content_view_core_impl.h
+++ b/chromium/content/browser/android/content_view_core_impl.h
@@ -26,6 +26,7 @@
#include "ui/android/view_android.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/selection_bound.h"
#include "url/gurl.h"
namespace cc {
@@ -316,7 +317,7 @@ class ContentViewCoreImpl : public ContentViewCore,
const gfx::Vector2dF& controls_offset,
const gfx::Vector2dF& content_offset,
bool is_mobile_optimized_hint,
- const cc::ViewportSelectionBound& selection_start);
+ const gfx::SelectionBound& selection_start);
void ForceUpdateImeAdapter(long native_ime_adapter);
void UpdateImeAdapter(long native_ime_adapter,
diff --git a/chromium/content/browser/android/deferred_download_observer.cc b/chromium/content/browser/android/deferred_download_observer.cc
deleted file mode 100644
index e41e48478ff..00000000000
--- a/chromium/content/browser/android/deferred_download_observer.cc
+++ /dev/null
@@ -1,32 +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/android/deferred_download_observer.h"
-
-#include <memory>
-
-#include "content/browser/android/download_controller_android_impl.h"
-#include "content/public/browser/web_contents.h"
-
-namespace content {
-
-DeferredDownloadObserver::DeferredDownloadObserver(
- WebContents* web_contents,
- const base::Closure& deferred_download_cb)
- : WebContentsObserver(web_contents),
- deferred_download_cb_(deferred_download_cb) {
-}
-
-DeferredDownloadObserver::~DeferredDownloadObserver() {}
-
-void DeferredDownloadObserver::WasShown() {
- deferred_download_cb_.Run();
- DownloadControllerAndroidImpl::GetInstance()->CancelDeferredDownload(this);
-}
-
-void DeferredDownloadObserver::WebContentsDestroyed() {
- DownloadControllerAndroidImpl::GetInstance()->CancelDeferredDownload(this);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/deferred_download_observer.h b/chromium/content/browser/android/deferred_download_observer.h
deleted file mode 100644
index 0c11db8cee5..00000000000
--- a/chromium/content/browser/android/deferred_download_observer.h
+++ /dev/null
@@ -1,42 +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_ANDROID_DEFERRED_DOWNLOAD_OBSERVER_H_
-#define CONTENT_BROWSER_ANDROID_DEFERRED_DOWNLOAD_OBSERVER_H_
-
-#include "base/callback.h"
-#include "base/containers/scoped_ptr_hash_map.h"
-#include "base/macros.h"
-#include "content/public/browser/web_contents_observer.h"
-
-namespace content {
-class WebContents;
-
-// Class for handling deferred downloads inside a WebContents. In document
-// mode, it is possible that a download starts before ContentViewCore gets
-// created. This class listens to the WebContentsObserver::WasShown() method
-// before running the download tasks to make sure ContentViewCore is attached
-// to WebContents.
-// TODO(qinmin): Remove this when java Tab object creation is no longer pending
-// on Activity creation.
-class DeferredDownloadObserver : public WebContentsObserver {
- public:
- DeferredDownloadObserver(WebContents* web_contents,
- const base::Closure& deferred_download_cb);
- ~DeferredDownloadObserver() override;
-
- // WebContentsObserver method.
- void WasShown() override;
- void WebContentsDestroyed() override;
-
- private:
- // Callback to run when WebContents gets shown.
- base::Closure deferred_download_cb_;
-
- DISALLOW_COPY_AND_ASSIGN(DeferredDownloadObserver);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_DEFERRED_DOWNLOAD_OBSERVER_H_
diff --git a/chromium/content/browser/android/download_controller_android_impl.cc b/chromium/content/browser/android/download_controller_android_impl.cc
deleted file mode 100644
index f6231b3ce12..00000000000
--- a/chromium/content/browser/android/download_controller_android_impl.cc
+++ /dev/null
@@ -1,635 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/download_controller_android_impl.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/android/context_utils.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-#include "content/browser/android/content_view_core_impl.h"
-#include "content/browser/android/deferred_download_observer.h"
-#include "content/browser/download/download_item_impl.h"
-#include "content/browser/download/download_manager_impl.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_delegate.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/download_url_parameters.h"
-#include "content/public/browser/global_request_id.h"
-#include "content/public/browser/resource_request_info.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/referrer.h"
-#include "jni/DownloadController_jni.h"
-#include "net/base/filename_util.h"
-#include "net/cookies/cookie_options.h"
-#include "net/cookies/cookie_store.h"
-#include "net/http/http_content_disposition.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-
-using base::android::ConvertUTF8ToJavaString;
-using base::android::ScopedJavaLocalRef;
-
-namespace {
-// Guards download_controller_
-base::LazyInstance<base::Lock> g_download_controller_lock_;
-
-content::WebContents* GetWebContents(int render_process_id,
- int render_view_id) {
- content::RenderViewHost* render_view_host =
- content::RenderViewHost::FromID(render_process_id, render_view_id);
-
- if (!render_view_host)
- return nullptr;
-
- return content::WebContents::FromRenderViewHost(render_view_host);
-}
-
-void CreateContextMenuDownload(int render_process_id,
- int render_view_id,
- const content::ContextMenuParams& params,
- bool is_link,
- const std::string& extra_headers,
- bool granted) {
- if (!granted)
- return;
-
- content::WebContents* web_contents =
- GetWebContents(render_process_id, render_view_id);
- if (!web_contents)
- return;
-
- const GURL& url = is_link ? params.link_url : params.src_url;
- const GURL& referring_url =
- params.frame_url.is_empty() ? params.page_url : params.frame_url;
- content::DownloadManagerImpl* dlm =
- static_cast<content::DownloadManagerImpl*>(
- content::BrowserContext::GetDownloadManager(
- web_contents->GetBrowserContext()));
- std::unique_ptr<content::DownloadUrlParameters> dl_params(
- content::DownloadUrlParameters::FromWebContents(web_contents, url));
- content::Referrer referrer = content::Referrer::SanitizeForRequest(
- url,
- content::Referrer(referring_url.GetAsReferrer(), params.referrer_policy));
- dl_params->set_referrer(referrer);
- if (is_link)
- dl_params->set_referrer_encoding(params.frame_charset);
- net::HttpRequestHeaders headers;
- headers.AddHeadersFromString(extra_headers);
- for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();)
- dl_params->add_request_header(it.name(), it.value());
- if (!is_link && extra_headers.empty())
- dl_params->set_prefer_cache(true);
- dl_params->set_prompt(false);
- dlm->DownloadUrl(std::move(dl_params));
-}
-
-// Check if an interrupted download item can be auto resumed.
-bool IsInterruptedDownloadAutoResumable(content::DownloadItem* download_item) {
- int interrupt_reason = download_item->GetLastReason();
- DCHECK_NE(interrupt_reason, content::DOWNLOAD_INTERRUPT_REASON_NONE);
- return
- interrupt_reason == content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT ||
- interrupt_reason == content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED ||
- interrupt_reason ==
- content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED;
-}
-
-} // namespace
-
-namespace content {
-
-// JNI methods
-static void Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
- DownloadControllerAndroidImpl::GetInstance()->Init(env, obj);
-}
-
-static void OnRequestFileAccessResult(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jlong callback_id,
- jboolean granted) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(callback_id);
-
- // Convert java long long int to c++ pointer, take ownership.
- std::unique_ptr<
- DownloadControllerAndroid::AcquireFileAccessPermissionCallback>
- cb(reinterpret_cast<
- DownloadControllerAndroid::AcquireFileAccessPermissionCallback*>(
- callback_id));
- if (!granted) {
- DownloadControllerAndroid::RecordDownloadCancelReason(
- DownloadControllerAndroid::CANCEL_REASON_NO_STORAGE_PERMISSION);
- }
- cb->Run(granted);
-}
-
-struct DownloadControllerAndroidImpl::JavaObject {
- ScopedJavaLocalRef<jobject> Controller(JNIEnv* env) {
- return GetRealObject(env, obj);
- }
- jweak obj;
-};
-
-// static
-bool DownloadControllerAndroidImpl::RegisterDownloadController(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-// static
-DownloadControllerAndroid* DownloadControllerAndroid::Get() {
- base::AutoLock lock(g_download_controller_lock_.Get());
- if (!DownloadControllerAndroid::download_controller_)
- download_controller_ = DownloadControllerAndroidImpl::GetInstance();
- return DownloadControllerAndroid::download_controller_;
-}
-
-//static
-void DownloadControllerAndroid::SetDownloadControllerAndroid(
- DownloadControllerAndroid* download_controller) {
- base::AutoLock lock(g_download_controller_lock_.Get());
- DownloadControllerAndroid::download_controller_ = download_controller;
-}
-
-// static
-void DownloadControllerAndroid::RecordDownloadCancelReason(
- DownloadCancelReason reason) {
- UMA_HISTOGRAM_ENUMERATION(
- "MobileDownload.CancelReason", reason, CANCEL_REASON_MAX);
-}
-
-// static
-DownloadControllerAndroidImpl* DownloadControllerAndroidImpl::GetInstance() {
- return base::Singleton<DownloadControllerAndroidImpl>::get();
-}
-
-DownloadControllerAndroidImpl::DownloadControllerAndroidImpl()
- : java_object_(NULL) {
-}
-
-DownloadControllerAndroidImpl::~DownloadControllerAndroidImpl() {
- if (java_object_) {
- JNIEnv* env = base::android::AttachCurrentThread();
- env->DeleteWeakGlobalRef(java_object_->obj);
- delete java_object_;
- base::android::CheckException(env);
- }
-}
-
-// Initialize references to Java object.
-void DownloadControllerAndroidImpl::Init(JNIEnv* env, jobject obj) {
- java_object_ = new JavaObject;
- java_object_->obj = env->NewWeakGlobalRef(obj);
-}
-
-void DownloadControllerAndroidImpl::CancelDeferredDownload(
- DeferredDownloadObserver* observer) {
- for (auto iter = deferred_downloads_.begin();
- iter != deferred_downloads_.end(); ++iter) {
- if (*iter == observer) {
- deferred_downloads_.erase(iter);
- return;
- }
- }
-}
-
-void DownloadControllerAndroidImpl::AcquireFileAccessPermission(
- WebContents* web_contents,
- const DownloadControllerAndroid::AcquireFileAccessPermissionCallback& cb) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(web_contents);
-
- ScopedJavaLocalRef<jobject> view =
- GetContentViewCoreFromWebContents(web_contents);
- if (view.is_null()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(cb, false));
- return;
- }
-
- if (HasFileAccessPermission(view)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(cb, true));
- return;
- }
-
- JNIEnv* env = base::android::AttachCurrentThread();
- // Make copy on the heap so we can pass the pointer through JNI.
- intptr_t callback_id = reinterpret_cast<intptr_t>(
- new DownloadControllerAndroid::AcquireFileAccessPermissionCallback(cb));
- Java_DownloadController_requestFileAccess(
- env, GetJavaObject()->Controller(env).obj(), view.obj(), callback_id);
-}
-
-void DownloadControllerAndroidImpl::SetDefaultDownloadFileName(
- const std::string& file_name) {
- default_file_name_ = file_name;
-}
-
-bool DownloadControllerAndroidImpl::HasFileAccessPermission(
- ScopedJavaLocalRef<jobject> j_content_view_core) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!j_content_view_core.is_null());
-
- JNIEnv* env = base::android::AttachCurrentThread();
- return Java_DownloadController_hasFileAccess(
- env, GetJavaObject()->Controller(env).obj(), j_content_view_core.obj());
-}
-
-void DownloadControllerAndroidImpl::CreateGETDownload(
- int render_process_id, int render_view_id, int request_id,
- bool must_download) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- GlobalRequestID global_id(render_process_id, request_id);
-
- // We are yielding the UI thread and render_view_host may go away by
- // the time we come back. Pass along render_process_id and render_view_id
- // to retrieve it later (if it still exists).
- GetDownloadInfoCB cb = base::Bind(
- &DownloadControllerAndroidImpl::StartAndroidDownload,
- base::Unretained(this), render_process_id,
- render_view_id, must_download);
-
- PrepareDownloadInfo(
- global_id,
- base::Bind(&DownloadControllerAndroidImpl::StartDownloadOnUIThread,
- base::Unretained(this), cb));
-}
-
-void DownloadControllerAndroidImpl::PrepareDownloadInfo(
- const GlobalRequestID& global_id,
- const GetDownloadInfoCB& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- net::URLRequest* request =
- ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
- if (!request) {
- LOG(ERROR) << "Request to download not found.";
- return;
- }
-
- DownloadInfoAndroid info_android(request);
-
- net::CookieStore* cookie_store = request->context()->cookie_store();
- if (cookie_store) {
- cookie_store->GetAllCookiesForURLAsync(
- request->url(),
- base::Bind(&DownloadControllerAndroidImpl::CheckPolicyAndLoadCookies,
- base::Unretained(this), info_android, callback, global_id));
- } else {
- // Can't get any cookies, start android download.
- callback.Run(info_android);
- }
-}
-
-void DownloadControllerAndroidImpl::CheckPolicyAndLoadCookies(
- const DownloadInfoAndroid& info, const GetDownloadInfoCB& callback,
- const GlobalRequestID& global_id, const net::CookieList& cookie_list) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- net::URLRequest* request =
- ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
- if (!request) {
- LOG(ERROR) << "Request to download not found.";
- return;
- }
-
- if (request->context()->network_delegate()->CanGetCookies(
- *request, cookie_list)) {
- DoLoadCookies(info, callback, global_id);
- } else {
- callback.Run(info);
- }
-}
-
-void DownloadControllerAndroidImpl::DoLoadCookies(
- const DownloadInfoAndroid& info, const GetDownloadInfoCB& callback,
- const GlobalRequestID& global_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- net::CookieOptions options;
- options.set_include_httponly();
-
- net::URLRequest* request =
- ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
- if (!request) {
- LOG(ERROR) << "Request to download not found.";
- return;
- }
-
- request->context()->cookie_store()->GetCookiesWithOptionsAsync(
- info.url, options,
- base::Bind(&DownloadControllerAndroidImpl::OnCookieResponse,
- base::Unretained(this), info, callback));
-}
-
-void DownloadControllerAndroidImpl::OnCookieResponse(
- DownloadInfoAndroid download_info,
- const GetDownloadInfoCB& callback,
- const std::string& cookie) {
- download_info.cookie = cookie;
-
- // We have everything we need, start Android download.
- callback.Run(download_info);
-}
-
-void DownloadControllerAndroidImpl::StartDownloadOnUIThread(
- const GetDownloadInfoCB& callback,
- const DownloadInfoAndroid& info) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(callback, info));
-}
-
-void DownloadControllerAndroidImpl::StartAndroidDownload(
- int render_process_id, int render_view_id, bool must_download,
- const DownloadInfoAndroid& info) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- WebContents* web_contents = GetWebContents(render_process_id, render_view_id);
- if (!web_contents) {
- // The view went away. Can't proceed.
- LOG(ERROR) << "Download failed on URL:" << info.url.spec();
- return;
- }
- ScopedJavaLocalRef<jobject> view =
- GetContentViewCoreFromWebContents(web_contents);
- if (view.is_null()) {
- // ContentViewCore might not have been created yet, pass a callback to
- // DeferredDownloadTaskManager so that the download can restart when
- // ContentViewCore is created.
- deferred_downloads_.push_back(new DeferredDownloadObserver(
- web_contents,
- base::Bind(&DownloadControllerAndroidImpl::StartAndroidDownload,
- base::Unretained(this), render_process_id, render_view_id,
- must_download, info)));
- return;
- }
-
- AcquireFileAccessPermission(
- web_contents,
- base::Bind(&DownloadControllerAndroidImpl::StartAndroidDownloadInternal,
- base::Unretained(this), render_process_id, render_view_id,
- must_download, info));
-}
-
-void DownloadControllerAndroidImpl::StartAndroidDownloadInternal(
- int render_process_id, int render_view_id, bool must_download,
- const DownloadInfoAndroid& info, bool allowed) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!allowed)
- return;
-
- // Call newHttpGetDownload
- WebContents* web_contents = GetWebContents(render_process_id, render_view_id);
- // The view went away. Can't proceed.
- if (!web_contents)
- return;
- ScopedJavaLocalRef<jobject> view =
- GetContentViewCoreFromWebContents(web_contents);
- if (view.is_null())
- return;
-
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jstring> jurl =
- ConvertUTF8ToJavaString(env, info.url.spec());
- ScopedJavaLocalRef<jstring> juser_agent =
- ConvertUTF8ToJavaString(env, info.user_agent);
- ScopedJavaLocalRef<jstring> jcontent_disposition =
- ConvertUTF8ToJavaString(env, info.content_disposition);
- ScopedJavaLocalRef<jstring> jmime_type =
- ConvertUTF8ToJavaString(env, info.original_mime_type);
- ScopedJavaLocalRef<jstring> jcookie =
- ConvertUTF8ToJavaString(env, info.cookie);
- ScopedJavaLocalRef<jstring> jreferer =
- ConvertUTF8ToJavaString(env, info.referer);
-
- // net::GetSuggestedFilename will fallback to "download" as filename.
- ScopedJavaLocalRef<jstring> jfilename =
- base::android::ConvertUTF16ToJavaString(
- env, net::GetSuggestedFilename(info.url, info.content_disposition,
- std::string(), // referrer_charset
- std::string(), // suggested_name
- info.original_mime_type,
- default_file_name_));
-
- Java_DownloadController_newHttpGetDownload(
- env, GetJavaObject()->Controller(env).obj(), view.obj(), jurl.obj(),
- juser_agent.obj(), jcontent_disposition.obj(), jmime_type.obj(),
- jcookie.obj(), jreferer.obj(), info.has_user_gesture, jfilename.obj(),
- info.total_bytes, must_download);
-}
-
-void DownloadControllerAndroidImpl::OnDownloadStarted(
- DownloadItem* download_item) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!download_item->GetWebContents())
- return;
-
- JNIEnv* env = base::android::AttachCurrentThread();
-
- // Register for updates to the DownloadItem.
- download_item->AddObserver(this);
-
- ScopedJavaLocalRef<jobject> view =
- GetContentViewCoreFromWebContents(download_item->GetWebContents());
- // The view went away. Can't proceed.
- if (view.is_null())
- return;
-
- ScopedJavaLocalRef<jstring> jmime_type =
- ConvertUTF8ToJavaString(env, download_item->GetMimeType());
- ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
- env, download_item->GetTargetFilePath().BaseName().value());
- Java_DownloadController_onDownloadStarted(
- env, GetJavaObject()->Controller(env).obj(), view.obj(), jfilename.obj(),
- jmime_type.obj());
-}
-
-void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (item->IsDangerous() && (item->GetState() != DownloadItem::CANCELLED))
- OnDangerousDownload(item);
-
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jstring> jguid =
- ConvertUTF8ToJavaString(env, item->GetGuid());
- ScopedJavaLocalRef<jstring> jurl =
- ConvertUTF8ToJavaString(env, item->GetURL().spec());
- ScopedJavaLocalRef<jstring> jmime_type =
- ConvertUTF8ToJavaString(env, item->GetMimeType());
- ScopedJavaLocalRef<jstring> jpath =
- ConvertUTF8ToJavaString(env, item->GetTargetFilePath().value());
- ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
- env, item->GetTargetFilePath().BaseName().value());
- ScopedJavaLocalRef<jstring> joriginal_url =
- ConvertUTF8ToJavaString(env, item->GetOriginalUrl().spec());
- ScopedJavaLocalRef<jstring> jreferrer_url =
- ConvertUTF8ToJavaString(env, item->GetReferrerUrl().spec());
-
- switch (item->GetState()) {
- case DownloadItem::IN_PROGRESS: {
- base::TimeDelta time_delta;
- item->TimeRemaining(&time_delta);
- Java_DownloadController_onDownloadUpdated(
- env, GetJavaObject()->Controller(env).obj(), jurl.obj(),
- jmime_type.obj(), jfilename.obj(), jpath.obj(),
- item->GetReceivedBytes(), item->GetId(), jguid.obj(),
- item->PercentComplete(), time_delta.InMilliseconds(),
- item->HasUserGesture(), item->IsPaused(),
- item->GetBrowserContext()->IsOffTheRecord());
- break;
- }
- case DownloadItem::COMPLETE:
- // Multiple OnDownloadUpdated() notifications may be issued while the
- // download is in the COMPLETE state. Only handle one.
- item->RemoveObserver(this);
-
- // Call onDownloadCompleted
- Java_DownloadController_onDownloadCompleted(
- env, GetJavaObject()->Controller(env).obj(), jurl.obj(),
- jmime_type.obj(), jfilename.obj(), jpath.obj(),
- item->GetReceivedBytes(), item->GetId(), jguid.obj(),
- joriginal_url.obj(), jreferrer_url.obj(), item->HasUserGesture());
- DownloadControllerAndroid::RecordDownloadCancelReason(
- DownloadControllerAndroid::CANCEL_REASON_NOT_CANCELED);
- break;
- case DownloadItem::CANCELLED:
- Java_DownloadController_onDownloadCancelled(
- env, GetJavaObject()->Controller(env).obj(), item->GetId(),
- jguid.obj());
- break;
- case DownloadItem::INTERRUPTED:
- // When device loses/changes network, we get a NETWORK_TIMEOUT,
- // NETWORK_FAILED or NETWORK_DISCONNECTED error. Download should auto
- // resume in this case.
- Java_DownloadController_onDownloadInterrupted(
- env, GetJavaObject()->Controller(env).obj(), jurl.obj(),
- jmime_type.obj(), jfilename.obj(), jpath.obj(),
- item->GetReceivedBytes(), item->GetId(), jguid.obj(),
- item->CanResume(), IsInterruptedDownloadAutoResumable(item),
- item->GetBrowserContext()->IsOffTheRecord());
- item->RemoveObserver(this);
- break;
- case DownloadItem::MAX_DOWNLOAD_STATE:
- NOTREACHED();
- }
-}
-
-void DownloadControllerAndroidImpl::OnDangerousDownload(DownloadItem* item) {
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
- env, item->GetTargetFilePath().BaseName().value());
- ScopedJavaLocalRef<jstring> jguid =
- ConvertUTF8ToJavaString(env, item->GetGuid());
- ScopedJavaLocalRef<jobject> view_core = GetContentViewCoreFromWebContents(
- item->GetWebContents());
- if (!view_core.is_null()) {
- Java_DownloadController_onDangerousDownload(
- env, GetJavaObject()->Controller(env).obj(), view_core.obj(),
- jfilename.obj(), jguid.obj());
- }
-}
-
-ScopedJavaLocalRef<jobject>
- DownloadControllerAndroidImpl::GetContentViewCoreFromWebContents(
- WebContents* web_contents) {
- if (!web_contents)
- return ScopedJavaLocalRef<jobject>();
-
- ContentViewCore* view_core = ContentViewCore::FromWebContents(web_contents);
- return view_core ? view_core->GetJavaObject() :
- ScopedJavaLocalRef<jobject>();
-}
-
-DownloadControllerAndroidImpl::JavaObject*
- DownloadControllerAndroidImpl::GetJavaObject() {
- if (!java_object_) {
- // Initialize Java DownloadController by calling
- // DownloadController.getInstance(), which will call Init()
- // if Java DownloadController is not instantiated already.
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_DownloadController_getInstance(env);
- }
-
- DCHECK(java_object_);
- return java_object_;
-}
-
-void DownloadControllerAndroidImpl::StartContextMenuDownload(
- const ContextMenuParams& params, WebContents* web_contents, bool is_link,
- const std::string& extra_headers) {
- int process_id = web_contents->GetRenderProcessHost()->GetID();
- int routing_id = web_contents->GetRoutingID();
- AcquireFileAccessPermission(
- web_contents, base::Bind(&CreateContextMenuDownload, process_id,
- routing_id, params, is_link, extra_headers));
-}
-
-void DownloadControllerAndroidImpl::DangerousDownloadValidated(
- WebContents* web_contents,
- const std::string& download_guid,
- bool accept) {
- if (!web_contents)
- return;
- DownloadManagerImpl* dlm = static_cast<DownloadManagerImpl*>(
- BrowserContext::GetDownloadManager(web_contents->GetBrowserContext()));
- DownloadItem* item = dlm->GetDownloadByGuid(download_guid);
- if (!item)
- return;
- if (accept) {
- item->ValidateDangerousDownload();
- } else {
- DownloadControllerAndroid::RecordDownloadCancelReason(
- DownloadControllerAndroid::
- CANCEL_REASON_DANGEROUS_DOWNLOAD_INFOBAR_DISMISSED);
- item->Remove();
- }
-}
-
-DownloadControllerAndroidImpl::DownloadInfoAndroid::DownloadInfoAndroid(
- net::URLRequest* request)
- : has_user_gesture(false) {
- request->GetResponseHeaderByName("content-disposition", &content_disposition);
-
- if (request->response_headers())
- request->response_headers()->GetMimeType(&original_mime_type);
-
- request->extra_request_headers().GetHeader(
- net::HttpRequestHeaders::kUserAgent, &user_agent);
- if (user_agent.empty())
- user_agent = GetContentClient()->GetUserAgent();
- GURL referer_url(request->referrer());
- if (referer_url.is_valid())
- referer = referer_url.spec();
- if (!request->url_chain().empty()) {
- original_url = request->url_chain().front();
- url = request->url_chain().back();
- }
-
- const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
- if (info)
- has_user_gesture = info->HasUserGesture();
-}
-
-DownloadControllerAndroidImpl::DownloadInfoAndroid::DownloadInfoAndroid(
- const DownloadInfoAndroid& other) = default;
-
-DownloadControllerAndroidImpl::DownloadInfoAndroid::~DownloadInfoAndroid() {}
-
-} // namespace content
diff --git a/chromium/content/browser/android/download_controller_android_impl.h b/chromium/content/browser/android/download_controller_android_impl.h
deleted file mode 100644
index 133c1029092..00000000000
--- a/chromium/content/browser/android/download_controller_android_impl.h
+++ /dev/null
@@ -1,159 +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.
-
-// This class pairs with DownloadController on Java side to forward requests
-// for GET downloads to the current DownloadListener. POST downloads are
-// handled on the native side.
-//
-// Both classes are Singleton classes. C++ object owns Java object.
-//
-// Call sequence
-// GET downloads:
-// DownloadControllerAndroid::CreateGETDownload() =>
-// DownloadController.newHttpGetDownload() =>
-// DownloadListener.onDownloadStart() /
-// DownloadListener2.requestHttpGetDownload()
-//
-
-#ifndef CONTENT_BROWSER_ANDROID_DOWNLOAD_CONTROLLER_ANDROID_IMPL_H_
-#define CONTENT_BROWSER_ANDROID_DOWNLOAD_CONTROLLER_ANDROID_IMPL_H_
-
-#include <string>
-
-#include <stdint.h>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/scoped_vector.h"
-#include "base/memory/singleton.h"
-#include "content/public/browser/android/download_controller_android.h"
-#include "net/cookies/cookie_monster.h"
-#include "url/gurl.h"
-
-namespace net {
-class URLRequest;
-}
-
-namespace content {
-struct GlobalRequestID;
-class DeferredDownloadObserver;
-class RenderViewHost;
-class WebContents;
-
-class DownloadControllerAndroidImpl : public DownloadControllerAndroid {
- public:
- static DownloadControllerAndroidImpl* GetInstance();
-
- static bool RegisterDownloadController(JNIEnv* env);
-
- // Called when DownloadController Java object is instantiated.
- void Init(JNIEnv* env, jobject obj);
-
- // Removes a deferred download from |deferred_downloads_|.
- void CancelDeferredDownload(DeferredDownloadObserver* observer);
-
- // DownloadControllerAndroid implementation.
- void AcquireFileAccessPermission(
- WebContents* web_contents,
- const AcquireFileAccessPermissionCallback& callback) override;
- void SetDefaultDownloadFileName(const std::string& file_name) override;
-
- private:
- // Used to store all the information about an Android download.
- struct DownloadInfoAndroid {
- explicit DownloadInfoAndroid(net::URLRequest* request);
- DownloadInfoAndroid(const DownloadInfoAndroid& other);
- ~DownloadInfoAndroid();
-
- // The URL from which we are downloading. This is the final URL after any
- // redirection by the server for |original_url_|.
- GURL url;
- // The original URL before any redirection by the server for this URL.
- GURL original_url;
- int64_t total_bytes;
- std::string content_disposition;
- std::string original_mime_type;
- std::string user_agent;
- std::string cookie;
- std::string referer;
- bool has_user_gesture;
-
- WebContents* web_contents;
- // Default copy constructor is used for passing this struct by value.
- };
- struct JavaObject;
- friend struct base::DefaultSingletonTraits<DownloadControllerAndroidImpl>;
- DownloadControllerAndroidImpl();
- ~DownloadControllerAndroidImpl() override;
-
- // Helper method for implementing AcquireFileAccessPermission().
- bool HasFileAccessPermission(
- base::android::ScopedJavaLocalRef<jobject> j_content_view_core);
-
- // DownloadControllerAndroid implementation.
- void CreateGETDownload(int render_process_id,
- int render_view_id,
- int request_id,
- bool must_download) override;
- void OnDownloadStarted(DownloadItem* download_item) override;
- void StartContextMenuDownload(const ContextMenuParams& params,
- WebContents* web_contents,
- bool is_link,
- const std::string& extra_headers) override;
- void DangerousDownloadValidated(WebContents* web_contents,
- const std::string& download_guid,
- bool accept) override;
-
- // DownloadItem::Observer interface.
- void OnDownloadUpdated(DownloadItem* item) override;
-
- typedef base::Callback<void(const DownloadInfoAndroid&)>
- GetDownloadInfoCB;
- void PrepareDownloadInfo(const GlobalRequestID& global_id,
- const GetDownloadInfoCB& callback);
- void CheckPolicyAndLoadCookies(const DownloadInfoAndroid& info,
- const GetDownloadInfoCB& callback,
- const GlobalRequestID& global_id,
- const net::CookieList& cookie_list);
- void DoLoadCookies(const DownloadInfoAndroid& info,
- const GetDownloadInfoCB& callback,
- const GlobalRequestID& global_id);
- void OnCookieResponse(DownloadInfoAndroid info,
- const GetDownloadInfoCB& callback,
- const std::string& cookie);
- void StartDownloadOnUIThread(const GetDownloadInfoCB& callback,
- const DownloadInfoAndroid& info);
- void StartAndroidDownload(int render_process_id,
- int render_view_id,
- bool must_download,
- const DownloadInfoAndroid& info);
- void StartAndroidDownloadInternal(int render_process_id,
- int render_view_id,
- bool must_download,
- const DownloadInfoAndroid& info,
- bool allowed);
-
- // The download item contains dangerous file types.
- void OnDangerousDownload(DownloadItem *item);
-
- base::android::ScopedJavaLocalRef<jobject> GetContentViewCoreFromWebContents(
- WebContents* web_contents);
-
- // Creates Java object if it is not created already and returns it.
- JavaObject* GetJavaObject();
-
- JavaObject* java_object_;
-
- std::string default_file_name_;
-
- ScopedVector<DeferredDownloadObserver> deferred_downloads_;
-
- DISALLOW_COPY_AND_ASSIGN(DownloadControllerAndroidImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_DOWNLOAD_CONTROLLER_ANDROID_IMPL_H_
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 78100575452..9c9cc09bdeb 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
@@ -44,56 +44,54 @@ void GinJavaMethodInvocationHelper::Init(DispatcherDelegate* dispatcher) {
// Build on the UI thread a map of object_id -> WeakRef for Java objects from
// |arguments_|. Then we can use this map on the background thread without
// accessing |dispatcher|.
- BuildObjectRefsFromListValue(dispatcher, arguments_.get());
+ BuildObjectRefsFromListValue(dispatcher, *arguments_);
}
// As V8ValueConverter has finite recursion depth when serializing
// JavaScript values, we don't bother about having a recursion threshold here.
void GinJavaMethodInvocationHelper::BuildObjectRefsFromListValue(
DispatcherDelegate* dispatcher,
- const base::Value* list_value) {
- DCHECK(list_value->IsType(base::Value::TYPE_LIST));
+ const base::Value& list_value) {
+ DCHECK(list_value.IsType(base::Value::TYPE_LIST));
const base::ListValue* list;
- list_value->GetAsList(&list);
- for (base::ListValue::const_iterator iter = list->begin();
- iter != list->end();
- ++iter) {
- if (AppendObjectRef(dispatcher, *iter))
+ list_value.GetAsList(&list);
+ for (const auto& entry : *list) {
+ if (AppendObjectRef(dispatcher, *entry))
continue;
- if ((*iter)->IsType(base::Value::TYPE_LIST)) {
- BuildObjectRefsFromListValue(dispatcher, *iter);
- } else if ((*iter)->IsType(base::Value::TYPE_DICTIONARY)) {
- BuildObjectRefsFromDictionaryValue(dispatcher, *iter);
+ if (entry->IsType(base::Value::TYPE_LIST)) {
+ BuildObjectRefsFromListValue(dispatcher, *entry);
+ } else if (entry->IsType(base::Value::TYPE_DICTIONARY)) {
+ BuildObjectRefsFromDictionaryValue(dispatcher, *entry);
}
}
}
void GinJavaMethodInvocationHelper::BuildObjectRefsFromDictionaryValue(
DispatcherDelegate* dispatcher,
- const base::Value* dict_value) {
- DCHECK(dict_value->IsType(base::Value::TYPE_DICTIONARY));
+ const base::Value& dict_value) {
+ DCHECK(dict_value.IsType(base::Value::TYPE_DICTIONARY));
const base::DictionaryValue* dict;
- dict_value->GetAsDictionary(&dict);
+ dict_value.GetAsDictionary(&dict);
for (base::DictionaryValue::Iterator iter(*dict);
!iter.IsAtEnd();
iter.Advance()) {
- if (AppendObjectRef(dispatcher, &iter.value()))
+ if (AppendObjectRef(dispatcher, iter.value()))
continue;
if (iter.value().IsType(base::Value::TYPE_LIST)) {
- BuildObjectRefsFromListValue(dispatcher, &iter.value());
+ BuildObjectRefsFromListValue(dispatcher, iter.value());
} else if (iter.value().IsType(base::Value::TYPE_DICTIONARY)) {
- BuildObjectRefsFromDictionaryValue(dispatcher, &iter.value());
+ BuildObjectRefsFromDictionaryValue(dispatcher, iter.value());
}
}
}
bool GinJavaMethodInvocationHelper::AppendObjectRef(
DispatcherDelegate* dispatcher,
- const base::Value* raw_value) {
- if (!GinJavaBridgeValue::ContainsGinJavaBridgeValue(raw_value))
+ const base::Value& raw_value) {
+ if (!GinJavaBridgeValue::ContainsGinJavaBridgeValue(&raw_value))
return false;
std::unique_ptr<const GinJavaBridgeValue> value(
- GinJavaBridgeValue::FromValue(raw_value));
+ GinJavaBridgeValue::FromValue(&raw_value));
if (!value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID))
return false;
GinJavaBoundObject::ObjectID object_id;
diff --git a/chromium/content/browser/android/java/gin_java_method_invocation_helper.h b/chromium/content/browser/android/java/gin_java_method_invocation_helper.h
index b2c0992eaa4..6582ccfe6b1 100644
--- a/chromium/content/browser/android/java/gin_java_method_invocation_helper.h
+++ b/chromium/content/browser/android/java/gin_java_method_invocation_helper.h
@@ -73,12 +73,12 @@ class CONTENT_EXPORT GinJavaMethodInvocationHelper
~GinJavaMethodInvocationHelper();
void BuildObjectRefsFromListValue(DispatcherDelegate* dispatcher,
- const base::Value* list_value);
+ const base::Value& list_value);
void BuildObjectRefsFromDictionaryValue(DispatcherDelegate* dispatcher,
- const base::Value* dict_value);
+ const base::Value& dict_value);
bool AppendObjectRef(DispatcherDelegate* dispatcher,
- const base::Value* raw_value);
+ const base::Value& raw_value);
void InvokeMethod(jobject object,
jclass clazz,
diff --git a/chromium/content/browser/android/service_registry_android_impl.cc b/chromium/content/browser/android/service_registry_android_impl.cc
index e54c3610a29..b66e4d3e915 100644
--- a/chromium/content/browser/android/service_registry_android_impl.cc
+++ b/chromium/content/browser/android/service_registry_android_impl.cc
@@ -10,9 +10,10 @@
#include "base/android/jni_string.h"
#include "base/callback.h"
#include "base/memory/ptr_util.h"
-#include "content/public/common/service_registry.h"
#include "jni/ServiceRegistry_jni.h"
#include "mojo/public/cpp/system/message_pipe.h"
+#include "services/shell/public/cpp/interface_provider.h"
+#include "services/shell/public/cpp/interface_registry.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF8;
@@ -39,8 +40,10 @@ void CreateImplAndAttach(
// static
std::unique_ptr<ServiceRegistryAndroid> ServiceRegistryAndroid::Create(
- ServiceRegistry* registry) {
- return base::WrapUnique(new ServiceRegistryAndroidImpl(registry));
+ shell::InterfaceRegistry* interface_registry,
+ shell::InterfaceProvider* remote_interfaces) {
+ return base::WrapUnique(new ServiceRegistryAndroidImpl(
+ interface_registry, remote_interfaces));
}
// static
@@ -54,8 +57,10 @@ ServiceRegistryAndroidImpl::~ServiceRegistryAndroidImpl() {
// Constructor and destructor call into Java.
ServiceRegistryAndroidImpl::ServiceRegistryAndroidImpl(
- ServiceRegistry* service_registry)
- : service_registry_(service_registry) {
+ shell::InterfaceRegistry* interface_registry,
+ shell::InterfaceProvider* remote_interfaces)
+ : interface_registry_(interface_registry),
+ remote_interfaces_(remote_interfaces) {
JNIEnv* env = AttachCurrentThread();
obj_.Reset(
env,
@@ -85,9 +90,10 @@ void ServiceRegistryAndroidImpl::AddService(
ScopedJavaGlobalRef<jobject> j_scoped_factory;
j_scoped_factory.Reset(env, j_factory);
- service_registry_->AddService(
+ interface_registry_->AddInterface(
name, base::Bind(&CreateImplAndAttach, j_scoped_service_registry,
- j_scoped_manager, j_scoped_factory));
+ j_scoped_manager, j_scoped_factory),
+ nullptr);
}
void ServiceRegistryAndroidImpl::RemoveService(
@@ -95,7 +101,7 @@ void ServiceRegistryAndroidImpl::RemoveService(
const JavaParamRef<jobject>& j_service_registry,
const JavaParamRef<jstring>& j_name) {
std::string name(ConvertJavaStringToUTF8(env, j_name));
- service_registry_->RemoveService(name);
+ interface_registry_->RemoveInterface(name);
}
void ServiceRegistryAndroidImpl::ConnectToRemoteService(
@@ -105,7 +111,7 @@ void ServiceRegistryAndroidImpl::ConnectToRemoteService(
jint j_handle) {
std::string name(ConvertJavaStringToUTF8(env, j_name));
mojo::ScopedMessagePipeHandle handle((mojo::MessagePipeHandle(j_handle)));
- service_registry_->ConnectToRemoteService(name, std::move(handle));
+ remote_interfaces_->GetInterface(name, std::move(handle));
}
} // namespace content
diff --git a/chromium/content/browser/android/service_registry_android_impl.h b/chromium/content/browser/android/service_registry_android_impl.h
index 2620313c801..10e8870ec87 100644
--- a/chromium/content/browser/android/service_registry_android_impl.h
+++ b/chromium/content/browser/android/service_registry_android_impl.h
@@ -22,7 +22,8 @@ class ServiceRegistryAndroidImpl : public ServiceRegistryAndroid {
friend class ServiceRegistryAndroid;
// Use ServiceRegistryAndroid::Create() to create an instance.
- explicit ServiceRegistryAndroidImpl(ServiceRegistry* service_registry);
+ ServiceRegistryAndroidImpl(shell::InterfaceRegistry* interface_registry,
+ shell::InterfaceProvider* remote_interfaces);
// ServiceRegistryAndroid implementation:
void AddService(
@@ -42,7 +43,8 @@ class ServiceRegistryAndroidImpl : public ServiceRegistryAndroid {
jint handle) override;
const base::android::ScopedJavaGlobalRef<jobject>& GetObj() override;
- ServiceRegistry* service_registry_;
+ shell::InterfaceRegistry* interface_registry_ = nullptr;
+ shell::InterfaceProvider* remote_interfaces_ = nullptr;
base::android::ScopedJavaGlobalRef<jobject> obj_;
DISALLOW_COPY_AND_ASSIGN(ServiceRegistryAndroidImpl);
diff --git a/chromium/content/browser/android/synchronous_compositor_host.cc b/chromium/content/browser/android/synchronous_compositor_host.cc
index ec9bdf0bab6..5bd7165ca65 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.cc
+++ b/chromium/content/browser/android/synchronous_compositor_host.cc
@@ -53,43 +53,35 @@ std::unique_ptr<SynchronousCompositorHost> SynchronousCompositorHost::Create(
return nullptr; // Not using sync compositing.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- bool async_input =
- !command_line->HasSwitch(switches::kSyncInputForSyncCompositor);
bool use_in_proc_software_draw =
command_line->HasSwitch(switches::kSingleProcess);
return base::WrapUnique(new SynchronousCompositorHost(
- rwhva, web_contents_android->synchronous_compositor_client(), async_input,
+ rwhva, web_contents_android->synchronous_compositor_client(),
use_in_proc_software_draw));
}
SynchronousCompositorHost::SynchronousCompositorHost(
RenderWidgetHostViewAndroid* rwhva,
SynchronousCompositorClient* client,
- bool async_input,
bool use_in_proc_software_draw)
: rwhva_(rwhva),
client_(client),
ui_task_runner_(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)),
+ process_id_(rwhva_->GetRenderWidgetHost()->GetProcess()->GetID()),
routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
sender_(rwhva_->GetRenderWidgetHost()),
- async_input_(async_input),
use_in_process_zero_copy_software_draw_(use_in_proc_software_draw),
- is_active_(false),
bytes_limit_(0u),
renderer_param_version_(0u),
need_animate_scroll_(false),
need_invalidate_count_(0u),
- need_begin_frame_(false),
- did_activate_pending_tree_count_(0u),
- weak_ptr_factory_(this) {
- client_->DidInitializeCompositor(this);
+ did_activate_pending_tree_count_(0u) {
+ client_->DidInitializeCompositor(this, process_id_, routing_id_);
}
SynchronousCompositorHost::~SynchronousCompositorHost() {
- client_->DidDestroyCompositor(this);
- if (weak_ptr_factory_.HasWeakPtrs())
- UpdateStateTask();
+ client_->DidDestroyCompositor(this, process_id_, routing_id_);
}
bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
@@ -98,16 +90,11 @@ bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_OutputSurfaceCreated,
OutputSurfaceCreated)
IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
- IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_OverScroll, OnOverScroll)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void SynchronousCompositorHost::DidBecomeCurrent() {
- client_->DidBecomeCurrent(this);
-}
-
SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
const gfx::Size& surface_size,
const gfx::Transform& transform,
@@ -120,11 +107,9 @@ SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
transform_for_tile_priority);
SynchronousCompositor::Frame frame;
frame.frame.reset(new cc::CompositorFrame);
- SyncCompositorCommonBrowserParams common_browser_params;
- PopulateCommonParams(&common_browser_params);
SyncCompositorCommonRendererParams common_renderer_params;
if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
- routing_id_, common_browser_params, params, &common_renderer_params,
+ routing_id_, params, &common_renderer_params,
&frame.output_surface_id, frame.frame.get()))) {
return SynchronousCompositor::Frame();
}
@@ -134,14 +119,14 @@ SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
frame.frame.reset();
}
if (frame.frame) {
- UpdateFrameMetaData(frame.frame->metadata);
+ UpdateFrameMetaData(frame.frame->metadata.Clone());
}
return frame;
}
void SynchronousCompositorHost::UpdateFrameMetaData(
- const cc::CompositorFrameMetadata& frame_metadata) {
- rwhva_->SynchronousFrameMetadata(frame_metadata);
+ cc::CompositorFrameMetadata frame_metadata) {
+ rwhva_->SynchronousFrameMetadata(std::move(frame_metadata));
}
namespace {
@@ -163,22 +148,20 @@ class ScopedSetSkCanvas {
}
bool SynchronousCompositorHost::DemandDrawSwInProc(SkCanvas* canvas) {
- SyncCompositorCommonBrowserParams common_browser_params;
- PopulateCommonParams(&common_browser_params);
SyncCompositorCommonRendererParams common_renderer_params;
bool success = false;
std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
ScopedSetSkCanvas set_sk_canvas(canvas);
SyncCompositorDemandDrawSwParams params; // Unused.
if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
- routing_id_, common_browser_params, params, &success,
- &common_renderer_params, frame.get()))) {
+ routing_id_, params, &success, &common_renderer_params,
+ frame.get()))) {
return false;
}
if (!success)
return false;
ProcessCommonParams(common_renderer_params);
- UpdateFrameMetaData(frame->metadata);
+ UpdateFrameMetaData(std::move(frame->metadata));
return true;
}
@@ -232,13 +215,11 @@ bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
return false;
std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
- SyncCompositorCommonBrowserParams common_browser_params;
- PopulateCommonParams(&common_browser_params);
SyncCompositorCommonRendererParams common_renderer_params;
bool success = false;
if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
- routing_id_, common_browser_params, params, &success,
- &common_renderer_params, frame.get()))) {
+ routing_id_, params, &success, &common_renderer_params,
+ frame.get()))) {
return false;
}
ScopedSendZeroMemory send_zero_memory(this);
@@ -246,7 +227,7 @@ bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
return false;
ProcessCommonParams(common_renderer_params);
- UpdateFrameMetaData(frame->metadata);
+ UpdateFrameMetaData(std::move(frame->metadata));
SkBitmap bitmap;
if (!bitmap.installPixels(info, software_draw_shm_->shm.memory(), stride))
@@ -287,13 +268,10 @@ void SynchronousCompositorHost::SetSoftwareDrawSharedMemoryIfNeeded(
return;
}
- SyncCompositorCommonBrowserParams common_browser_params;
- PopulateCommonParams(&common_browser_params);
bool success = false;
SyncCompositorCommonRendererParams common_renderer_params;
if (!sender_->Send(new SyncCompositorMsg_SetSharedMemory(
- routing_id_, common_browser_params, set_shm_params, &success,
- &common_renderer_params)) ||
+ routing_id_, set_shm_params, &success, &common_renderer_params)) ||
!success) {
return;
}
@@ -333,91 +311,38 @@ void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
new SyncCompositorMsg_SetScroll(routing_id_, root_scroll_offset_));
}
-void SynchronousCompositorHost::SendAsyncCompositorStateIfNeeded() {
- if (weak_ptr_factory_.HasWeakPtrs())
- return;
-
- ui_task_runner_->PostTask(
- FROM_HERE, base::Bind(&SynchronousCompositorHost::UpdateStateTask,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void SynchronousCompositorHost::UpdateStateTask() {
- SyncCompositorCommonBrowserParams common_browser_params;
- PopulateCommonParams(&common_browser_params);
- sender_->Send(
- new SyncCompositorMsg_UpdateState(routing_id_, common_browser_params));
- DCHECK(!weak_ptr_factory_.HasWeakPtrs());
-}
-
void SynchronousCompositorHost::SynchronouslyZoomBy(float zoom_delta,
const gfx::Point& anchor) {
- SyncCompositorCommonBrowserParams common_browser_params;
- PopulateCommonParams(&common_browser_params);
SyncCompositorCommonRendererParams common_renderer_params;
if (!sender_->Send(new SyncCompositorMsg_ZoomBy(
- routing_id_, common_browser_params, zoom_delta, anchor,
- &common_renderer_params))) {
+ routing_id_, zoom_delta, anchor, &common_renderer_params))) {
return;
}
ProcessCommonParams(common_renderer_params);
}
-void SynchronousCompositorHost::SetIsActive(bool is_active) {
- if (is_active_ == is_active)
- return;
- is_active_ = is_active;
- UpdateNeedsBeginFrames();
- SendAsyncCompositorStateIfNeeded();
-}
-
void SynchronousCompositorHost::OnComputeScroll(
base::TimeTicks animation_time) {
if (!need_animate_scroll_)
return;
need_animate_scroll_ = false;
- SyncCompositorCommonBrowserParams common_browser_params;
- PopulateCommonParams(&common_browser_params);
- SyncCompositorCommonRendererParams common_renderer_params;
- sender_->Send(new SyncCompositorMsg_ComputeScroll(
- routing_id_, common_browser_params, animation_time));
-}
-
-InputEventAckState SynchronousCompositorHost::HandleInputEvent(
- const blink::WebInputEvent& input_event) {
- if (async_input_)
- return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
- SyncCompositorCommonBrowserParams common_browser_params;
- PopulateCommonParams(&common_browser_params);
SyncCompositorCommonRendererParams common_renderer_params;
- InputEventAckState ack = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
- if (!sender_->Send(new SyncCompositorMsg_HandleInputEvent(
- routing_id_, common_browser_params, &input_event,
- &common_renderer_params, &ack))) {
- return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
- }
- ProcessCommonParams(common_renderer_params);
- return ack;
+ sender_->Send(
+ new SyncCompositorMsg_ComputeScroll(routing_id_, animation_time));
}
void SynchronousCompositorHost::DidOverscroll(
const DidOverscrollParams& over_scroll_params) {
- client_->DidOverscroll(over_scroll_params.accumulated_overscroll,
+ client_->DidOverscroll(this, over_scroll_params.accumulated_overscroll,
over_scroll_params.latest_overscroll_delta,
over_scroll_params.current_fling_velocity);
}
-void SynchronousCompositorHost::BeginFrame(const cc::BeginFrameArgs& args) {
- if (!is_active_)
- return;
-
- SyncCompositorCommonBrowserParams common_browser_params;
- PopulateCommonParams(&common_browser_params);
+void SynchronousCompositorHost::DidSendBeginFrame() {
SyncCompositorCommonRendererParams common_renderer_params;
- if (!sender_->Send(
- new SyncCompositorMsg_BeginFrame(routing_id_, common_browser_params,
- args, &common_renderer_params))) {
+ if (!sender_->Send(new SyncCompositorMsg_SynchronizeRendererState(
+ routing_id_, &common_renderer_params))) {
return;
}
ProcessCommonParams(common_renderer_params);
@@ -430,21 +355,6 @@ void SynchronousCompositorHost::OutputSurfaceCreated() {
new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit_));
}
-void SynchronousCompositorHost::OnOverScroll(
- const SyncCompositorCommonRendererParams& params,
- const DidOverscrollParams& over_scroll_params) {
- ProcessCommonParams(params);
- DidOverscroll(over_scroll_params);
-}
-
-void SynchronousCompositorHost::PopulateCommonParams(
- SyncCompositorCommonBrowserParams* params) {
- DCHECK(params);
- params->begin_frame_source_paused = !is_active_;
-
- weak_ptr_factory_.InvalidateWeakPtrs();
-}
-
void SynchronousCompositorHost::ProcessCommonParams(
const SyncCompositorCommonRendererParams& params) {
// Ignore if |renderer_param_version_| is newer than |params.version|. This
@@ -454,21 +364,17 @@ void SynchronousCompositorHost::ProcessCommonParams(
}
renderer_param_version_ = params.version;
need_animate_scroll_ = params.need_animate_scroll;
- if (need_begin_frame_ != params.need_begin_frame) {
- need_begin_frame_ = params.need_begin_frame;
- UpdateNeedsBeginFrames();
- }
root_scroll_offset_ = params.total_scroll_offset;
if (need_invalidate_count_ != params.need_invalidate_count) {
need_invalidate_count_ = params.need_invalidate_count;
- client_->PostInvalidate();
+ client_->PostInvalidate(this);
}
if (did_activate_pending_tree_count_ !=
params.did_activate_pending_tree_count) {
did_activate_pending_tree_count_ = params.did_activate_pending_tree_count;
- client_->DidUpdateContent();
+ client_->DidUpdateContent(this);
}
// Ensure only valid values from compositor are sent to client.
@@ -476,15 +382,11 @@ void SynchronousCompositorHost::ProcessCommonParams(
// for that case here.
if (params.page_scale_factor) {
client_->UpdateRootLayerState(
- gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
+ this, gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
gfx::ScrollOffsetToVector2dF(params.max_scroll_offset),
params.scrollable_size, params.page_scale_factor,
params.min_page_scale_factor, params.max_page_scale_factor);
}
}
-void SynchronousCompositorHost::UpdateNeedsBeginFrames() {
- rwhva_->OnSetNeedsBeginFrames(is_active_ && need_begin_frame_);
-}
-
} // namespace content
diff --git a/chromium/content/browser/android/synchronous_compositor_host.h b/chromium/content/browser/android/synchronous_compositor_host.h
index b30e8f87741..7cef5b09f4b 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.h
+++ b/chromium/content/browser/android/synchronous_compositor_host.h
@@ -38,7 +38,6 @@ class RenderWidgetHostViewAndroid;
class SynchronousCompositorClient;
class WebContents;
struct DidOverscrollParams;
-struct SyncCompositorCommonBrowserParams;
struct SyncCompositorCommonRendererParams;
class SynchronousCompositorHost : public SynchronousCompositor {
@@ -64,14 +63,11 @@ class SynchronousCompositorHost : public SynchronousCompositor {
void DidChangeRootLayerScrollOffset(
const gfx::ScrollOffset& root_offset) override;
void SynchronouslyZoomBy(float zoom_delta, const gfx::Point& anchor) override;
- void SetIsActive(bool is_active) override;
void OnComputeScroll(base::TimeTicks animation_time) override;
- InputEventAckState HandleInputEvent(const blink::WebInputEvent& input_event);
void DidOverscroll(const DidOverscrollParams& over_scroll_params);
- void BeginFrame(const cc::BeginFrameArgs& args);
+ void DidSendBeginFrame();
bool OnMessageReceived(const IPC::Message& message);
- void DidBecomeCurrent();
private:
class ScopedSendZeroMemory;
@@ -81,17 +77,10 @@ class SynchronousCompositorHost : public SynchronousCompositor {
SynchronousCompositorHost(RenderWidgetHostViewAndroid* rwhva,
SynchronousCompositorClient* client,
- bool async_input,
bool use_in_proc_software_draw);
- void PopulateCommonParams(SyncCompositorCommonBrowserParams* params);
void ProcessCommonParams(const SyncCompositorCommonRendererParams& params);
- void UpdateNeedsBeginFrames();
- void UpdateFrameMetaData(const cc::CompositorFrameMetadata& frame_metadata);
+ void UpdateFrameMetaData(cc::CompositorFrameMetadata frame_metadata);
void OutputSurfaceCreated();
- void OnOverScroll(const SyncCompositorCommonRendererParams& params,
- const DidOverscrollParams& over_scroll_params);
- void SendAsyncCompositorStateIfNeeded();
- void UpdateStateTask();
bool DemandDrawSwInProc(SkCanvas* canvas);
void SetSoftwareDrawSharedMemoryIfNeeded(size_t stride, size_t buffer_size);
void SendZeroMemory();
@@ -99,12 +88,11 @@ class SynchronousCompositorHost : public SynchronousCompositor {
RenderWidgetHostViewAndroid* const rwhva_;
SynchronousCompositorClient* const client_;
const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+ const int process_id_;
const int routing_id_;
IPC::Sender* const sender_;
- const bool async_input_;
const bool use_in_process_zero_copy_software_draw_;
- bool is_active_;
size_t bytes_limit_;
std::unique_ptr<SharedMemoryWithSize> software_draw_shm_;
@@ -115,10 +103,8 @@ class SynchronousCompositorHost : public SynchronousCompositor {
uint32_t renderer_param_version_;
bool need_animate_scroll_;
uint32_t need_invalidate_count_;
- bool need_begin_frame_;
uint32_t did_activate_pending_tree_count_;
- base::WeakPtrFactory<SynchronousCompositorHost> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorHost);
};
diff --git a/chromium/content/browser/appcache/appcache_database.cc b/chromium/content/browser/appcache/appcache_database.cc
index 690da354623..d80c5536a14 100644
--- a/chromium/content/browser/appcache/appcache_database.cc
+++ b/chromium/content/browser/appcache/appcache_database.cc
@@ -1321,7 +1321,7 @@ bool AppCacheDatabase::DeleteExistingAndCreateNewDatabase() {
void AppCacheDatabase::OnDatabaseError(int err, sql::Statement* stmt) {
was_corruption_detected_ |= sql::IsErrorCatastrophic(err);
- if (!db_->ShouldIgnoreSqliteError(err))
+ if (!db_->IsExpectedSqliteError(err))
DLOG(ERROR) << db_->GetErrorMessage();
// TODO: Maybe use non-catostrophic errors to trigger a full integrity check?
}
diff --git a/chromium/content/browser/appcache/appcache_database_unittest.cc b/chromium/content/browser/appcache/appcache_database_unittest.cc
index 79751d99e96..e5e92d0e83c 100644
--- a/chromium/content/browser/appcache/appcache_database_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_database_unittest.cc
@@ -16,7 +16,7 @@
#include "sql/connection.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
-#include "sql/test/scoped_error_ignorer.h"
+#include "sql/test/scoped_error_expecter.h"
#include "sql/test/test_helpers.h"
#include "sql/transaction.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -110,13 +110,13 @@ TEST(AppCacheDatabaseTest, QuickIntegrityCheck) {
// Reopening will notice the corruption and delete/recreate the directory.
{
- sql::ScopedErrorIgnorer ignore_errors;
- ignore_errors.IgnoreError(SQLITE_CORRUPT);
+ sql::test::ScopedErrorExpecter expecter;
+ expecter.ExpectError(SQLITE_CORRUPT);
AppCacheDatabase db(kDbFile);
EXPECT_TRUE(db.LazyOpen(true));
EXPECT_FALSE(base::PathExists(kOtherFile));
EXPECT_TRUE(base::PathExists(kDbFile));
- EXPECT_TRUE(ignore_errors.CheckIgnoredErrors());
+ EXPECT_TRUE(expecter.SawExpectedErrors());
}
}
#endif // NDEBUG
@@ -138,13 +138,13 @@ TEST(AppCacheDatabaseTest, WasCorrutionDetected) {
// See the the corruption is detected and reported.
{
- sql::ScopedErrorIgnorer ignore_errors;
- ignore_errors.IgnoreError(SQLITE_CORRUPT);
+ sql::test::ScopedErrorExpecter expecter;
+ expecter.ExpectError(SQLITE_CORRUPT);
std::map<GURL, int64_t> usage_map;
EXPECT_FALSE(db.GetAllOriginUsage(&usage_map));
EXPECT_TRUE(db.was_corruption_detected());
EXPECT_TRUE(base::PathExists(kDbFile));
- EXPECT_TRUE(ignore_errors.CheckIgnoredErrors());
+ EXPECT_TRUE(expecter.SawExpectedErrors());
}
}
@@ -187,13 +187,13 @@ TEST(AppCacheDatabaseTest, EntryRecords) {
AppCacheDatabase db(kEmptyPath);
EXPECT_TRUE(db.LazyOpen(true));
- sql::ScopedErrorIgnorer ignore_errors;
+ sql::test::ScopedErrorExpecter expecter;
// TODO(shess): Suppressing SQLITE_CONSTRAINT because the code
// expects that and handles the resulting error. Consider revising
// the code to use INSERT OR IGNORE (which would not throw
// SQLITE_CONSTRAINT) and then check ChangeCount() to see if any
// changes were made.
- ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
+ expecter.ExpectError(SQLITE_CONSTRAINT);
AppCacheDatabase::EntryRecord entry;
@@ -260,7 +260,7 @@ TEST(AppCacheDatabaseTest, EntryRecords) {
EXPECT_FALSE(db.AddEntryFlags(GURL("http://blah/1"), 1,
AppCacheEntry::FOREIGN));
- ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ ASSERT_TRUE(expecter.SawExpectedErrors());
}
TEST(AppCacheDatabaseTest, CacheRecords) {
@@ -268,9 +268,9 @@ TEST(AppCacheDatabaseTest, CacheRecords) {
AppCacheDatabase db(kEmptyPath);
EXPECT_TRUE(db.LazyOpen(true));
- sql::ScopedErrorIgnorer ignore_errors;
+ sql::test::ScopedErrorExpecter expecter;
// TODO(shess): See EntryRecords test.
- ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
+ expecter.ExpectError(SQLITE_CONSTRAINT);
const AppCacheDatabase::CacheRecord kZeroRecord;
AppCacheDatabase::CacheRecord record;
@@ -306,7 +306,7 @@ TEST(AppCacheDatabaseTest, CacheRecords) {
EXPECT_TRUE(db.DeleteCache(1));
- ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ ASSERT_TRUE(expecter.SawExpectedErrors());
}
TEST(AppCacheDatabaseTest, GroupRecords) {
@@ -314,9 +314,9 @@ TEST(AppCacheDatabaseTest, GroupRecords) {
AppCacheDatabase db(kEmptyPath);
EXPECT_TRUE(db.LazyOpen(true));
- sql::ScopedErrorIgnorer ignore_errors;
+ sql::test::ScopedErrorExpecter expecter;
// TODO(shess): See EntryRecords test.
- ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
+ expecter.ExpectError(SQLITE_CONSTRAINT);
const GURL kManifestUrl("http://blah/manifest");
const GURL kOrigin(kManifestUrl.GetOrigin());
@@ -437,7 +437,7 @@ TEST(AppCacheDatabaseTest, GroupRecords) {
EXPECT_EQ(kManifest2, record.manifest_url);
EXPECT_EQ(kOrigin2, record.origin);
- ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ ASSERT_TRUE(expecter.SawExpectedErrors());
}
TEST(AppCacheDatabaseTest, GroupAccessAndEvictionTimes) {
@@ -518,9 +518,9 @@ TEST(AppCacheDatabaseTest, NamespaceRecords) {
AppCacheDatabase db(kEmptyPath);
EXPECT_TRUE(db.LazyOpen(true));
- sql::ScopedErrorIgnorer ignore_errors;
+ sql::test::ScopedErrorExpecter expecter;
// TODO(shess): See EntryRecords test.
- ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
+ expecter.ExpectError(SQLITE_CONSTRAINT);
const GURL kFooNameSpace1("http://foo/namespace1");
const GURL kFooNameSpace2("http://foo/namespace2");
@@ -626,7 +626,7 @@ TEST(AppCacheDatabaseTest, NamespaceRecords) {
EXPECT_TRUE(fallbacks[0].namespace_.is_pattern);
EXPECT_TRUE(fallbacks[1].namespace_.is_pattern);
- ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ ASSERT_TRUE(expecter.SawExpectedErrors());
}
TEST(AppCacheDatabaseTest, OnlineWhiteListRecords) {
@@ -681,9 +681,9 @@ TEST(AppCacheDatabaseTest, DeletableResponseIds) {
AppCacheDatabase db(kEmptyPath);
EXPECT_TRUE(db.LazyOpen(true));
- sql::ScopedErrorIgnorer ignore_errors;
+ sql::test::ScopedErrorExpecter expecter;
// TODO(shess): See EntryRecords test.
- ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
+ expecter.ExpectError(SQLITE_CONSTRAINT);
std::vector<int64_t> ids;
@@ -752,7 +752,7 @@ TEST(AppCacheDatabaseTest, DeletableResponseIds) {
for (int i = 0; i < static_cast<int>(ids.size()); ++i)
EXPECT_EQ(i + 5, ids[i]);
- ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ ASSERT_TRUE(expecter.SawExpectedErrors());
}
TEST(AppCacheDatabaseTest, OriginUsage) {
diff --git a/chromium/content/browser/appcache/appcache_group.cc b/chromium/content/browser/appcache/appcache_group.cc
index 49d44627ac7..0e8f3c496da 100644
--- a/chromium/content/browser/appcache/appcache_group.cc
+++ b/chromium/content/browser/appcache/appcache_group.cc
@@ -114,6 +114,7 @@ void AppCacheGroup::AddCache(AppCache* complete_cache) {
void AppCacheGroup::RemoveCache(AppCache* cache) {
DCHECK(cache->associated_hosts().empty());
if (cache == newest_complete_cache_) {
+ CancelUpdate();
AppCache* tmp_cache = newest_complete_cache_;
newest_complete_cache_ = NULL;
tmp_cache->set_owning_group(NULL); // may cause this group to be deleted
diff --git a/chromium/content/browser/appcache/appcache_interceptor.cc b/chromium/content/browser/appcache/appcache_interceptor.cc
index 050e66aee18..85022442562 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.cc
+++ b/chromium/content/browser/appcache/appcache_interceptor.cc
@@ -4,6 +4,7 @@
#include "content/browser/appcache/appcache_interceptor.h"
+#include "base/debug/crash_logging.h"
#include "content/browser/appcache/appcache_backend_impl.h"
#include "content/browser/appcache/appcache_host.h"
#include "content/browser/appcache/appcache_request_handler.h"
@@ -85,6 +86,18 @@ void AppCacheInterceptor::CompleteCrossSiteTransfer(
if (!handler)
return;
if (!handler->SanityCheckIsSameService(filter->appcache_service())) {
+ // This can happen when V2 apps and web pages end up in the same storage
+ // partition.
+ const GURL& first_party_url_for_cookies =
+ request->first_party_for_cookies();
+ if (first_party_url_for_cookies.is_valid()) {
+ // TODO(lazyboy): Remove this once we know which extensions run into this
+ // issue. See https://crbug.com/612711#c25 for details.
+ base::debug::SetCrashKeyValue("aci_wrong_sp_extension_id",
+ first_party_url_for_cookies.host());
+ // No need to explicitly call DumpWithoutCrashing(), since
+ // bad_message::ReceivedBadMessage() below will do that.
+ }
bad_message::ReceivedBadMessage(filter,
bad_message::ACI_WRONG_STORAGE_PARTITION);
return;
diff --git a/chromium/content/browser/appcache/appcache_internals_ui.cc b/chromium/content/browser/appcache/appcache_internals_ui.cc
index 10f316e6135..0c83ce031fc 100644
--- a/chromium/content/browser/appcache/appcache_internals_ui.cc
+++ b/chromium/content/browser/appcache/appcache_internals_ui.cc
@@ -419,7 +419,7 @@ void AppCacheInternalsUI::OnAllAppCacheInfoReady(
std::string incognito_path_prefix;
if (browser_context()->IsOffTheRecord())
incognito_path_prefix = "Incognito ";
- web_ui()->CallJavascriptFunction(
+ web_ui()->CallJavascriptFunctionUnsafe(
kFunctionOnAllAppCacheInfoReady,
base::StringValue(incognito_path_prefix + partition_path.AsUTF8Unsafe()),
*GetListValueFromAppCacheInfoCollection(collection.get()));
@@ -429,7 +429,7 @@ void AppCacheInternalsUI::OnAppCacheInfoDeleted(
const base::FilePath& partition_path,
const std::string& manifest_url,
bool deleted) {
- web_ui()->CallJavascriptFunction(
+ web_ui()->CallJavascriptFunctionUnsafe(
kFunctionOnAppCacheInfoDeleted,
base::StringValue(partition_path.AsUTF8Unsafe()),
base::StringValue(manifest_url), base::FundamentalValue(deleted));
@@ -440,12 +440,12 @@ void AppCacheInternalsUI::OnAppCacheDetailsReady(
const std::string& manifest_url,
std::unique_ptr<AppCacheResourceInfoVector> resource_info_vector) {
if (resource_info_vector) {
- web_ui()->CallJavascriptFunction(
+ web_ui()->CallJavascriptFunctionUnsafe(
kFunctionOnAppCacheDetailsReady, base::StringValue(manifest_url),
base::StringValue(partition_path.AsUTF8Unsafe()),
*GetListValueForAppCacheResourceInfoVector(resource_info_vector.get()));
} else {
- web_ui()->CallJavascriptFunction(
+ web_ui()->CallJavascriptFunctionUnsafe(
kFunctionOnAppCacheDetailsReady, base::StringValue(manifest_url),
base::StringValue(partition_path.AsUTF8Unsafe()));
}
@@ -483,7 +483,7 @@ void AppCacheInternalsUI::OnFileDetailsReady(
if (data_length < response_info->response_data_size())
hex_dump.append("\nNote: data is truncated...");
hex_dump.append("</pre>");
- web_ui()->CallJavascriptFunction(
+ web_ui()->CallJavascriptFunctionUnsafe(
kFunctionOnFileDetailsReady,
*GetDictionaryValueForResponseEnquiry(response_enquiry),
base::StringValue(headers), base::StringValue(hex_dump));
@@ -492,7 +492,7 @@ void AppCacheInternalsUI::OnFileDetailsReady(
void AppCacheInternalsUI::OnFileDetailsFailed(
const Proxy::ResponseEnquiry& response_enquiry,
int net_result_code) {
- web_ui()->CallJavascriptFunction(
+ web_ui()->CallJavascriptFunctionUnsafe(
kFunctionOnFileDetailsFailed,
*GetDictionaryValueForResponseEnquiry(response_enquiry),
base::FundamentalValue(net_result_code));
diff --git a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
index eec35053dfc..ffb58da6077 100644
--- a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -184,7 +184,9 @@ class AppCacheRequestHandlerTest : public testing::Test {
template <class Method>
void RunTestOnIOThread(Method method) {
- test_finished_event_ .reset(new base::WaitableEvent(false, false));
+ test_finished_event_.reset(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED));
io_thread_->task_runner()->PostTask(
FROM_HERE,
base::Bind(&AppCacheRequestHandlerTest::MethodWrapper<Method>,
diff --git a/chromium/content/browser/appcache/appcache_response_unittest.cc b/chromium/content/browser/appcache/appcache_response_unittest.cc
index efb38180f50..9c279d362dc 100644
--- a/chromium/content/browser/appcache/appcache_response_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_response_unittest.cc
@@ -81,7 +81,9 @@ class AppCacheResponseTest : public testing::Test {
template <class Method>
void RunTestOnIOThread(Method method) {
- test_finished_event_ .reset(new base::WaitableEvent(false, false));
+ test_finished_event_.reset(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED));
io_thread_->task_runner()->PostTask(
FROM_HERE, base::Bind(&AppCacheResponseTest::MethodWrapper<Method>,
base::Unretained(this), method));
diff --git a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
index 8baccee429c..85725b46b01 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -400,7 +400,9 @@ class AppCacheStorageImplTest : public testing::Test {
template <class Method>
void RunTestOnIOThread(Method method) {
- test_finished_event_ .reset(new base::WaitableEvent(false, false));
+ test_finished_event_.reset(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED));
io_thread->task_runner()->PostTask(
FROM_HERE, base::Bind(&AppCacheStorageImplTest::MethodWrapper<Method>,
base::Unretained(this), method));
@@ -462,7 +464,8 @@ class AppCacheStorageImplTest : public testing::Test {
void FlushDbThreadTasks() {
// We pump a task thru the db thread to ensure any tasks previously
// scheduled on that thread have been performed prior to return.
- base::WaitableEvent event(false, false);
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
db_thread->task_runner()->PostTask(
FROM_HERE, base::Bind(&AppCacheStorageImplTest::SignalEvent, &event));
event.Wait();
diff --git a/chromium/content/browser/appcache/appcache_update_job.cc b/chromium/content/browser/appcache/appcache_update_job.cc
index 82502777683..0913b911fe2 100644
--- a/chromium/content/browser/appcache/appcache_update_job.cc
+++ b/chromium/content/browser/appcache/appcache_update_job.cc
@@ -7,6 +7,8 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -1256,8 +1258,8 @@ void AppCacheUpdateJob::FetchUrls() {
} else {
URLFetcher* fetcher = new URLFetcher(
url_to_fetch.url, URLFetcher::URL_FETCH, this);
- if (url_to_fetch.existing_response_info.get()) {
- DCHECK(group_->newest_complete_cache());
+ if (url_to_fetch.existing_response_info.get() &&
+ group_->newest_complete_cache()) {
AppCacheEntry* existing_entry =
group_->newest_complete_cache()->GetEntry(url_to_fetch.url);
DCHECK(existing_entry);
@@ -1709,7 +1711,7 @@ void AppCacheUpdateJob::DeleteSoon() {
group_ = NULL;
}
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_update_job_unittest.cc b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
index 7564b9d4446..d7fae7a2162 100644
--- a/chromium/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
@@ -625,7 +625,9 @@ class AppCacheUpdateJobTest : public testing::Test,
// when it goes out of scope.
template <class Method>
void RunTestOnIOThread(Method method) {
- event_.reset(new base::WaitableEvent(false, false));
+ event_.reset(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED));
io_thread_->task_runner()->PostTask(
FROM_HERE, base::Bind(method, base::Unretained(this)));
diff --git a/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc b/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
index 15868aa770a..dbce38ddaf9 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
@@ -238,7 +238,9 @@ class AppCacheURLRequestJobTest : public testing::Test {
template <class Method>
void RunTestOnIOThread(Method method) {
- test_finished_event_ .reset(new base::WaitableEvent(false, false));
+ test_finished_event_.reset(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED));
io_thread_->task_runner()->PostTask(
FROM_HERE, base::Bind(&AppCacheURLRequestJobTest::MethodWrapper<Method>,
base::Unretained(this), method));
diff --git a/chromium/content/browser/background_sync/background_sync_manager.cc b/chromium/content/browser/background_sync/background_sync_manager.cc
index 9afe9148e8f..fadb79c8f8a 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager.cc
@@ -17,6 +17,7 @@
#include "content/browser/background_sync/background_sync_metrics.h"
#include "content/browser/background_sync/background_sync_network_observer.h"
#include "content/browser/background_sync/background_sync_registration_options.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/storage_partition_impl.h"
@@ -51,7 +52,7 @@ void RecordFailureAndPostError(
// Returns nullptr if the browser context cannot be accessed for any reason.
BrowserContext* GetBrowserContextOnUIThread(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) {
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!service_worker_context)
@@ -66,11 +67,11 @@ BrowserContext* GetBrowserContextOnUIThread(
// Returns nullptr if the controller cannot be accessed for any reason.
BackgroundSyncController* GetBackgroundSyncControllerOnUIThread(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) {
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserContext* browser_context =
- GetBrowserContextOnUIThread(service_worker_context);
+ GetBrowserContextOnUIThread(std::move(service_worker_context));
if (!browser_context)
return nullptr;
@@ -80,12 +81,12 @@ BackgroundSyncController* GetBackgroundSyncControllerOnUIThread(
// Returns PermissionStatus::DENIED if the permission manager cannot be
// accessed for any reason.
blink::mojom::PermissionStatus GetBackgroundSyncPermissionOnUIThread(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
const GURL& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserContext* browser_context =
- GetBrowserContextOnUIThread(service_worker_context);
+ GetBrowserContextOnUIThread(std::move(service_worker_context));
if (!browser_context)
return blink::mojom::PermissionStatus::DENIED;
@@ -100,12 +101,12 @@ blink::mojom::PermissionStatus GetBackgroundSyncPermissionOnUIThread(
}
void NotifyBackgroundSyncRegisteredOnUIThread(
- const scoped_refptr<ServiceWorkerContextWrapper>& sw_context_wrapper,
+ scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
const GURL& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BackgroundSyncController* background_sync_controller =
- GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);
+ GetBackgroundSyncControllerOnUIThread(std::move(sw_context_wrapper));
if (!background_sync_controller)
return;
@@ -114,7 +115,7 @@ void NotifyBackgroundSyncRegisteredOnUIThread(
}
void RunInBackgroundOnUIThread(
- const scoped_refptr<ServiceWorkerContextWrapper>& sw_context_wrapper,
+ scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
bool enabled,
int64_t min_ms) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -127,7 +128,7 @@ void RunInBackgroundOnUIThread(
}
std::unique_ptr<BackgroundSyncParameters> GetControllerParameters(
- const scoped_refptr<ServiceWorkerContextWrapper>& sw_context_wrapper,
+ scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
std::unique_ptr<BackgroundSyncParameters> parameters) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -145,11 +146,10 @@ std::unique_ptr<BackgroundSyncParameters> GetControllerParameters(
return parameters;
}
-void OnSyncEventFinished(
- const scoped_refptr<ServiceWorkerVersion>& active_version,
- int request_id,
- const ServiceWorkerVersion::StatusCallback& callback,
- blink::mojom::ServiceWorkerEventStatus status) {
+void OnSyncEventFinished(scoped_refptr<ServiceWorkerVersion> active_version,
+ int request_id,
+ const ServiceWorkerVersion::StatusCallback& callback,
+ blink::mojom::ServiceWorkerEventStatus status) {
if (!active_version->FinishRequest(
request_id,
status == blink::mojom::ServiceWorkerEventStatus::COMPLETED)) {
@@ -174,7 +174,7 @@ BackgroundSyncManager::BackgroundSyncRegistrations::
// static
std::unique_ptr<BackgroundSyncManager> BackgroundSyncManager::Create(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) {
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BackgroundSyncManager* sync_manager =
@@ -259,8 +259,22 @@ void BackgroundSyncManager::SetMaxSyncAttemptsForTesting(int max_attempts) {
weak_ptr_factory_.GetWeakPtr(), max_attempts, MakeEmptyCompletion()));
}
+void BackgroundSyncManager::EmulateDispatchSyncEvent(
+ const std::string& tag,
+ scoped_refptr<ServiceWorkerVersion> active_version,
+ bool last_chance,
+ const ServiceWorkerVersion::StatusCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DispatchSyncEvent(
+ tag, std::move(active_version),
+ last_chance
+ ? blink::mojom::BackgroundSyncEventLastChance::IS_LAST_CHANCE
+ : blink::mojom::BackgroundSyncEventLastChance::IS_NOT_LAST_CHANCE,
+ callback);
+}
+
BackgroundSyncManager::BackgroundSyncManager(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
: service_worker_context_(service_worker_context),
parameters_(new BackgroundSyncParameters()),
disabled_(false),
@@ -736,13 +750,13 @@ void BackgroundSyncManager::GetDataFromBackend(
void BackgroundSyncManager::DispatchSyncEvent(
const std::string& tag,
- const scoped_refptr<ServiceWorkerVersion>& active_version,
+ scoped_refptr<ServiceWorkerVersion> active_version,
blink::mojom::BackgroundSyncEventLastChance last_chance,
const ServiceWorkerVersion::StatusCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(active_version);
- if (active_version->running_status() != ServiceWorkerVersion::RUNNING) {
+ if (active_version->running_status() != EmbeddedWorkerStatus::RUNNING) {
active_version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::SYNC,
base::Bind(&BackgroundSyncManager::DispatchSyncEvent,
@@ -761,9 +775,9 @@ void BackgroundSyncManager::DispatchSyncEvent(
->GetMojoServiceForRequest<blink::mojom::BackgroundSyncServiceClient>(
request_id);
- client->Sync(
- tag, last_chance,
- base::Bind(&OnSyncEventFinished, active_version, request_id, callback));
+ client->Sync(tag, last_chance,
+ base::Bind(&OnSyncEventFinished, std::move(active_version),
+ request_id, callback));
}
void BackgroundSyncManager::ScheduleDelayedTask(const base::Closure& callback,
@@ -1010,7 +1024,7 @@ void BackgroundSyncManager::FireReadyEventsAllEventsFiring(
// |service_worker_registration| is just to keep the registration alive
// while the event is firing.
void BackgroundSyncManager::EventComplete(
- const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
int64_t service_worker_id,
const std::string& tag,
const base::Closure& callback,
diff --git a/chromium/content/browser/background_sync/background_sync_manager.h b/chromium/content/browser/background_sync/background_sync_manager.h
index e834495b88a..9b8b77396bc 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.h
+++ b/chromium/content/browser/background_sync/background_sync_manager.h
@@ -64,7 +64,7 @@ class CONTENT_EXPORT BackgroundSyncManager
std::unique_ptr<ScopedVector<BackgroundSyncRegistration>>)>;
static std::unique_ptr<BackgroundSyncManager> Create(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context);
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
~BackgroundSyncManager() override;
// Stores the given background sync registration and adds it to the scheduling
@@ -102,9 +102,16 @@ class CONTENT_EXPORT BackgroundSyncManager
clock_ = std::move(clock);
}
+ // Called from DevTools
+ void EmulateDispatchSyncEvent(
+ const std::string& tag,
+ scoped_refptr<ServiceWorkerVersion> active_version,
+ bool last_chance,
+ const ServiceWorkerVersion::StatusCallback& callback);
+
protected:
explicit BackgroundSyncManager(
- const scoped_refptr<ServiceWorkerContextWrapper>& context);
+ scoped_refptr<ServiceWorkerContextWrapper> context);
// Init must be called before any public member function. Only call it once.
void Init();
@@ -122,7 +129,7 @@ class CONTENT_EXPORT BackgroundSyncManager
callback);
virtual void DispatchSyncEvent(
const std::string& tag,
- const scoped_refptr<ServiceWorkerVersion>& active_version,
+ scoped_refptr<ServiceWorkerVersion> active_version,
blink::mojom::BackgroundSyncEventLastChance last_chance,
const ServiceWorkerVersion::StatusCallback& callback);
virtual void ScheduleDelayedTask(const base::Closure& callback,
@@ -247,12 +254,12 @@ class CONTENT_EXPORT BackgroundSyncManager
void FireReadyEventsAllEventsFiring(const base::Closure& callback);
// Called when a sync event has completed.
- void EventComplete(const scoped_refptr<ServiceWorkerRegistration>&
- service_worker_registration,
- int64_t service_worker_id,
- const std::string& tag,
- const base::Closure& callback,
- ServiceWorkerStatusCode status_code);
+ void EventComplete(
+ scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
+ int64_t service_worker_id,
+ const std::string& tag,
+ const base::Closure& callback,
+ ServiceWorkerStatusCode status_code);
void EventCompleteImpl(int64_t service_worker_id,
const std::string& tag,
ServiceWorkerStatusCode status_code,
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 f4acfb7f31d..cfe3f78266c 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 4dbddeecb04..2846089b450 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
@@ -63,7 +63,7 @@ void ErrorAndRegistrationCallback(
blink::mojom::BackgroundSyncError* out_error,
blink::mojom::SyncRegistrationPtr* out_registration,
blink::mojom::BackgroundSyncError error,
- const blink::mojom::SyncRegistrationPtr& registration) {
+ blink::mojom::SyncRegistrationPtr registration) {
*called = true;
*out_error = error;
*out_registration = registration.Clone();
@@ -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());
}
diff --git a/chromium/content/browser/bad_message.h b/chromium/content/browser/bad_message.h
index e96735a122a..d5f1d67d05d 100644
--- a/chromium/content/browser/bad_message.h
+++ b/chromium/content/browser/bad_message.h
@@ -28,7 +28,7 @@ enum BadMessageReason {
RFH_NO_PROXY_TO_PARENT = 4,
RPH_DESERIALIZATION_FAILED = 5,
RVH_CAN_ACCESS_FILES_OF_PAGE_STATE = 6,
- RVH_FILE_CHOOSER_PATH = 7,
+ RFH_FILE_CHOOSER_PATH = 7,
RWH_SYNTHETIC_GESTURE = 8,
RWH_FOCUS = 9, // obsolete; no longer used
RWH_BLUR = 10,
@@ -85,7 +85,7 @@ enum BadMessageReason {
SWDH_PROVIDER_CREATED_NO_HOST = 61,
SWDH_PROVIDER_DESTROYED_NO_HOST = 62,
SWDH_SET_HOSTED_VERSION_NO_HOST = 63,
- SWDH_SET_HOSTED_VERSION = 64,
+ OBSOLETE_SWDH_SET_HOSTED_VERSION = 64,
SWDH_WORKER_SCRIPT_LOAD_NO_HOST = 65,
SWDH_INCREMENT_WORKER_BAD_HANDLE = 66,
SWDH_DECREMENT_WORKER_BAD_HANDLE = 67,
@@ -144,6 +144,14 @@ enum BadMessageReason {
RFH_FAIL_PROVISIONAL_LOAD_NO_HANDLE = 120,
RFH_FAIL_PROVISIONAL_LOAD_NO_ERROR = 121,
NI_IN_PAGE_NAVIGATION = 122,
+ RPH_MOJO_PROCESS_ERROR = 123,
+ DBMF_INVALID_ORIGIN_ON_GET_SPACE = 124,
+ DBMF_INVALID_ORIGIN_ON_MODIFIED = 125,
+ DBMF_INVALID_ORIGIN_ON_CLOSED = 126,
+ WSH_INVALID_HEADER_VALUE = 127,
+ SWDH_SET_HOSTED_VERSION_INVALID_HOST = 128,
+ SWDH_SET_HOSTED_VERSION_PROCESS_MISMATCH = 129,
+ MSDH_INVALID_FRAME_ID = 130,
// 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 2851c50b613..e8c6c8523c3 100644
--- a/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc
+++ b/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc
@@ -12,7 +12,6 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/service_registry.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"
@@ -21,6 +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"
// These tests run against a dummy implementation of the BatteryMonitor service.
// That is, they verify that the service implementation is correctly exposed to
@@ -54,13 +54,11 @@ class FakeBatteryMonitor : public device::BatteryMonitor {
}
private:
- typedef mojo::Callback<void(device::BatteryStatusPtr)> BatteryStatusCallback;
-
FakeBatteryMonitor(mojo::InterfaceRequest<BatteryMonitor> request)
: binding_(this, std::move(request)) {}
~FakeBatteryMonitor() override {}
- void QueryNextStatus(const BatteryStatusCallback& callback) override {
+ void QueryNextStatus(const QueryNextStatusCallback& callback) override {
// We don't expect overlapped calls to QueryNextStatus.
DCHECK(callback_.is_null());
@@ -78,21 +76,23 @@ class FakeBatteryMonitor : public device::BatteryMonitor {
void DidChange(const device::BatteryStatus& battery_status) {
if (!callback_.is_null()) {
callback_.Run(battery_status.Clone());
- callback_.reset();
+ callback_.Reset();
}
}
std::unique_ptr<BatteryUpdateSubscription> subscription_;
mojo::StrongBinding<BatteryMonitor> binding_;
- BatteryStatusCallback callback_;
+ QueryNextStatusCallback callback_;
};
// Overrides the default service implementation with the test implementation
// declared above.
class TestContentBrowserClient : public ContentBrowserClient {
public:
- void RegisterRenderProcessMojoServices(ServiceRegistry* registry) override {
- registry->AddService(base::Bind(&FakeBatteryMonitor::Create));
+ void ExposeInterfacesToRenderer(
+ shell::InterfaceRegistry* registry,
+ RenderProcessHost* render_process_host) override {
+ registry->AddInterface(base::Bind(&FakeBatteryMonitor::Create));
}
void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
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 55dc6681b6a..ccd53246c44 100644
--- a/chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc
@@ -5,12 +5,12 @@
#include "content/browser/blob_storage/blob_dispatcher_host.h"
#include <memory>
+#include <tuple>
#include <vector>
#include "base/command_line.h"
#include "base/memory/shared_memory.h"
#include "base/run_loop.h"
-#include "base/tuple.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"
@@ -185,13 +185,13 @@ class BlobDispatcherHostTest : public testing::Test {
const IPC::Message* message =
sink_.GetUniqueMessageMatching(BlobStorageMsg_RequestMemoryItem::ID);
ASSERT_TRUE(message);
- base::Tuple<std::string, std::vector<storage::BlobItemBytesRequest>,
- std::vector<base::SharedMemoryHandle>,
- std::vector<IPC::PlatformFileForTransit>>
+ std::tuple<std::string, std::vector<storage::BlobItemBytesRequest>,
+ std::vector<base::SharedMemoryHandle>,
+ std::vector<IPC::PlatformFileForTransit>>
args;
BlobStorageMsg_RequestMemoryItem::Read(message, &args);
- EXPECT_EQ(expected_uuid, base::get<0>(args));
- std::vector<BlobItemBytesRequest> requests = base::get<1>(args);
+ EXPECT_EQ(expected_uuid, std::get<0>(args));
+ std::vector<BlobItemBytesRequest> requests = std::get<1>(args);
ASSERT_EQ(requests.size(), expected_requests.size());
for (size_t i = 0; i < expected_requests.size(); ++i) {
EXPECT_EQ(expected_requests[i], requests[i]);
@@ -209,18 +209,18 @@ class BlobDispatcherHostTest : public testing::Test {
const IPC::Message* message =
sink_.GetUniqueMessageMatching(BlobStorageMsg_RequestMemoryItem::ID);
ASSERT_TRUE(message);
- base::Tuple<std::string, std::vector<storage::BlobItemBytesRequest>,
- std::vector<base::SharedMemoryHandle>,
- std::vector<IPC::PlatformFileForTransit>>
+ std::tuple<std::string, std::vector<storage::BlobItemBytesRequest>,
+ std::vector<base::SharedMemoryHandle>,
+ std::vector<IPC::PlatformFileForTransit>>
args;
BlobStorageMsg_RequestMemoryItem::Read(message, &args);
- EXPECT_EQ(expected_uuid, base::get<0>(args));
- std::vector<BlobItemBytesRequest> requests = base::get<1>(args);
+ EXPECT_EQ(expected_uuid, std::get<0>(args));
+ std::vector<BlobItemBytesRequest> requests = std::get<1>(args);
ASSERT_EQ(requests.size(), expected_requests.size());
for (size_t i = 0; i < expected_requests.size(); ++i) {
EXPECT_EQ(expected_requests[i], requests[i]);
}
- *shared_memory_handles = std::move(base::get<2>(args));
+ *shared_memory_handles = std::move(std::get<2>(args));
}
void ExpectCancel(const std::string& expected_uuid,
@@ -232,10 +232,10 @@ class BlobDispatcherHostTest : public testing::Test {
const IPC::Message* message =
sink_.GetUniqueMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID);
ASSERT_TRUE(message);
- base::Tuple<std::string, IPCBlobCreationCancelCode> args;
+ std::tuple<std::string, IPCBlobCreationCancelCode> args;
BlobStorageMsg_CancelBuildingBlob::Read(message, &args);
- EXPECT_EQ(expected_uuid, base::get<0>(args));
- EXPECT_EQ(code, base::get<1>(args));
+ EXPECT_EQ(expected_uuid, std::get<0>(args));
+ EXPECT_EQ(code, std::get<1>(args));
}
void ExpectDone(const std::string& expected_uuid) {
@@ -245,9 +245,9 @@ class BlobDispatcherHostTest : public testing::Test {
sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID));
const IPC::Message* message =
sink_.GetUniqueMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID);
- base::Tuple<std::string> args;
+ std::tuple<std::string> args;
BlobStorageMsg_DoneBuildingBlob::Read(message, &args);
- EXPECT_EQ(expected_uuid, base::get<0>(args));
+ EXPECT_EQ(expected_uuid, std::get<0>(args));
}
bool IsBeingBuiltInHost(const std::string& uuid) {
diff --git a/chromium/content/browser/blob_storage/blob_reader_unittest.cc b/chromium/content/browser/blob_storage/blob_reader_unittest.cc
index 8c2fe4107a2..07de8e208ae 100644
--- a/chromium/content/browser/blob_storage/blob_reader_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_reader_unittest.cc
@@ -424,6 +424,7 @@ TEST_F(BlobReaderTest, BasicMemory) {
EXPECT_FALSE(IsReaderTotalSizeCalculated());
EXPECT_EQ(BlobReader::Status::DONE,
reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+ EXPECT_TRUE(reader_->IsInMemory());
CheckSizeCalculatedSynchronously(kDataSize, size_result);
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kDataSize));
@@ -454,6 +455,7 @@ TEST_F(BlobReaderTest, BasicFile) {
EXPECT_FALSE(IsReaderTotalSizeCalculated());
EXPECT_EQ(BlobReader::Status::DONE,
reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+ EXPECT_FALSE(reader_->IsInMemory());
CheckSizeCalculatedSynchronously(kData.size(), size_result);
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
@@ -476,7 +478,6 @@ TEST_F(BlobReaderTest, BasicFileSystem) {
const base::Time kTime = base::Time::Now();
b.AppendFileSystemFile(kURL, 0, kData.size(), kTime);
this->InitializeReader(&b);
-
// Non-async reader.
ExpectFileSystemCall(kURL, 0, kData.size(), kTime,
new FakeFileStreamReader(kData));
@@ -485,6 +486,8 @@ TEST_F(BlobReaderTest, BasicFileSystem) {
EXPECT_FALSE(IsReaderTotalSizeCalculated());
EXPECT_EQ(BlobReader::Status::DONE,
reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+ EXPECT_FALSE(reader_->IsInMemory());
+
CheckSizeCalculatedSynchronously(kData.size(), size_result);
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
@@ -719,6 +722,7 @@ TEST_F(BlobReaderTest, FileAsync) {
EXPECT_FALSE(IsReaderTotalSizeCalculated());
EXPECT_EQ(BlobReader::Status::IO_PENDING,
reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+ EXPECT_FALSE(reader_->IsInMemory());
CheckSizeNotCalculatedYet(size_result);
message_loop_.RunUntilIdle();
CheckSizeCalculatedAsynchronously(kData.size(), size_result);
@@ -755,6 +759,7 @@ TEST_F(BlobReaderTest, FileSystemAsync) {
EXPECT_EQ(BlobReader::Status::IO_PENDING,
reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
CheckSizeNotCalculatedYet(size_result);
+ EXPECT_FALSE(reader_->IsInMemory());
message_loop_.RunUntilIdle();
CheckSizeCalculatedAsynchronously(kData.size(), size_result);
@@ -1178,6 +1183,7 @@ TEST_F(BlobReaderTest, HandleBeforeAsyncCancel) {
int size_result = -1;
EXPECT_EQ(BlobReader::Status::IO_PENDING,
reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+ EXPECT_FALSE(reader_->IsInMemory());
context_.CancelPendingBlob(kUuid, IPCBlobCreationCancelCode::UNKNOWN);
message_loop_.RunUntilIdle();
EXPECT_EQ(net::ERR_FAILED, size_result);
@@ -1198,6 +1204,7 @@ TEST_F(BlobReaderTest, ReadFromIncompleteBlob) {
int size_result = -1;
EXPECT_EQ(BlobReader::Status::IO_PENDING,
reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+ EXPECT_FALSE(reader_->IsInMemory());
context_.CompletePendingBlob(b);
message_loop_.RunUntilIdle();
CheckSizeCalculatedAsynchronously(kDataSize, size_result);
diff --git a/chromium/content/browser/bluetooth/bluetooth_adapter_factory_wrapper.cc b/chromium/content/browser/bluetooth/bluetooth_adapter_factory_wrapper.cc
new file mode 100644
index 00000000000..5623d5177fc
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_adapter_factory_wrapper.cc
@@ -0,0 +1,146 @@
+// 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/bluetooth/bluetooth_adapter_factory_wrapper.h"
+
+#include <stddef.h>
+
+#include <utility>
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "content/public/browser/browser_thread.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+
+using device::BluetoothAdapter;
+using device::BluetoothAdapterFactory;
+
+namespace {
+// TODO(ortuno): Once we have a chooser for scanning and a way to control that
+// chooser from tests we should delete this constant.
+// https://crbug.com/436280
+enum { kTestingScanDuration = 0 }; // No need to wait when testing.
+enum { kScanDuration = 10 };
+} // namespace
+
+namespace content {
+
+BluetoothAdapterFactoryWrapper::BluetoothAdapterFactoryWrapper()
+ : scan_duration_(base::TimeDelta::FromSecondsD(kScanDuration)),
+ testing_(false),
+ weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+BluetoothAdapterFactoryWrapper::~BluetoothAdapterFactoryWrapper() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // All observers should have been removed already.
+ DCHECK(adapter_observers_.empty());
+ // Clear adapter.
+ set_adapter(scoped_refptr<device::BluetoothAdapter>());
+}
+
+bool BluetoothAdapterFactoryWrapper::IsBluetoothAdapterAvailable() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return BluetoothAdapterFactory::IsBluetoothAdapterAvailable() || testing_;
+}
+
+void BluetoothAdapterFactoryWrapper::AcquireAdapter(
+ device::BluetoothAdapter::Observer* observer,
+ const AcquireAdapterCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!GetAdapter(observer));
+
+ AddAdapterObserver(observer);
+ if (adapter_.get()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, base::Unretained(adapter_.get())));
+ return;
+ }
+
+ DCHECK(BluetoothAdapterFactory::IsBluetoothAdapterAvailable());
+ BluetoothAdapterFactory::GetAdapter(
+ base::Bind(&BluetoothAdapterFactoryWrapper::OnGetAdapter,
+ weak_ptr_factory_.GetWeakPtr(), callback));
+}
+
+void BluetoothAdapterFactoryWrapper::ReleaseAdapter(
+ device::BluetoothAdapter::Observer* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!HasAdapter(observer)) {
+ return;
+ }
+ RemoveAdapterObserver(observer);
+ if (adapter_observers_.empty())
+ set_adapter(scoped_refptr<device::BluetoothAdapter>());
+}
+
+BluetoothAdapter* BluetoothAdapterFactoryWrapper::GetAdapter(
+ device::BluetoothAdapter::Observer* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (HasAdapter(observer)) {
+ return adapter_.get();
+ }
+ return nullptr;
+}
+
+void BluetoothAdapterFactoryWrapper::SetBluetoothAdapterForTesting(
+ scoped_refptr<device::BluetoothAdapter> mock_adapter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ scan_duration_ = base::TimeDelta::FromSecondsD(kTestingScanDuration);
+ testing_ = true;
+ set_adapter(std::move(mock_adapter));
+}
+
+void BluetoothAdapterFactoryWrapper::OnGetAdapter(
+ const AcquireAdapterCallback& continuation,
+ scoped_refptr<device::BluetoothAdapter> adapter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ set_adapter(adapter);
+ continuation.Run(adapter_.get());
+}
+
+bool BluetoothAdapterFactoryWrapper::HasAdapter(
+ device::BluetoothAdapter::Observer* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return ContainsKey(adapter_observers_, observer);
+}
+
+void BluetoothAdapterFactoryWrapper::AddAdapterObserver(
+ device::BluetoothAdapter::Observer* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ auto iter = adapter_observers_.insert(observer);
+ DCHECK(iter.second);
+ if (adapter_) {
+ adapter_->AddObserver(observer);
+ }
+}
+
+void BluetoothAdapterFactoryWrapper::RemoveAdapterObserver(
+ device::BluetoothAdapter::Observer* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ size_t removed = adapter_observers_.erase(observer);
+ DCHECK(removed);
+ if (adapter_) {
+ adapter_->RemoveObserver(observer);
+ }
+}
+
+void BluetoothAdapterFactoryWrapper::set_adapter(
+ scoped_refptr<device::BluetoothAdapter> adapter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (adapter_.get()) {
+ for (device::BluetoothAdapter::Observer* observer : adapter_observers_) {
+ adapter_->RemoveObserver(observer);
+ }
+ }
+ adapter_ = adapter;
+ if (adapter_.get()) {
+ for (device::BluetoothAdapter::Observer* observer : adapter_observers_) {
+ adapter_->AddObserver(observer);
+ }
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_adapter_factory_wrapper.h b/chromium/content/browser/bluetooth/bluetooth_adapter_factory_wrapper.h
new file mode 100644
index 00000000000..233802ca0eb
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_adapter_factory_wrapper.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_ADAPTER_FACTORY_WRAPPER_H_
+#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_ADAPTER_FACTORY_WRAPPER_H_
+
+#include <unordered_set>
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+
+namespace content {
+
+class WebBluetoothServiceImpl;
+
+// Wrapper around BluetoothAdapterFactory that allows us to change
+// the underlying BluetoothAdapter object and have the observers
+// observe the new instance of the object.
+// TODO(ortuno): Once there is no need to swap the adapter to change its
+// behavior observers should add/remove themselves to/from the adapter.
+// http://crbug.com/603291
+class CONTENT_EXPORT BluetoothAdapterFactoryWrapper final {
+ public:
+ typedef base::Callback<void(device::BluetoothAdapter*)>
+ AcquireAdapterCallback;
+
+ BluetoothAdapterFactoryWrapper();
+ ~BluetoothAdapterFactoryWrapper();
+
+ // Returns true if the platform supports Bluetooth or if
+ // SetBluetoothAdapterForTesting has been called.
+ bool IsBluetoothAdapterAvailable();
+
+ // Adds |observer| to the set of adapter observers. If another observer has
+ // acquired the adapter in the past it adds |observer| as an observer to that
+ // adapter, otherwise it gets a new adapter and adds |observer| to it. Runs
+ // |callback| with the adapter |observer| has been added to.
+ void AcquireAdapter(device::BluetoothAdapter::Observer* observer,
+ const AcquireAdapterCallback& callback);
+ // Removes |observer| from the list of adapter observers if |observer|
+ // has acquired the adapter in the past. If there are no more observers
+ // it deletes the reference to the adapter.
+ void ReleaseAdapter(device::BluetoothAdapter::Observer* observer);
+
+ // Returns an adapter if |observer| has acquired an adapter in the past and
+ // this instance holds a reference to an adapter. Otherwise returns nullptr.
+ device::BluetoothAdapter* GetAdapter(
+ device::BluetoothAdapter::Observer* observer);
+
+ // The period of time a device discovery session should be active for.
+ // Returns 0 if SetBluetoothAdapterForTesting has been called.
+ base::TimeDelta GetScanDuration() { return scan_duration_; }
+
+ // Sets a new BluetoothAdapter to be returned by GetAdapter. When setting
+ // a new adapter all observers from the old adapter are removed and added
+ // to |mock_adapter|.
+ void SetBluetoothAdapterForTesting(
+ scoped_refptr<device::BluetoothAdapter> mock_adapter);
+
+ private:
+ void OnGetAdapter(const AcquireAdapterCallback& continuation,
+ scoped_refptr<device::BluetoothAdapter> adapter);
+
+ bool HasAdapter(device::BluetoothAdapter::Observer* observer);
+ void AddAdapterObserver(device::BluetoothAdapter::Observer* observer);
+ void RemoveAdapterObserver(device::BluetoothAdapter::Observer* observer);
+
+ // Sets |adapter_| to a BluetoothAdapter instance and register observers,
+ // releasing references to previous |adapter_|.
+ void set_adapter(scoped_refptr<device::BluetoothAdapter> adapter);
+
+ // A BluetoothAdapter instance representing an adapter of the system.
+ scoped_refptr<device::BluetoothAdapter> adapter_;
+
+ // We keep a list of all observers so that when the adapter gets swapped,
+ // we can remove all observers from the old adapter and add them to the
+ // new adapter.
+ std::unordered_set<device::BluetoothAdapter::Observer*> adapter_observers_;
+
+ // This is 0 if SetBluetoothAdapterForTesting has been called.
+ base::TimeDelta scan_duration_;
+
+ bool testing_;
+
+ // 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
+ // invalidate its weak pointers before any other members are destroyed.
+ base::WeakPtrFactory<BluetoothAdapterFactoryWrapper> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterFactoryWrapper);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_ADAPTER_FACTORY_WRAPPER_H_
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
index cd2e78929a3..1e8f79b115a 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
@@ -8,12 +8,11 @@
#include "base/base64.h"
#include "base/logging.h"
+#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "content/browser/bluetooth/bluetooth_blacklist.h"
-#include "content/common/bluetooth/bluetooth_scan_filter.h"
#include "crypto/random.h"
-#include "device/bluetooth/bluetooth_uuid.h"
using device::BluetoothUUID;
@@ -42,18 +41,11 @@ BluetoothAllowedDevicesMap::~BluetoothAllowedDevicesMap() {}
const std::string& BluetoothAllowedDevicesMap::AddDevice(
const url::Origin& origin,
const std::string& device_address,
- const std::vector<BluetoothScanFilter>& filters,
- const std::vector<BluetoothUUID>& optional_services) {
+ const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
VLOG(1) << "Adding a device to Map of Allowed Devices.";
- // "Unique" Origins generate the same key in maps. The set of "unique"
- // Origins that generate the same key does not intersect the set of
- // potentially trustworthy origins; since Bluetooth is only available for
- // potntially trustworthy origins we should never receive a request from a
- // "unique" Origin.
- // See url::Origin for what constitutes a "unique" Origin and the
- // Secure Contexts spec for what constitutes a Trusworthy Origin:
- // https://w3c.github.io/webappsec-secure-contexts/
+ // "Unique" Origins generate the same key in maps, therefore are not
+ // supported.
CHECK(!origin.unique());
auto device_address_to_id_map = origin_to_device_address_to_id_map_[origin];
@@ -63,8 +55,7 @@ const std::string& BluetoothAllowedDevicesMap::AddDevice(
const auto& device_id = id_iter->second;
AddUnionOfServicesTo(
- filters, optional_services,
- &origin_to_device_id_to_services_map_[origin][device_id]);
+ options, &origin_to_device_id_to_services_map_[origin][device_id]);
return origin_to_device_address_to_id_map_[origin][device_address];
}
@@ -74,8 +65,7 @@ const std::string& BluetoothAllowedDevicesMap::AddDevice(
origin_to_device_address_to_id_map_[origin][device_address] = device_id;
origin_to_device_id_to_address_map_[origin][device_id] = device_address;
AddUnionOfServicesTo(
- filters, optional_services,
- &origin_to_device_id_to_services_map_[origin][device_id]);
+ options, &origin_to_device_id_to_services_map_[origin][device_id]);
CHECK(device_id_set_.insert(device_id).second);
@@ -140,9 +130,10 @@ const std::string& BluetoothAllowedDevicesMap::GetDeviceAddress(
bool BluetoothAllowedDevicesMap::IsOriginAllowedToAccessService(
const url::Origin& origin,
const std::string& device_id,
- const std::string& service_uuid) const {
- if (BluetoothBlacklist::Get().IsExcluded(BluetoothUUID(service_uuid)))
+ const BluetoothUUID& service_uuid) const {
+ if (BluetoothBlacklist::Get().IsExcluded(service_uuid)) {
return false;
+ }
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()) {
@@ -168,16 +159,16 @@ std::string BluetoothAllowedDevicesMap::GenerateDeviceId() {
}
void BluetoothAllowedDevicesMap::AddUnionOfServicesTo(
- const std::vector<BluetoothScanFilter>& filters,
- const std::vector<device::BluetoothUUID>& optional_services,
- std::set<std::string>* unionOfServices) {
- for (const auto& filter : filters) {
- for (const BluetoothUUID& uuid : filter.services) {
- unionOfServices->insert(uuid.canonical_value());
+ 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());
}
}
- for (const BluetoothUUID& uuid : optional_services) {
- unionOfServices->insert(uuid.canonical_value());
+ for (const base::Optional<BluetoothUUID>& uuid : options->optional_services) {
+ unionOfServices->insert(uuid.value());
}
}
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h
index 2f585f8b903..396f7293c8a 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h
@@ -8,9 +8,11 @@
#include <map>
#include <memory>
#include <set>
+#include <unordered_set>
#include <vector>
#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
#include "url/origin.h"
namespace device {
@@ -32,12 +34,13 @@ class CONTENT_EXPORT BluetoothAllowedDevicesMap final {
~BluetoothAllowedDevicesMap();
// Adds the Bluetooth Device with |device_address| to the map of allowed
- // devices for that origin. Generates and returns a device id.
+ // devices for that origin. Generates and returns a device id. Because
+ // unique origins generate the same hash, unique origins are not supported.
+ // Calling this function with a unique origin will CHECK-fail.
const std::string& AddDevice(
const url::Origin& origin,
const std::string& device_address,
- const std::vector<BluetoothScanFilter>& filters,
- const std::vector<device::BluetoothUUID>& optional_services);
+ const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options);
// Removes the Bluetooth Device with |device_address| from the map of allowed
// devices for |origin|.
@@ -56,23 +59,31 @@ class CONTENT_EXPORT BluetoothAllowedDevicesMap final {
// Returns true if the origin has previously been granted access to
// the service.
- bool IsOriginAllowedToAccessService(const url::Origin& origin,
- const std::string& device_id,
- const std::string& service_uuid) const;
+ bool IsOriginAllowedToAccessService(
+ const url::Origin& origin,
+ const std::string& device_id,
+ const device::BluetoothUUID& service_uuid) const;
private:
typedef std::map<std::string, std::string> DeviceAddressToIdMap;
typedef std::map<std::string, std::string> DeviceIdToAddressMap;
- typedef std::map<std::string, std::set<std::string>> DeviceIdToServicesMap;
+ typedef std::map<
+ std::string,
+ std::unordered_set<device::BluetoothUUID, device::BluetoothUUIDHash>>
+ DeviceIdToServicesMap;
// Returns an id guaranteed to be unique for the map. The id is randomly
// generated so that an origin can't guess the id used in another origin.
std::string GenerateDeviceId();
void AddUnionOfServicesTo(
- const std::vector<BluetoothScanFilter>& filters,
- const std::vector<device::BluetoothUUID>& optional_services,
- std::set<std::string>* unionOfServices);
-
+ const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options,
+ std::unordered_set<device::BluetoothUUID, device::BluetoothUUIDHash>*
+ unionOfServices);
+
+ // TODO(ortuno): Now that there is only one instance of this class per frame
+ // and that this map gets destroyed when navigating consider removing the
+ // origin mapping.
+ // http://crbug.com/610343
std::map<url::Origin, DeviceAddressToIdMap>
origin_to_device_address_to_id_map_;
std::map<url::Origin, DeviceIdToAddressMap>
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 925d1a1393f..58b98d96793 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
@@ -5,8 +5,6 @@
#include "content/browser/bluetooth/bluetooth_allowed_devices_map.h"
#include "base/strings/string_util.h"
-#include "content/common/bluetooth/bluetooth_scan_filter.h"
-#include "device/bluetooth/bluetooth_uuid.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -31,17 +29,32 @@ const BluetoothUUID kBatteryServiceUUID(kBatteryServiceUUIDString);
const BluetoothUUID kBloodPressureUUID(kBloodPressureUUIDString);
const BluetoothUUID kCyclingPowerUUID(kCyclingPowerUUIDString);
-const std::vector<content::BluetoothScanFilter> kEmptyFilters =
- std::vector<BluetoothScanFilter>();
-const std::vector<device::BluetoothUUID> kEmptyOptionalServices =
- std::vector<device::BluetoothUUID>();
+class BluetoothAllowedDevicesMapTest : public testing::Test {
+ protected:
+ BluetoothAllowedDevicesMapTest() {
+ empty_options_ = blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ }
+
+ ~BluetoothAllowedDevicesMapTest() override {}
+
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr empty_options_;
+};
+
} // namespace
-TEST(BluetoothAllowedDevicesMapTest, AddDeviceToMap) {
+TEST_F(BluetoothAllowedDevicesMapTest, UniqueOriginNotSupported) {
+ BluetoothAllowedDevicesMap allowed_devices_map;
+
+ EXPECT_DEATH_IF_SUPPORTED(allowed_devices_map.AddDevice(
+ url::Origin(), kDeviceAddress1, empty_options_),
+ "");
+}
+
+TEST_F(BluetoothAllowedDevicesMapTest, AddDeviceToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
// Test that we can retrieve the device address/id.
EXPECT_EQ(device_id,
@@ -50,12 +63,12 @@ TEST(BluetoothAllowedDevicesMapTest, AddDeviceToMap) {
allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id));
}
-TEST(BluetoothAllowedDevicesMapTest, AddDeviceToMapTwice) {
+TEST_F(BluetoothAllowedDevicesMapTest, AddDeviceToMapTwice) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id1 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
const std::string& device_id2 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
EXPECT_EQ(device_id1, device_id2);
@@ -66,12 +79,12 @@ TEST(BluetoothAllowedDevicesMapTest, AddDeviceToMapTwice) {
allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id1));
}
-TEST(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromSameOriginToMap) {
+TEST_F(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromSameOriginToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id1 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
const std::string& device_id2 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress2, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress2, empty_options_);
EXPECT_NE(device_id1, device_id2);
@@ -87,12 +100,12 @@ TEST(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromSameOriginToMap) {
allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id2));
}
-TEST(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromTwoOriginsToMap) {
+TEST_F(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromTwoOriginsToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id1 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
const std::string& device_id2 = allowed_devices_map.AddDevice(
- kTestOrigin2, kDeviceAddress2, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin2, kDeviceAddress2, empty_options_);
EXPECT_NE(device_id1, device_id2);
@@ -120,12 +133,12 @@ TEST(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromTwoOriginsToMap) {
allowed_devices_map.GetDeviceAddress(kTestOrigin2, device_id2));
}
-TEST(BluetoothAllowedDevicesMapTest, AddDeviceFromTwoOriginsToMap) {
+TEST_F(BluetoothAllowedDevicesMapTest, AddDeviceFromTwoOriginsToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id1 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
const std::string& device_id2 = allowed_devices_map.AddDevice(
- kTestOrigin2, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin2, kDeviceAddress1, empty_options_);
EXPECT_NE(device_id1, device_id2);
@@ -136,24 +149,24 @@ TEST(BluetoothAllowedDevicesMapTest, AddDeviceFromTwoOriginsToMap) {
allowed_devices_map.GetDeviceAddress(kTestOrigin2, device_id1));
}
-TEST(BluetoothAllowedDevicesMapTest, AddRemoveAddDeviceToMap) {
+TEST_F(BluetoothAllowedDevicesMapTest, AddRemoveAddDeviceToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string device_id_first_time = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
allowed_devices_map.RemoveDevice(kTestOrigin1, kDeviceAddress1);
const std::string device_id_second_time = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
EXPECT_NE(device_id_first_time, device_id_second_time);
}
-TEST(BluetoothAllowedDevicesMapTest, RemoveDeviceFromMap) {
+TEST_F(BluetoothAllowedDevicesMapTest, RemoveDeviceFromMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
allowed_devices_map.RemoveDevice(kTestOrigin1, kDeviceAddress1);
@@ -163,237 +176,260 @@ TEST(BluetoothAllowedDevicesMapTest, RemoveDeviceFromMap) {
kTestOrigin1, kDeviceAddress1));
}
-TEST(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginOneDevice) {
+TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginOneDevice) {
BluetoothAllowedDevicesMap allowed_devices_map;
// Setup device.
- BluetoothScanFilter scanFilter1;
- scanFilter1.services.push_back(kGlucoseUUID);
- BluetoothScanFilter scanFilter2;
- scanFilter2.services.push_back(kHeartRateUUID);
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ blink::mojom::WebBluetoothScanFilterPtr scanFilter1 =
+ blink::mojom::WebBluetoothScanFilter::New();
+ blink::mojom::WebBluetoothScanFilterPtr scanFilter2 =
+ blink::mojom::WebBluetoothScanFilter::New();
+
+ scanFilter1->services.push_back(kGlucoseUUID);
+ options->filters.push_back(scanFilter1.Clone());
- std::vector<BluetoothScanFilter> filters;
- filters.push_back(scanFilter1);
- filters.push_back(scanFilter2);
+ scanFilter2->services.push_back(kHeartRateUUID);
+ options->filters.push_back(scanFilter2.Clone());
- std::vector<BluetoothUUID> optional_services;
- optional_services.push_back(kBatteryServiceUUID);
- optional_services.push_back(kHeartRateUUID);
+ options->optional_services.push_back(kBatteryServiceUUID);
+ options->optional_services.push_back(kHeartRateUUID);
// Add to map.
- const std::string device_id1 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, filters, optional_services);
+ const std::string device_id1 =
+ allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options);
// Access allowed services.
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kGlucoseUUIDString));
+ kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kHeartRateUUIDString));
+ kTestOrigin1, device_id1, kHeartRateUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+ kTestOrigin1, device_id1, kBatteryServiceUUID));
// Try to access a non-allowed service.
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBloodPressureUUIDString));
+ kTestOrigin1, device_id1, kBloodPressureUUID));
// Try to access allowed services after removing device.
allowed_devices_map.RemoveDevice(kTestOrigin1, kDeviceAddress1);
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kGlucoseUUIDString));
+ kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kHeartRateUUIDString));
+ kTestOrigin1, device_id1, kHeartRateUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+ kTestOrigin1, device_id1, kBatteryServiceUUID));
// Add device back.
- const std::string device_id2 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, filters, kEmptyOptionalServices);
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options2 =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+
+ options2->filters.push_back(scanFilter1.Clone());
+ options2->filters.push_back(scanFilter2.Clone());
+
+ const std::string device_id2 =
+ allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options2);
// Access allowed services.
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kGlucoseUUIDString));
+ kTestOrigin1, device_id2, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kHeartRateUUIDString));
+ kTestOrigin1, device_id2, kHeartRateUUID));
// Try to access a non-allowed service.
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kBatteryServiceUUIDString));
+ kTestOrigin1, device_id2, kBatteryServiceUUID));
// Try to access services from old device.
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kGlucoseUUIDString));
+ kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kHeartRateUUIDString));
+ kTestOrigin1, device_id1, kHeartRateUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+ kTestOrigin1, device_id1, kBatteryServiceUUID));
}
-TEST(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginTwoDevices) {
+TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginTwoDevices) {
BluetoothAllowedDevicesMap allowed_devices_map;
// Setup request for device #1.
- BluetoothScanFilter scanFilter1;
- scanFilter1.services.push_back(kGlucoseUUID);
- std::vector<BluetoothScanFilter> filters1;
- filters1.push_back(scanFilter1);
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options1 =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ blink::mojom::WebBluetoothScanFilterPtr scanFilter1 =
+ blink::mojom::WebBluetoothScanFilter::New();
+
+ scanFilter1->services.push_back(kGlucoseUUID);
+ options1->filters.push_back(std::move(scanFilter1));
- std::vector<BluetoothUUID> optional_services1;
- optional_services1.push_back(kHeartRateUUID);
+ options1->optional_services.push_back(kHeartRateUUID);
// Setup request for device #2.
- BluetoothScanFilter scanFilter2;
- scanFilter2.services.push_back(kBatteryServiceUUID);
- std::vector<BluetoothScanFilter> filters2;
- filters2.push_back(scanFilter2);
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options2 =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ blink::mojom::WebBluetoothScanFilterPtr scanFilter2 =
+ blink::mojom::WebBluetoothScanFilter::New();
- std::vector<BluetoothUUID> optional_services2;
- optional_services2.push_back(kBloodPressureUUID);
+ scanFilter2->services.push_back(kBatteryServiceUUID);
+ options2->filters.push_back(std::move(scanFilter2));
+
+ options2->optional_services.push_back(kBloodPressureUUID);
// Add devices to map.
- const std::string& device_id1 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, filters1, optional_services1);
- const std::string& device_id2 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress2, filters2, optional_services2);
+ const std::string& device_id1 =
+ allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options1);
+ const std::string& device_id2 =
+ allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress2, options2);
// Access allowed services.
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kGlucoseUUIDString));
+ kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kHeartRateUUIDString));
+ kTestOrigin1, device_id1, kHeartRateUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kBatteryServiceUUIDString));
+ kTestOrigin1, device_id2, kBatteryServiceUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kBloodPressureUUIDString));
+ kTestOrigin1, device_id2, kBloodPressureUUID));
// Try to access non-allowed services.
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+ kTestOrigin1, device_id1, kBatteryServiceUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBloodPressureUUIDString));
+ kTestOrigin1, device_id1, kBloodPressureUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kCyclingPowerUUIDString));
+ kTestOrigin1, device_id1, kCyclingPowerUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kGlucoseUUIDString));
+ kTestOrigin1, device_id2, kGlucoseUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kHeartRateUUIDString));
+ kTestOrigin1, device_id2, kHeartRateUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kCyclingPowerUUIDString));
+ kTestOrigin1, device_id2, kCyclingPowerUUID));
}
-TEST(BluetoothAllowedDevicesMapTest, AllowedServices_TwoOriginsOneDevice) {
+TEST_F(BluetoothAllowedDevicesMapTest, AllowedServices_TwoOriginsOneDevice) {
BluetoothAllowedDevicesMap allowed_devices_map;
// Setup request #1 for device.
- BluetoothScanFilter scanFilter1;
- scanFilter1.services.push_back(kGlucoseUUID);
- std::vector<BluetoothScanFilter> filters1;
- filters1.push_back(scanFilter1);
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options1 =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ blink::mojom::WebBluetoothScanFilterPtr scanFilter1 =
+ blink::mojom::WebBluetoothScanFilter::New();
- std::vector<BluetoothUUID> optional_services1;
- optional_services1.push_back(kHeartRateUUID);
+ scanFilter1->services.push_back(kGlucoseUUID);
+ options1->filters.push_back(std::move(scanFilter1));
+
+ options1->optional_services.push_back(kHeartRateUUID);
// Setup request #2 for device.
- BluetoothScanFilter scanFilter2;
- scanFilter2.services.push_back(kBatteryServiceUUID);
- std::vector<BluetoothScanFilter> filters2;
- filters2.push_back(scanFilter2);
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options2 =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ blink::mojom::WebBluetoothScanFilterPtr scanFilter2 =
+ blink::mojom::WebBluetoothScanFilter::New();
+
+ scanFilter2->services.push_back(kBatteryServiceUUID);
+ options2->filters.push_back(std::move(scanFilter2));
- std::vector<BluetoothUUID> optional_services2;
- optional_services2.push_back(kBloodPressureUUID);
+ options2->optional_services.push_back(kBloodPressureUUID);
// Add devices to map.
- const std::string& device_id1 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, filters1, optional_services1);
- const std::string& device_id2 = allowed_devices_map.AddDevice(
- kTestOrigin2, kDeviceAddress1, filters2, optional_services2);
+ const std::string& device_id1 =
+ allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options1);
+ const std::string& device_id2 =
+ allowed_devices_map.AddDevice(kTestOrigin2, kDeviceAddress1, options2);
// Access allowed services.
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kGlucoseUUIDString));
+ kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kHeartRateUUIDString));
+ kTestOrigin1, device_id1, kHeartRateUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin2, device_id2, kBatteryServiceUUIDString));
+ kTestOrigin2, device_id2, kBatteryServiceUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin2, device_id2, kBloodPressureUUIDString));
+ kTestOrigin2, device_id2, kBloodPressureUUID));
// Try to access non-allowed services.
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+ kTestOrigin1, device_id1, kBatteryServiceUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBloodPressureUUIDString));
+ kTestOrigin1, device_id1, kBloodPressureUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kGlucoseUUIDString));
+ kTestOrigin1, device_id2, kGlucoseUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kHeartRateUUIDString));
+ kTestOrigin1, device_id2, kHeartRateUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kBatteryServiceUUIDString));
+ kTestOrigin1, device_id2, kBatteryServiceUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id2, kBloodPressureUUIDString));
+ kTestOrigin1, device_id2, kBloodPressureUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin2, device_id2, kGlucoseUUIDString));
+ kTestOrigin2, device_id2, kGlucoseUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin2, device_id2, kHeartRateUUIDString));
+ kTestOrigin2, device_id2, kHeartRateUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin2, device_id1, kGlucoseUUIDString));
+ kTestOrigin2, device_id1, kGlucoseUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin2, device_id1, kHeartRateUUIDString));
+ kTestOrigin2, device_id1, kHeartRateUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin2, device_id1, kBatteryServiceUUIDString));
+ kTestOrigin2, device_id1, kBatteryServiceUUID));
EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin2, device_id1, kBloodPressureUUIDString));
+ kTestOrigin2, device_id1, kBloodPressureUUID));
}
-TEST(BluetoothAllowedDevicesMapTest, MergeServices) {
+TEST_F(BluetoothAllowedDevicesMapTest, MergeServices) {
BluetoothAllowedDevicesMap allowed_devices_map;
// Setup first request.
- BluetoothScanFilter scanFilter1;
- scanFilter1.services.push_back(kGlucoseUUID);
- std::vector<BluetoothScanFilter> filters1;
- filters1.push_back(scanFilter1);
- std::vector<BluetoothUUID> optional_services1;
- optional_services1.push_back(kBatteryServiceUUID);
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options1 =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ blink::mojom::WebBluetoothScanFilterPtr scanFilter1 =
+ blink::mojom::WebBluetoothScanFilter::New();
+
+ scanFilter1->services.push_back(kGlucoseUUID);
+ options1->filters.push_back(std::move(scanFilter1));
+
+ options1->optional_services.push_back(kBatteryServiceUUID);
// Add to map.
- const std::string device_id1 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, filters1, optional_services1);
+ const std::string device_id1 =
+ allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options1);
// Setup second request.
- BluetoothScanFilter scanFilter2;
- scanFilter2.services.push_back(kHeartRateUUID);
- std::vector<BluetoothScanFilter> filters2;
- filters2.push_back(scanFilter2);
- std::vector<BluetoothUUID> optional_services2;
- optional_services2.push_back(kBloodPressureUUID);
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options2 =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+ blink::mojom::WebBluetoothScanFilterPtr scanFilter2 =
+ blink::mojom::WebBluetoothScanFilter::New();
+
+ scanFilter2->services.push_back(kHeartRateUUID);
+ options2->filters.push_back(std::move(scanFilter2));
+
+ options2->optional_services.push_back(kBloodPressureUUID);
// Add to map again.
- const std::string device_id2 = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, filters2, optional_services2);
+ const std::string device_id2 =
+ allowed_devices_map.AddDevice(kTestOrigin1, kDeviceAddress1, options2);
EXPECT_EQ(device_id1, device_id2);
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kGlucoseUUIDString));
+ kTestOrigin1, device_id1, kGlucoseUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+ kTestOrigin1, device_id1, kBatteryServiceUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kHeartRateUUIDString));
+ kTestOrigin1, device_id1, kHeartRateUUID));
EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
- kTestOrigin1, device_id1, kBloodPressureUUIDString));
+ kTestOrigin1, device_id1, kBloodPressureUUID));
}
-TEST(BluetoothAllowedDevicesMapTest, CorrectIdFormat) {
+TEST_F(BluetoothAllowedDevicesMapTest, CorrectIdFormat) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id = allowed_devices_map.AddDevice(
- kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
+ kTestOrigin1, kDeviceAddress1, empty_options_);
EXPECT_TRUE(device_id.size() == 24)
<< "Expected Lenghth of a 128bit string encoded to Base64.";
diff --git a/chromium/content/browser/bluetooth/bluetooth_blacklist.cc b/chromium/content/browser/bluetooth/bluetooth_blacklist.cc
index 6564c4c4b90..7508f128624 100644
--- a/chromium/content/browser/bluetooth/bluetooth_blacklist.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_blacklist.cc
@@ -6,8 +6,8 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
#include "base/strings/string_split.h"
-#include "content/common/bluetooth/bluetooth_scan_filter.h"
#include "content/public/browser/content_browser_client.h"
using device::BluetoothUUID;
@@ -33,7 +33,7 @@ BluetoothBlacklist& BluetoothBlacklist::Get() {
return g_singleton.Get();
}
-void BluetoothBlacklist::Add(const device::BluetoothUUID& uuid, Value value) {
+void BluetoothBlacklist::Add(const BluetoothUUID& uuid, Value value) {
CHECK(uuid.IsValid());
auto insert_result = blacklisted_uuids_.insert(std::make_pair(uuid, value));
bool inserted = insert_result.second;
@@ -86,10 +86,10 @@ bool BluetoothBlacklist::IsExcluded(const BluetoothUUID& uuid) const {
}
bool BluetoothBlacklist::IsExcluded(
- const std::vector<content::BluetoothScanFilter>& filters) {
- for (const BluetoothScanFilter& filter : filters) {
- for (const BluetoothUUID& service : filter.services) {
- if (IsExcluded(service)) {
+ const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
+ for (const blink::mojom::WebBluetoothScanFilterPtr& filter : filters) {
+ for (const base::Optional<BluetoothUUID>& service : filter->services) {
+ if (IsExcluded(service.value())) {
return true;
}
}
@@ -113,16 +113,16 @@ bool BluetoothBlacklist::IsExcludedFromWrites(const BluetoothUUID& uuid) const {
return it->second == Value::EXCLUDE || it->second == Value::EXCLUDE_WRITES;
}
-void BluetoothBlacklist::RemoveExcludedUuids(
- std::vector<device::BluetoothUUID>* uuids) {
- auto it = uuids->begin();
- while (it != uuids->end()) {
- if (IsExcluded(*it)) {
- it = uuids->erase(it);
- } else {
- it++;
+void BluetoothBlacklist::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);
}
}
+ options->optional_services = std::move(optional_services_blacklist_filtered);
}
void BluetoothBlacklist::ResetToDefaultValuesForTest() {
diff --git a/chromium/content/browser/bluetooth/bluetooth_blacklist.h b/chromium/content/browser/bluetooth/bluetooth_blacklist.h
index d363d86cfb9..ebc01dafe63 100644
--- a/chromium/content/browser/bluetooth/bluetooth_blacklist.h
+++ b/chromium/content/browser/bluetooth/bluetooth_blacklist.h
@@ -13,11 +13,10 @@
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
#include "device/bluetooth/bluetooth_uuid.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
namespace content {
-struct BluetoothScanFilter;
-
// Implements the Web Bluetooth Blacklist policy as defined in the Web Bluetooth
// specification:
// https://webbluetoothcg.github.io/web-bluetooth/#the-gatt-blacklist
@@ -65,7 +64,8 @@ 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 std::vector<content::BluetoothScanFilter>&);
+ bool IsExcluded(
+ const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters);
// Returns if a UUID is excluded from read operations. UUID must be valid.
bool IsExcludedFromReads(const device::BluetoothUUID&) const;
@@ -73,8 +73,10 @@ class CONTENT_EXPORT BluetoothBlacklist final {
// Returns if a UUID is excluded from write operations. UUID must be valid.
bool IsExcludedFromWrites(const device::BluetoothUUID&) const;
- // Modifies a list of UUIDs, removing any UUIDs with Value::EXCLUDE.
- void RemoveExcludedUuids(std::vector<device::BluetoothUUID>*);
+ // Modifies |options->optional_services|, removing any UUIDs with
+ // Value::EXCLUDE.
+ void RemoveExcludedUUIDs(
+ blink::mojom::WebBluetoothRequestDeviceOptions* options);
// Size of blacklist.
size_t size() { return blacklisted_uuids_.size(); }
diff --git a/chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc b/chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc
index b0ed9c2c6a1..d1ea654c0a9 100644
--- a/chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc
@@ -4,7 +4,6 @@
#include "content/browser/bluetooth/bluetooth_blacklist.h"
-#include "content/common/bluetooth/bluetooth_scan_filter.h"
#include "device/bluetooth/bluetooth_uuid.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -12,6 +11,14 @@ 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 {
public:
BluetoothBlacklistTest() : list_(BluetoothBlacklist::Get()) {
@@ -218,92 +225,143 @@ TEST_F(BluetoothBlacklistTest, IsExcluded_BluetoothScanFilter_ReturnsFalse) {
list_.Add(BluetoothUUID("ee01"), BluetoothBlacklist::Value::EXCLUDE_READS);
list_.Add(BluetoothUUID("ee02"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
{
- std::vector<BluetoothScanFilter> empty_filters;
+ mojo::Array<blink::mojom::WebBluetoothScanFilterPtr> empty_filters;
EXPECT_FALSE(list_.IsExcluded(empty_filters));
}
{
- std::vector<BluetoothScanFilter> single_empty_filter(1);
- EXPECT_EQ(0u, single_empty_filter[0].services.size());
+ mojo::Array<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>>();
+
+ EXPECT_EQ(0u, single_empty_filter[0]->services.size());
EXPECT_FALSE(list_.IsExcluded(single_empty_filter));
}
{
- std::vector<BluetoothScanFilter> single_non_matching_filter(1);
- single_non_matching_filter[0].services.push_back(BluetoothUUID("0000"));
+ mojo::Array<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"));
+
EXPECT_FALSE(list_.IsExcluded(single_non_matching_filter));
}
{
- std::vector<BluetoothScanFilter> multiple_non_matching_filter(2);
- multiple_non_matching_filter[0].services.push_back(BluetoothUUID("0000"));
- multiple_non_matching_filter[0].services.push_back(BluetoothUUID("ee01"));
- multiple_non_matching_filter[1].services.push_back(BluetoothUUID("ee02"));
- multiple_non_matching_filter[1].services.push_back(BluetoothUUID("0003"));
- EXPECT_FALSE(list_.IsExcluded(multiple_non_matching_filter));
+ mojo::Array<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[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"));
+
+ EXPECT_FALSE(list_.IsExcluded(multiple_non_matching_filters));
}
}
TEST_F(BluetoothBlacklistTest, IsExcluded_BluetoothScanFilter_ReturnsTrue) {
list_.Add(BluetoothUUID("eeee"), BluetoothBlacklist::Value::EXCLUDE);
{
- std::vector<BluetoothScanFilter> single_matching_filter(1);
- single_matching_filter[0].services.push_back(BluetoothUUID("eeee"));
+ 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"));
+
EXPECT_TRUE(list_.IsExcluded(single_matching_filter));
}
{
- std::vector<BluetoothScanFilter> first_matching_filter(2);
- first_matching_filter[0].services.push_back(BluetoothUUID("eeee"));
- first_matching_filter[0].services.push_back(BluetoothUUID("0001"));
- first_matching_filter[1].services.push_back(BluetoothUUID("0002"));
- first_matching_filter[1].services.push_back(BluetoothUUID("0003"));
+ mojo::Array<blink::mojom::WebBluetoothScanFilterPtr> first_matching_filter(
+ 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[1] = blink::mojom::WebBluetoothScanFilter::New();
+ first_matching_filter[1]->services.push_back(Canonicalize("0002"));
+ first_matching_filter[1]->services.push_back(Canonicalize("0003"));
+
EXPECT_TRUE(list_.IsExcluded(first_matching_filter));
}
{
- std::vector<BluetoothScanFilter> last_matching_filter(2);
- last_matching_filter[0].services.push_back(BluetoothUUID("0001"));
- last_matching_filter[0].services.push_back(BluetoothUUID("0001"));
- last_matching_filter[1].services.push_back(BluetoothUUID("0002"));
- last_matching_filter[1].services.push_back(BluetoothUUID("eeee"));
+ mojo::Array<blink::mojom::WebBluetoothScanFilterPtr> last_matching_filter(
+ 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[1] = blink::mojom::WebBluetoothScanFilter::New();
+ last_matching_filter[1]->services.push_back(Canonicalize("0002"));
+ last_matching_filter[1]->services.push_back(Canonicalize("eeee"));
+
EXPECT_TRUE(list_.IsExcluded(last_matching_filter));
}
{
- std::vector<BluetoothScanFilter> multiple_matching_filter(2);
- multiple_matching_filter[0].services.push_back(BluetoothUUID("eeee"));
- multiple_matching_filter[0].services.push_back(BluetoothUUID("eeee"));
- multiple_matching_filter[1].services.push_back(BluetoothUUID("eeee"));
- multiple_matching_filter[1].services.push_back(BluetoothUUID("eeee"));
- EXPECT_TRUE(list_.IsExcluded(multiple_matching_filter));
+ mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>
+ 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[1] = blink::mojom::WebBluetoothScanFilter::New();
+ multiple_matching_filters[1]->services.push_back(Canonicalize("eeee"));
+ multiple_matching_filters[1]->services.push_back(Canonicalize("eeee"));
+
+ EXPECT_TRUE(list_.IsExcluded(multiple_matching_filters));
}
}
-TEST_F(BluetoothBlacklistTest, RemoveExcludedUuids_NonMatching) {
+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);
+
+ // options.optional_services should be the same before and after
+ // RemoveExcludedUUIDs().
{
- std::vector<BluetoothUUID> empty;
- std::vector<BluetoothUUID> expected_empty;
- list_.RemoveExcludedUuids(&empty);
- EXPECT_EQ(expected_empty, empty);
- }
- {
- std::vector<BluetoothUUID> single_non_matching;
- single_non_matching.push_back(BluetoothUUID("0000"));
+ // Empty optional_services.
+ blink::mojom::WebBluetoothRequestDeviceOptions options;
+ options.optional_services = mojo::Array<base::Optional<BluetoothUUID>>();
- std::vector<BluetoothUUID> expected_copy(single_non_matching);
+ mojo::Array<base::Optional<BluetoothUUID>> expected =
+ options.optional_services.Clone();
- list_.RemoveExcludedUuids(&single_non_matching);
- EXPECT_EQ(expected_copy, single_non_matching);
+ list_.RemoveExcludedUUIDs(&options);
+ EXPECT_TRUE(options.optional_services.Equals(expected));
}
{
- std::vector<BluetoothUUID> multiple_non_matching;
- multiple_non_matching.push_back(BluetoothUUID("0000"));
- multiple_non_matching.push_back(BluetoothUUID("ee01"));
- multiple_non_matching.push_back(BluetoothUUID("ee02"));
- multiple_non_matching.push_back(BluetoothUUID("0003"));
+ // One non-matching service in optional_services.
+ blink::mojom::WebBluetoothRequestDeviceOptions options;
+ options.optional_services.push_back(Canonicalize("0000"));
- std::vector<BluetoothUUID> expected_copy(multiple_non_matching);
+ mojo::Array<base::Optional<BluetoothUUID>> expected =
+ options.optional_services.Clone();
- list_.RemoveExcludedUuids(&multiple_non_matching);
- EXPECT_EQ(expected_copy, multiple_non_matching);
+ list_.RemoveExcludedUUIDs(&options);
+ EXPECT_TRUE(options.optional_services.Equals(expected));
+ }
+ {
+ // 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"));
+
+ mojo::Array<base::Optional<BluetoothUUID>> expected =
+ options.optional_services.Clone();
+
+ list_.RemoveExcludedUUIDs(&options);
+ EXPECT_TRUE(options.optional_services.Equals(expected));
}
}
@@ -313,38 +371,42 @@ TEST_F(BluetoothBlacklistTest, RemoveExcludedUuids_Matching) {
list_.Add(BluetoothUUID("eee3"), BluetoothBlacklist::Value::EXCLUDE);
list_.Add(BluetoothUUID("eee4"), BluetoothBlacklist::Value::EXCLUDE);
{
- std::vector<BluetoothUUID> single_matching;
- single_matching.push_back(BluetoothUUID("eeee"));
+ // Single matching service in optional_services.
+ blink::mojom::WebBluetoothRequestDeviceOptions options;
+ options.optional_services.push_back(Canonicalize("eeee"));
- std::vector<BluetoothUUID> expected_empty;
+ mojo::Array<base::Optional<BluetoothUUID>> expected;
- list_.RemoveExcludedUuids(&single_matching);
- EXPECT_EQ(expected_empty, single_matching);
+ list_.RemoveExcludedUUIDs(&options);
+
+ EXPECT_TRUE(options.optional_services.Equals(expected));
}
{
- std::vector<BluetoothUUID> single_matching_of_many;
- single_matching_of_many.push_back(BluetoothUUID("0000"));
- single_matching_of_many.push_back(BluetoothUUID("eeee"));
- single_matching_of_many.push_back(BluetoothUUID("0001"));
-
- std::vector<BluetoothUUID> expected;
- expected.push_back(BluetoothUUID("0000"));
- expected.push_back(BluetoothUUID("0001"));
-
- list_.RemoveExcludedUuids(&single_matching_of_many);
- EXPECT_EQ(expected, single_matching_of_many);
+ // 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"));
+
+ mojo::Array<base::Optional<BluetoothUUID>> expected;
+ expected.push_back(Canonicalize("0000"));
+ expected.push_back(Canonicalize("0001"));
+
+ list_.RemoveExcludedUUIDs(&options);
+ EXPECT_TRUE(options.optional_services.Equals(expected));
}
{
- std::vector<BluetoothUUID> all_matching_of_many;
- all_matching_of_many.push_back(BluetoothUUID("eee2"));
- all_matching_of_many.push_back(BluetoothUUID("eee4"));
- all_matching_of_many.push_back(BluetoothUUID("eee3"));
- all_matching_of_many.push_back(BluetoothUUID("eeee"));
+ // 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"));
- std::vector<BluetoothUUID> expected_empty;
+ mojo::Array<base::Optional<BluetoothUUID>> expected;
- list_.RemoveExcludedUuids(&all_matching_of_many);
- EXPECT_EQ(expected_empty, all_matching_of_many);
+ list_.RemoveExcludedUUIDs(&options);
+ EXPECT_TRUE(options.optional_services.Equals(expected));
}
}
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
new file mode 100644
index 00000000000..34bf2d49085
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -0,0 +1,478 @@
+// 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/bluetooth/bluetooth_device_chooser_controller.h"
+
+#include <set>
+#include <string>
+#include <unordered_set>
+
+#include "base/bind.h"
+#include "base/bind_helpers.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_metrics.h"
+#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+#include "device/bluetooth/bluetooth_common.h"
+#include "device/bluetooth/bluetooth_discovery_session.h"
+
+using device::BluetoothUUID;
+
+namespace content {
+
+namespace {
+constexpr size_t kMaxLengthForDeviceName =
+ 29; // max length of device name in filter.
+
+void LogRequestDeviceOptions(
+ const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
+ VLOG(1) << "requestDevice called with the following filters: ";
+ int i = 0;
+ for (const auto& filter : options->filters) {
+ VLOG(1) << "Filter #" << ++i;
+ if (!filter->name.is_null())
+ VLOG(1) << "Name: " << filter->name;
+
+ if (!filter->name_prefix.is_null())
+ VLOG(1) << "Name Prefix: " << filter->name_prefix;
+
+ if (!filter->services.is_null()) {
+ VLOG(1) << "Services: ";
+ VLOG(1) << "\t[";
+ for (const auto& service : filter->services)
+ VLOG(1) << "\t\t" << service->canonical_value();
+ VLOG(1) << "\t]";
+ }
+ }
+}
+
+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())
+ 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)
+ return true;
+ if (!filter->name_prefix.is_null() &&
+ filter->name_prefix.size() > kMaxLengthForDeviceName)
+ return true;
+
+ return false;
+}
+
+bool HasEmptyOrInvalidFilter(
+ const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
+ return filters.empty()
+ ? true
+ : filters.end() != std::find_if(filters.begin(), filters.end(),
+ IsEmptyOrInvalidFilter);
+}
+
+bool MatchesFilter(const device::BluetoothDevice& device,
+ const blink::mojom::WebBluetoothScanFilterPtr& filter) {
+ DCHECK(!IsEmptyOrInvalidFilter(filter));
+
+ // TODO(615720): Use the upcoming GetName (was GetDeviceName).
+ const std::string device_name = base::UTF16ToUTF8(device.GetNameForDisplay());
+
+ if (!filter->name.is_null() && (device_name != filter->name)) {
+ return false;
+ }
+
+ if (!filter->name_prefix.is_null() &&
+ (!base::StartsWith(device_name, filter->name_prefix.get(),
+ base::CompareCase::SENSITIVE))) {
+ return false;
+ }
+
+ if (!filter->services.is_null()) {
+ const auto& device_uuid_list = device.GetUUIDs();
+ const std::unordered_set<BluetoothUUID, device::BluetoothUUIDHash>
+ device_uuids(device_uuid_list.begin(), device_uuid_list.end());
+ for (const base::Optional<BluetoothUUID>& service : filter->services) {
+ if (!ContainsKey(device_uuids, service.value())) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool MatchesFilters(
+ const device::BluetoothDevice& device,
+ const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
+ DCHECK(!HasEmptyOrInvalidFilter(filters));
+ for (const auto& filter : filters) {
+ if (MatchesFilter(device, filter)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+std::unique_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter(
+ const mojo::Array<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());
+ }
+ }
+ auto discovery_filter = base::MakeUnique<device::BluetoothDiscoveryFilter>(
+ device::BLUETOOTH_TRANSPORT_DUAL);
+ for (const BluetoothUUID& service : services) {
+ discovery_filter->AddUUID(service);
+ }
+ return discovery_filter;
+}
+
+void StopDiscoverySession(
+ std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
+ // Nothing goes wrong if the discovery session fails to stop, and we don't
+ // need to wait for it before letting the user's script proceed, so we ignore
+ // the results here.
+ discovery_session->Stop(base::Bind(&base::DoNothing),
+ base::Bind(&base::DoNothing));
+}
+
+UMARequestDeviceOutcome OutcomeFromChooserEvent(BluetoothChooser::Event event) {
+ switch (event) {
+ case BluetoothChooser::Event::DENIED_PERMISSION:
+ return UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_DENIED_PERMISSION;
+ case BluetoothChooser::Event::CANCELLED:
+ return UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_CANCELLED;
+ case BluetoothChooser::Event::SHOW_OVERVIEW_HELP:
+ return UMARequestDeviceOutcome::BLUETOOTH_OVERVIEW_HELP_LINK_PRESSED;
+ case BluetoothChooser::Event::SHOW_ADAPTER_OFF_HELP:
+ return UMARequestDeviceOutcome::ADAPTER_OFF_HELP_LINK_PRESSED;
+ case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP:
+ return UMARequestDeviceOutcome::NEED_LOCATION_HELP_LINK_PRESSED;
+ case BluetoothChooser::Event::SELECTED:
+ // We can't know if we are going to send a success message yet because
+ // the device could have vanished. This event should be histogramed
+ // manually after checking if the device is still around.
+ 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;
+ }
+ NOTREACHED();
+ return UMARequestDeviceOutcome::SUCCESS;
+}
+
+} // namespace
+
+BluetoothDeviceChooserController::BluetoothDeviceChooserController(
+ WebBluetoothServiceImpl* web_bluetooth_service,
+ RenderFrameHost* render_frame_host,
+ device::BluetoothAdapter* adapter,
+ base::TimeDelta scan_duration)
+ : adapter_(adapter),
+ web_bluetooth_service_(web_bluetooth_service),
+ render_frame_host_(render_frame_host),
+ web_contents_(WebContents::FromRenderFrameHost(render_frame_host_)),
+ discovery_session_timer_(
+ FROM_HERE,
+ // TODO(jyasskin): Add a way for tests to control the dialog
+ // directly, and change this to a reasonable discovery timeout.
+ scan_duration,
+ base::Bind(&BluetoothDeviceChooserController::StopDeviceDiscovery,
+ // base::Timer guarantees it won't call back after its
+ // destructor starts.
+ base::Unretained(this)),
+ /*is_repeating=*/false),
+ weak_ptr_factory_(this) {
+ CHECK(adapter_);
+}
+
+BluetoothDeviceChooserController::~BluetoothDeviceChooserController() {
+ if (chooser_) {
+ DCHECK(!error_callback_.is_null());
+ error_callback_.Run(blink::mojom::WebBluetoothError::CHOOSER_CANCELLED);
+ }
+}
+
+void BluetoothDeviceChooserController::GetDevice(
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
+ const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // GetDevice should only be called once.
+ DCHECK(success_callback_.is_null());
+ DCHECK(error_callback_.is_null());
+
+ success_callback_ = success_callback;
+ error_callback_ = error_callback;
+
+ // The renderer should never send empty filters.
+ if (HasEmptyOrInvalidFilter(options->filters)) {
+ web_bluetooth_service_->CrashRendererAndClosePipe(
+ bad_message::BDH_EMPTY_OR_INVALID_FILTERS);
+ return;
+ }
+ options_ = std::move(options);
+ LogRequestDeviceOptions(options_);
+
+ // Check blacklist to reject invalid filters and adjust optional_services.
+ if (BluetoothBlacklist::Get().IsExcluded(options_->filters)) {
+ RecordRequestDeviceOutcome(
+ UMARequestDeviceOutcome::BLACKLISTED_SERVICE_IN_FILTER);
+ PostErrorCallback(
+ blink::mojom::WebBluetoothError::REQUEST_DEVICE_WITH_BLACKLISTED_UUID);
+ return;
+ }
+ BluetoothBlacklist::Get().RemoveExcludedUUIDs(options_.get());
+
+ const url::Origin requesting_origin =
+ render_frame_host_->GetLastCommittedOrigin();
+ const url::Origin embedding_origin =
+ web_contents_->GetMainFrame()->GetLastCommittedOrigin();
+
+ // TODO(crbug.com/518042): Enforce correctly-delegated permissions instead of
+ // matching origins. When relaxing this, take care to handle non-sandboxed
+ // unique origins.
+ if (!embedding_origin.IsSameOriginWith(requesting_origin)) {
+ PostErrorCallback(blink::mojom::WebBluetoothError::
+ REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME);
+ return;
+ }
+ // The above also excludes unique origins, which are not even same-origin with
+ // themselves.
+ DCHECK(!requesting_origin.unique());
+
+ if (!adapter_->IsPresent()) {
+ VLOG(1) << "Bluetooth Adapter not present. Can't serve requestDevice.";
+ RecordRequestDeviceOutcome(
+ UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_NOT_PRESENT);
+ PostErrorCallback(blink::mojom::WebBluetoothError::NO_BLUETOOTH_ADAPTER);
+ return;
+ }
+
+ switch (GetContentClient()->browser()->AllowWebBluetooth(
+ web_contents_->GetBrowserContext(), requesting_origin,
+ embedding_origin)) {
+ case ContentBrowserClient::AllowWebBluetoothResult::BLOCK_POLICY: {
+ RecordRequestDeviceOutcome(
+ UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_POLICY_DISABLED);
+ PostErrorCallback(blink::mojom::WebBluetoothError::
+ CHOOSER_NOT_SHOWN_API_LOCALLY_DISABLED);
+ return;
+ }
+ case ContentBrowserClient::AllowWebBluetoothResult::
+ BLOCK_GLOBALLY_DISABLED: {
+ // Log to the developer console.
+ web_contents_->GetMainFrame()->AddMessageToConsole(
+ content::CONSOLE_MESSAGE_LEVEL_LOG,
+ "Bluetooth permission has been blocked.");
+ // Block requests.
+ RecordRequestDeviceOutcome(
+ UMARequestDeviceOutcome::BLUETOOTH_GLOBALLY_DISABLED);
+ PostErrorCallback(blink::mojom::WebBluetoothError::
+ CHOOSER_NOT_SHOWN_API_GLOBALLY_DISABLED);
+ return;
+ }
+ case ContentBrowserClient::AllowWebBluetoothResult::ALLOW:
+ break;
+ }
+
+ BluetoothChooser::EventHandler chooser_event_handler =
+ base::Bind(&BluetoothDeviceChooserController::OnBluetoothChooserEvent,
+ base::Unretained(this));
+
+ if (WebContentsDelegate* delegate = web_contents_->GetDelegate()) {
+ chooser_ = delegate->RunBluetoothChooser(render_frame_host_,
+ chooser_event_handler);
+ }
+
+ if (!chooser_.get()) {
+ PostErrorCallback(
+ blink::mojom::WebBluetoothError::WEB_BLUETOOTH_NOT_SUPPORTED);
+ }
+
+ if (!chooser_->CanAskForScanningPermission()) {
+ VLOG(1) << "Closing immediately because Chooser cannot obtain permission.";
+ OnBluetoothChooserEvent(BluetoothChooser::Event::DENIED_PERMISSION,
+ "" /* device_address */);
+ return;
+ }
+
+ PopulateFoundDevices();
+ if (!chooser_.get()) {
+ // If the dialog's closing, no need to do any of the rest of this.
+ return;
+ }
+
+ if (!adapter_->IsPowered()) {
+ chooser_->SetAdapterPresence(
+ BluetoothChooser::AdapterPresence::POWERED_OFF);
+ return;
+ }
+
+ StartDeviceDiscovery();
+}
+
+void BluetoothDeviceChooserController::AddFilteredDevice(
+ const device::BluetoothDevice& device) {
+ if (chooser_.get() && MatchesFilters(device, options_->filters)) {
+ VLOG(1) << "Adding device to chooser: " << device.GetAddress();
+ chooser_->AddDevice(device.GetAddress(), device.GetNameForDisplay());
+ }
+}
+
+void BluetoothDeviceChooserController::AdapterPoweredChanged(bool powered) {
+ if (!powered && discovery_session_.get()) {
+ StopDiscoverySession(std::move(discovery_session_));
+ }
+
+ if (chooser_.get()) {
+ chooser_->SetAdapterPresence(
+ powered ? BluetoothChooser::AdapterPresence::POWERED_ON
+ : BluetoothChooser::AdapterPresence::POWERED_OFF);
+ if (powered) {
+ OnBluetoothChooserEvent(BluetoothChooser::Event::RESCAN,
+ "" /* device_address */);
+ }
+ }
+
+ if (!powered) {
+ discovery_session_timer_.Stop();
+ }
+}
+
+void BluetoothDeviceChooserController::PopulateFoundDevices() {
+ VLOG(1) << "Populating " << adapter_->GetDevices().size()
+ << " devices in chooser.";
+ for (const device::BluetoothDevice* device : adapter_->GetDevices()) {
+ AddFilteredDevice(*device);
+ }
+}
+
+void BluetoothDeviceChooserController::StartDeviceDiscovery() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (discovery_session_.get() && discovery_session_->IsActive()) {
+ // Already running; just increase the timeout.
+ discovery_session_timer_.Reset();
+ return;
+ }
+
+ chooser_->ShowDiscoveryState(BluetoothChooser::DiscoveryState::DISCOVERING);
+ adapter_->StartDiscoverySessionWithFilter(
+ ComputeScanFilter(options_->filters),
+ base::Bind(
+ &BluetoothDeviceChooserController::OnStartDiscoverySessionSuccess,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(
+ &BluetoothDeviceChooserController::OnStartDiscoverySessionFailed,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BluetoothDeviceChooserController::StopDeviceDiscovery() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ StopDiscoverySession(std::move(discovery_session_));
+ if (chooser_) {
+ chooser_->ShowDiscoveryState(BluetoothChooser::DiscoveryState::IDLE);
+ }
+}
+
+void BluetoothDeviceChooserController::OnStartDiscoverySessionSuccess(
+ std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ VLOG(1) << "Started discovery session.";
+ if (chooser_.get()) {
+ discovery_session_ = std::move(discovery_session);
+ discovery_session_timer_.Reset();
+ } else {
+ StopDiscoverySession(std::move(discovery_session));
+ }
+}
+
+void BluetoothDeviceChooserController::OnStartDiscoverySessionFailed() {
+ if (chooser_.get()) {
+ chooser_->ShowDiscoveryState(
+ BluetoothChooser::DiscoveryState::FAILED_TO_START);
+ }
+}
+
+void BluetoothDeviceChooserController::OnBluetoothChooserEvent(
+ BluetoothChooser::Event event,
+ const std::string& device_address) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Shouldn't recieve an event from a closed chooser.
+ DCHECK(chooser_.get());
+
+ switch (event) {
+ case BluetoothChooser::Event::RESCAN:
+ PopulateFoundDevices();
+ DCHECK(chooser_);
+ StartDeviceDiscovery();
+ // No need to close the chooser so we return.
+ return;
+ case BluetoothChooser::Event::DENIED_PERMISSION:
+ RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
+ PostErrorCallback(blink::mojom::WebBluetoothError::
+ CHOOSER_NOT_SHOWN_USER_DENIED_PERMISSION_TO_SCAN);
+ break;
+ case BluetoothChooser::Event::CANCELLED:
+ RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
+ PostErrorCallback(blink::mojom::WebBluetoothError::CHOOSER_CANCELLED);
+ break;
+ case BluetoothChooser::Event::SHOW_OVERVIEW_HELP:
+ VLOG(1) << "Overview Help link pressed.";
+ RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
+ PostErrorCallback(blink::mojom::WebBluetoothError::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);
+ break;
+ case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP:
+ VLOG(1) << "Need Location Help link pressed.";
+ RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
+ PostErrorCallback(blink::mojom::WebBluetoothError::CHOOSER_CANCELLED);
+ break;
+ case BluetoothChooser::Event::SELECTED:
+ PostSuccessCallback(device_address);
+ break;
+ }
+ // Close chooser.
+ chooser_.reset();
+}
+
+void BluetoothDeviceChooserController::PostSuccessCallback(
+ const std::string& device_address) {
+ if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(success_callback_, base::Passed(std::move(options_)),
+ device_address))) {
+ LOG(WARNING) << "No TaskRunner.";
+ }
+}
+
+void BluetoothDeviceChooserController::PostErrorCallback(
+ blink::mojom::WebBluetoothError error) {
+ if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(error_callback_, error))) {
+ LOG(WARNING) << "No TaskRunner.";
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
new file mode 100644
index 00000000000..dfa87248677
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.h
@@ -0,0 +1,148 @@
+// 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_BLUETOOTH_BLUETOOTH_DEVICE_CHOOSER_CONTROLLER_H_
+#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DEVICE_CHOOSER_CONTROLLER_H_
+
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "content/public/browser/bluetooth_chooser.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+
+namespace device {
+class BluetoothAdapter;
+class BluetoothDevice;
+class BluetoothDiscoveryFilter;
+class BluetoothDiscoverySession;
+}
+
+namespace content {
+
+class RenderFrameHost;
+class WebContents;
+class WebBluetoothServiceImpl;
+
+// Class that interacts with a chooser and starts a bluetooth discovery session.
+// This class needs to be re-instantiated for each call to GetDevice(). Calling
+// GetDevice() twice for the same instance will DCHECK.
+class BluetoothDeviceChooserController final {
+ public:
+ typedef base::Callback<void(blink::mojom::WebBluetoothRequestDeviceOptionsPtr,
+ const std::string& device_address)>
+ SuccessCallback;
+ typedef base::Callback<void(blink::mojom::WebBluetoothError error)>
+ ErrorCallback;
+
+ // |web_bluetooth_service_| service that owns this class.
+ // |render_frame_host| should be the RenderFrameHost that owns the
+ // |web_bluetooth_service_|.
+ // |adapter| should be the adapter used to scan for Bluetooth devices.
+ // |scan_duration| is how long will a discovery session be active.
+ BluetoothDeviceChooserController(
+ WebBluetoothServiceImpl* web_bluetooth_service_,
+ RenderFrameHost* render_frame_host,
+ device::BluetoothAdapter* adapter,
+ base::TimeDelta scan_duration);
+ ~BluetoothDeviceChooserController();
+
+ // This function performs the following checks before starting a discovery
+ // session:
+ // - Validates filters in |request_device_options|.
+ // - Removes any blacklisted 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.
+ // - Checks if the adapter is present.
+ // - Checks if the Web Bluetooth API has been disabled.
+ // - Checks if we are allowed to ask for scanning permission.
+ // If any of the previous checks failed then this function runs
+ // |error_callback| with the corresponding error. Otherwise this function
+ // populates the embedder provided BluetoothChooser with existing devices and
+ // starts a new discovery session.
+ // This function should only be called once per
+ // BluetoothDeviceChooserController instance. Calling this function more than
+ // once will DCHECK.
+ void GetDevice(
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr request_device_options,
+ const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback);
+
+ // Adds a device to the chooser. Should only be called after GetDevice and
+ // before either of the callbacks are run.
+ void AddFilteredDevice(const device::BluetoothDevice& device);
+
+ // Stops the current discovery session and notifies the chooser
+ // that the adapter changed states.
+ void AdapterPoweredChanged(bool powered);
+
+ private:
+ // Populates the chooser with the devices that are already in the adapter.
+ void PopulateFoundDevices();
+
+ // Notifies the chooser that discovery is starting and starts a discovery
+ // session.
+ void StartDeviceDiscovery();
+
+ // Stops the discovery session and notifies the chooser.
+ void StopDeviceDiscovery();
+
+ // StartDiscoverySessionWithFilter callbacks:
+ void OnStartDiscoverySessionSuccess(
+ std::unique_ptr<device::BluetoothDiscoverySession> discovery_session);
+ void OnStartDiscoverySessionFailed();
+
+ // BluetoothChooser::EventHandler:
+ // Runs error_callback_ if the chooser was cancelled or if we weren't able
+ // to show the chooser. Otherwise runs success_callback_ with
+ // |device_address|.
+ void OnBluetoothChooserEvent(BluetoothChooser::Event event,
+ const std::string& device_address);
+
+ // 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);
+
+ // The adapter used to get existing devices and start a discovery session.
+ device::BluetoothAdapter* adapter_;
+ // The WebBluetoothServiceImpl that owns this instance.
+ WebBluetoothServiceImpl* web_bluetooth_service_;
+ // The RenderFrameHost that owns web_bluetooth_service_.
+ RenderFrameHost* render_frame_host_;
+ // The WebContents that owns render_frame_host_.
+ WebContents* web_contents_;
+
+ // Contains the filters and optional services used when scanning.
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options_;
+
+ // Callbacks to be called with the result of the chooser.
+ SuccessCallback success_callback_;
+ ErrorCallback error_callback_;
+
+ // The currently opened BluetoothChooser.
+ std::unique_ptr<BluetoothChooser> chooser_;
+
+ // Automatically stops Bluetooth discovery a set amount of time after it was
+ // started.
+ base::Timer discovery_session_timer_;
+
+ // The last discovery session to be started.
+ // TODO(ortuno): This should be null unless there is an active discovery
+ // session. We need to null it when the platform stops discovery.
+ // http://crbug.com/611852
+ std::unique_ptr<device::BluetoothDiscoverySession> discovery_session_;
+
+ // 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
+ // invalidate its weak pointers before any other members are destroyed.
+ base::WeakPtrFactory<BluetoothDeviceChooserController> weak_ptr_factory_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DEVICE_CHOOSER_CONTROLLER_H_
diff --git a/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.cc b/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.cc
deleted file mode 100644
index 763838b8ba9..00000000000
--- a/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.cc
+++ /dev/null
@@ -1,779 +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.
-
-// ID Not In Map Note:
-// A service, characteristic, or descriptor ID not in the corresponding
-// BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_,
-// descriptor_to_characteristic_] implies a hostile renderer because a renderer
-// obtains the corresponding ID from this class and it will be added to the map
-// at that time.
-
-#include "content/browser/bluetooth/bluetooth_dispatcher_host.h"
-
-#include <stddef.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/bluetooth/bluetooth_blacklist.h"
-#include "content/browser/bluetooth/bluetooth_metrics.h"
-#include "content/browser/bluetooth/cache_query_result.h"
-#include "content/browser/bluetooth/first_device_bluetooth_chooser.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "device/bluetooth/bluetooth_adapter.h"
-#include "device/bluetooth/bluetooth_adapter_factory.h"
-#include "device/bluetooth/bluetooth_device.h"
-#include "device/bluetooth/bluetooth_discovery_session.h"
-
-using blink::WebBluetoothError;
-using device::BluetoothAdapter;
-using device::BluetoothAdapterFactory;
-using device::BluetoothUUID;
-
-namespace content {
-
-namespace {
-
-// TODO(ortuno): Once we have a chooser for scanning, a way to control that
-// chooser from tests, and the right callback for discovered services we should
-// delete these constants.
-// https://crbug.com/436280 and https://crbug.com/484504
-const int kDelayTime = 5; // 5 seconds for scanning and discovering
-const int kTestingDelayTime = 0; // No need to wait during tests
-const size_t kMaxLengthForDeviceName =
- 29; // max length of device name in filter.
-
-bool IsEmptyOrInvalidFilter(const content::BluetoothScanFilter& filter) {
- return filter.name.empty() && filter.namePrefix.empty() &&
- filter.services.empty() &&
- filter.name.length() > kMaxLengthForDeviceName &&
- filter.namePrefix.length() > kMaxLengthForDeviceName;
-}
-
-bool HasEmptyOrInvalidFilter(
- const std::vector<content::BluetoothScanFilter>& filters) {
- return filters.empty()
- ? true
- : filters.end() != std::find_if(filters.begin(), filters.end(),
- IsEmptyOrInvalidFilter);
-}
-
-// Defined at
-// https://webbluetoothchrome.github.io/web-bluetooth/#dfn-matches-a-filter
-bool MatchesFilter(const device::BluetoothDevice& device,
- const content::BluetoothScanFilter& filter) {
- DCHECK(!IsEmptyOrInvalidFilter(filter));
-
- const std::string device_name = base::UTF16ToUTF8(device.GetName());
-
- if (!filter.name.empty() && (device_name != filter.name)) {
- return false;
- }
-
- if (!filter.namePrefix.empty() &&
- (!base::StartsWith(device_name, filter.namePrefix,
- base::CompareCase::SENSITIVE))) {
- return false;
- }
-
- if (!filter.services.empty()) {
- const auto& device_uuid_list = device.GetUUIDs();
- const std::set<BluetoothUUID> device_uuids(device_uuid_list.begin(),
- device_uuid_list.end());
- for (const auto& service : filter.services) {
- if (!ContainsKey(device_uuids, service)) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool MatchesFilters(const device::BluetoothDevice& device,
- const std::vector<content::BluetoothScanFilter>& filters) {
- DCHECK(!HasEmptyOrInvalidFilter(filters));
- for (const content::BluetoothScanFilter& filter : filters) {
- if (MatchesFilter(device, filter)) {
- return true;
- }
- }
- return false;
-}
-
-void StopDiscoverySession(
- std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
- // Nothing goes wrong if the discovery session fails to stop, and we don't
- // need to wait for it before letting the user's script proceed, so we ignore
- // the results here.
- discovery_session->Stop(base::Bind(&base::DoNothing),
- base::Bind(&base::DoNothing));
-}
-
-UMARequestDeviceOutcome OutcomeFromChooserEvent(BluetoothChooser::Event event) {
- switch (event) {
- case BluetoothChooser::Event::DENIED_PERMISSION:
- return UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_DENIED_PERMISSION;
- case BluetoothChooser::Event::CANCELLED:
- return UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_CANCELLED;
- case BluetoothChooser::Event::SHOW_OVERVIEW_HELP:
- return UMARequestDeviceOutcome::BLUETOOTH_OVERVIEW_HELP_LINK_PRESSED;
- case BluetoothChooser::Event::SHOW_ADAPTER_OFF_HELP:
- return UMARequestDeviceOutcome::ADAPTER_OFF_HELP_LINK_PRESSED;
- case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP:
- return UMARequestDeviceOutcome::NEED_LOCATION_HELP_LINK_PRESSED;
- case BluetoothChooser::Event::SELECTED:
- // We can't know if we are going to send a success message yet because
- // the device could have vanished. This event should be histogramed
- // manually after checking if the device is still around.
- 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;
- }
- NOTREACHED();
- return UMARequestDeviceOutcome::SUCCESS;
-}
-
-} // namespace
-
-BluetoothDispatcherHost::BluetoothDispatcherHost(int render_process_id)
- : BrowserMessageFilter(BluetoothMsgStart),
- render_process_id_(render_process_id),
- current_delay_time_(kDelayTime),
- discovery_session_timer_(
- FROM_HERE,
- // TODO(jyasskin): Add a way for tests to control the dialog
- // directly, and change this to a reasonable discovery timeout.
- base::TimeDelta::FromSecondsD(current_delay_time_),
- base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery,
- // base::Timer guarantees it won't call back after its
- // destructor starts.
- base::Unretained(this)),
- /*is_repeating=*/false),
- weak_ptr_factory_(this) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- // Bind all future weak pointers to the UI thread.
- weak_ptr_on_ui_thread_ = weak_ptr_factory_.GetWeakPtr();
- weak_ptr_on_ui_thread_.get(); // Associates with UI thread.
-}
-
-void BluetoothDispatcherHost::OnDestruct() const {
- // See class comment: UI Thread Note.
- BrowserThread::DeleteOnUIThread::Destruct(this);
-}
-
-void BluetoothDispatcherHost::OverrideThreadForMessage(
- const IPC::Message& message,
- content::BrowserThread::ID* thread) {
- // See class comment: UI Thread Note.
- *thread = BrowserThread::UI;
-}
-
-bool BluetoothDispatcherHost::OnMessageReceived(const IPC::Message& message) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcherHost, message)
- IPC_MESSAGE_HANDLER(BluetoothHostMsg_RequestDevice, OnRequestDevice)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void BluetoothDispatcherHost::SetBluetoothAdapterForTesting(
- scoped_refptr<device::BluetoothAdapter> mock_adapter) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- if (mock_adapter.get()) {
- current_delay_time_ = kTestingDelayTime;
- // Reset the discovery session timer to use the new delay time.
- discovery_session_timer_.Start(
- FROM_HERE, base::TimeDelta::FromSecondsD(current_delay_time_),
- base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery,
- // base::Timer guarantees it won't call back after its
- // destructor starts.
- base::Unretained(this)));
- } else {
- // The following data structures are used to store pending operations.
- // They should never contain elements at the end of a test.
- DCHECK(request_device_sessions_.IsEmpty());
-
- // The following data structures are cleaned up when a
- // device/service/characteristic is removed.
- // Since this can happen after the test is done and the cleanup function is
- // called, we clean them here.
- allowed_devices_map_ = BluetoothAllowedDevicesMap();
- }
-
- set_adapter(std::move(mock_adapter));
-}
-
-BluetoothDispatcherHost::~BluetoothDispatcherHost() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // Clear adapter, releasing observer references.
- set_adapter(scoped_refptr<device::BluetoothAdapter>());
-}
-
-// Stores information associated with an in-progress requestDevice call. This
-// will include the state of the active chooser dialog in a future patch.
-struct BluetoothDispatcherHost::RequestDeviceSession {
- public:
- RequestDeviceSession(int thread_id,
- int request_id,
- url::Origin origin,
- const std::vector<BluetoothScanFilter>& filters,
- const std::vector<BluetoothUUID>& optional_services)
- : thread_id(thread_id),
- request_id(request_id),
- origin(origin),
- filters(filters),
- optional_services(optional_services) {}
-
- void AddFilteredDevice(const device::BluetoothDevice& device) {
- if (chooser && MatchesFilters(device, filters)) {
- chooser->AddDevice(device.GetAddress(), device.GetName());
- }
- }
-
- std::unique_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter() const {
- std::set<BluetoothUUID> services;
- for (const BluetoothScanFilter& filter : filters) {
- services.insert(filter.services.begin(), filter.services.end());
- }
- std::unique_ptr<device::BluetoothDiscoveryFilter> discovery_filter(
- new device::BluetoothDiscoveryFilter(
- device::BluetoothDiscoveryFilter::TRANSPORT_DUAL));
- for (const BluetoothUUID& service : services) {
- discovery_filter->AddUUID(service);
- }
- return discovery_filter;
- }
-
- const int thread_id;
- const int request_id;
- const url::Origin origin;
- const std::vector<BluetoothScanFilter> filters;
- const std::vector<BluetoothUUID> optional_services;
- std::unique_ptr<BluetoothChooser> chooser;
- std::unique_ptr<device::BluetoothDiscoverySession> discovery_session;
-};
-
-void BluetoothDispatcherHost::set_adapter(
- scoped_refptr<device::BluetoothAdapter> adapter) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (adapter_.get()) {
- adapter_->RemoveObserver(this);
- for (device::BluetoothAdapter::Observer* observer : adapter_observers_) {
- adapter_->RemoveObserver(observer);
- }
- }
- adapter_ = adapter;
- if (adapter_.get()) {
- adapter_->AddObserver(this);
- for (device::BluetoothAdapter::Observer* observer : adapter_observers_) {
- adapter_->AddObserver(observer);
- }
- } else {
- // Notify that the adapter has been removed and observers should clean up
- // their state.
- for (device::BluetoothAdapter::Observer* observer : adapter_observers_) {
- observer->AdapterPresentChanged(nullptr, false);
- }
- }
-}
-
-void BluetoothDispatcherHost::StartDeviceDiscovery(
- RequestDeviceSession* session,
- int chooser_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (session->discovery_session) {
- // Already running; just increase the timeout.
- discovery_session_timer_.Reset();
- } else {
- session->chooser->ShowDiscoveryState(
- BluetoothChooser::DiscoveryState::DISCOVERING);
- adapter_->StartDiscoverySessionWithFilter(
- session->ComputeScanFilter(),
- base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted,
- weak_ptr_on_ui_thread_, chooser_id),
- base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError,
- weak_ptr_on_ui_thread_, chooser_id));
- }
-}
-
-void BluetoothDispatcherHost::StopDeviceDiscovery() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- for (IDMap<RequestDeviceSession, IDMapOwnPointer>::iterator iter(
- &request_device_sessions_);
- !iter.IsAtEnd(); iter.Advance()) {
- RequestDeviceSession* session = iter.GetCurrentValue();
- if (session->discovery_session) {
- StopDiscoverySession(std::move(session->discovery_session));
- }
- if (session->chooser) {
- session->chooser->ShowDiscoveryState(
- BluetoothChooser::DiscoveryState::IDLE);
- }
- }
-}
-
-void BluetoothDispatcherHost::AdapterPoweredChanged(
- device::BluetoothAdapter* adapter,
- bool powered) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- const BluetoothChooser::AdapterPresence presence =
- powered ? BluetoothChooser::AdapterPresence::POWERED_ON
- : BluetoothChooser::AdapterPresence::POWERED_OFF;
- for (IDMap<RequestDeviceSession, IDMapOwnPointer>::iterator iter(
- &request_device_sessions_);
- !iter.IsAtEnd(); iter.Advance()) {
- RequestDeviceSession* session = iter.GetCurrentValue();
-
- // Stop ongoing discovery session if power is off.
- if (!powered && session->discovery_session) {
- StopDiscoverySession(std::move(session->discovery_session));
- }
-
- if (session->chooser)
- session->chooser->SetAdapterPresence(presence);
- }
-
- // Stop the timer so that we don't change the state of the chooser
- // when timer expires.
- if (!powered) {
- discovery_session_timer_.Stop();
- }
-}
-
-void BluetoothDispatcherHost::DeviceAdded(device::BluetoothAdapter* adapter,
- device::BluetoothDevice* device) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- VLOG(1) << "Adding device to all choosers: " << device->GetAddress();
- for (IDMap<RequestDeviceSession, IDMapOwnPointer>::iterator iter(
- &request_device_sessions_);
- !iter.IsAtEnd(); iter.Advance()) {
- RequestDeviceSession* session = iter.GetCurrentValue();
- session->AddFilteredDevice(*device);
- }
-}
-
-void BluetoothDispatcherHost::DeviceRemoved(device::BluetoothAdapter* adapter,
- device::BluetoothDevice* device) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- VLOG(1) << "Marking device removed on all choosers: " << device->GetAddress();
- for (IDMap<RequestDeviceSession, IDMapOwnPointer>::iterator iter(
- &request_device_sessions_);
- !iter.IsAtEnd(); iter.Advance()) {
- RequestDeviceSession* session = iter.GetCurrentValue();
- if (session->chooser) {
- session->chooser->RemoveDevice(device->GetAddress());
- }
- }
-}
-
-void BluetoothDispatcherHost::OnRequestDevice(
- int thread_id,
- int request_id,
- int frame_routing_id,
- const std::vector<BluetoothScanFilter>& filters,
- const std::vector<BluetoothUUID>& optional_services) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::REQUEST_DEVICE);
- RecordRequestDeviceArguments(filters, optional_services);
-
- if (!adapter_.get()) {
- if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
- BluetoothAdapterFactory::GetAdapter(base::Bind(
- &BluetoothDispatcherHost::OnGetAdapter, weak_ptr_on_ui_thread_,
- base::Bind(&BluetoothDispatcherHost::OnRequestDeviceImpl,
- weak_ptr_on_ui_thread_, thread_id, request_id,
- frame_routing_id, filters, optional_services)));
- return;
- }
- RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER);
- Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id, WebBluetoothError::NO_BLUETOOTH_ADAPTER));
- return;
- }
- OnRequestDeviceImpl(thread_id, request_id, frame_routing_id, filters,
- optional_services);
-}
-
-void BluetoothDispatcherHost::OnGetAdapter(
- base::Closure continuation,
- scoped_refptr<device::BluetoothAdapter> adapter) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- set_adapter(adapter);
- continuation.Run();
-}
-
-void BluetoothDispatcherHost::OnRequestDeviceImpl(
- int thread_id,
- int request_id,
- int frame_routing_id,
- const std::vector<BluetoothScanFilter>& filters,
- const std::vector<BluetoothUUID>& optional_services) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- VLOG(1) << "requestDevice called with the following filters: ";
- for (const BluetoothScanFilter& filter : filters) {
- VLOG(1) << "Name: " << filter.name;
- VLOG(1) << "Name Prefix: " << filter.namePrefix;
- VLOG(1) << "Services:";
- VLOG(1) << "\t[";
- for (const BluetoothUUID& service : filter.services)
- VLOG(1) << "\t\t" << service.value();
- VLOG(1) << "\t]";
- }
-
- VLOG(1) << "requestDevice called with the following optional services: ";
- for (const BluetoothUUID& service : optional_services)
- VLOG(1) << "\t" << service.value();
-
- // Check blacklist to reject invalid filters and adjust optional_services.
- if (BluetoothBlacklist::Get().IsExcluded(filters)) {
- RecordRequestDeviceOutcome(
- UMARequestDeviceOutcome::BLACKLISTED_SERVICE_IN_FILTER);
- Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id,
- WebBluetoothError::REQUEST_DEVICE_WITH_BLACKLISTED_UUID));
- return;
- }
- std::vector<BluetoothUUID> optional_services_blacklist_filtered(
- optional_services);
- BluetoothBlacklist::Get().RemoveExcludedUuids(
- &optional_services_blacklist_filtered);
-
- RenderFrameHostImpl* render_frame_host =
- RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id);
- WebContents* web_contents =
- WebContents::FromRenderFrameHost(render_frame_host);
-
- if (!render_frame_host || !web_contents) {
- DLOG(WARNING) << "Got a requestDevice IPC without a matching "
- << "RenderFrameHost or WebContents: " << render_process_id_
- << ", " << frame_routing_id;
- RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME);
- Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id,
- WebBluetoothError::REQUEST_DEVICE_WITHOUT_FRAME));
- return;
- }
-
- const url::Origin requesting_origin =
- render_frame_host->GetLastCommittedOrigin();
- const url::Origin embedding_origin =
- web_contents->GetMainFrame()->GetLastCommittedOrigin();
-
- // TODO(crbug.com/518042): Enforce correctly-delegated permissions instead of
- // matching origins. When relaxing this, take care to handle non-sandboxed
- // unique origins.
- if (!embedding_origin.IsSameOriginWith(requesting_origin)) {
- Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id,
- WebBluetoothError::REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME));
- return;
- }
- // The above also excludes unique origins, which are not even same-origin with
- // themselves.
- DCHECK(!requesting_origin.unique());
-
- DCHECK(adapter_.get());
-
- if (!adapter_->IsPresent()) {
- VLOG(1) << "Bluetooth Adapter not present. Can't serve requestDevice.";
- RecordRequestDeviceOutcome(
- UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_NOT_PRESENT);
- Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id, WebBluetoothError::NO_BLUETOOTH_ADAPTER));
- return;
- }
-
- // The renderer should never send empty filters.
- if (HasEmptyOrInvalidFilter(filters)) {
- bad_message::ReceivedBadMessage(this,
- bad_message::BDH_EMPTY_OR_INVALID_FILTERS);
- return;
- }
-
- switch (GetContentClient()->browser()->AllowWebBluetooth(
- web_contents->GetBrowserContext(), requesting_origin, embedding_origin)) {
- case ContentBrowserClient::AllowWebBluetoothResult::BLOCK_POLICY: {
- RecordRequestDeviceOutcome(
- UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_POLICY_DISABLED);
- Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id,
- WebBluetoothError::CHOOSER_NOT_SHOWN_API_LOCALLY_DISABLED));
- return;
- }
- case ContentBrowserClient::AllowWebBluetoothResult::
- BLOCK_GLOBALLY_DISABLED: {
- // Log to the developer console.
- web_contents->GetMainFrame()->AddMessageToConsole(
- content::CONSOLE_MESSAGE_LEVEL_LOG,
- "Bluetooth permission has been blocked.");
- // Block requests.
- RecordRequestDeviceOutcome(
- UMARequestDeviceOutcome::BLUETOOTH_GLOBALLY_DISABLED);
- Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id,
- WebBluetoothError::CHOOSER_NOT_SHOWN_API_GLOBALLY_DISABLED));
- return;
- }
- case ContentBrowserClient::AllowWebBluetoothResult::ALLOW:
- break;
- }
-
- // Create storage for the information that backs the chooser, and show the
- // chooser.
- RequestDeviceSession* const session =
- new RequestDeviceSession(thread_id, request_id, requesting_origin,
- filters, optional_services_blacklist_filtered);
- int chooser_id = request_device_sessions_.Add(session);
-
- BluetoothChooser::EventHandler chooser_event_handler =
- base::Bind(&BluetoothDispatcherHost::OnBluetoothChooserEvent,
- weak_ptr_on_ui_thread_, chooser_id);
- if (WebContentsDelegate* delegate = web_contents->GetDelegate()) {
- session->chooser =
- delegate->RunBluetoothChooser(render_frame_host, chooser_event_handler);
- }
- if (!session->chooser) {
- LOG(WARNING)
- << "No Bluetooth chooser implementation; falling back to first device.";
- session->chooser.reset(
- new FirstDeviceBluetoothChooser(chooser_event_handler));
- }
-
- if (!session->chooser->CanAskForScanningPermission()) {
- VLOG(1) << "Closing immediately because Chooser cannot obtain permission.";
- OnBluetoothChooserEvent(chooser_id,
- BluetoothChooser::Event::DENIED_PERMISSION, "");
- return;
- }
-
- // Populate the initial list of devices.
- VLOG(1) << "Populating " << adapter_->GetDevices().size()
- << " devices in chooser " << chooser_id;
- for (const device::BluetoothDevice* device : adapter_->GetDevices()) {
- VLOG(1) << "\t" << device->GetAddress();
- session->AddFilteredDevice(*device);
- }
-
- if (!session->chooser) {
- // If the dialog's closing, no need to do any of the rest of this.
- return;
- }
-
- if (!adapter_->IsPowered()) {
- session->chooser->SetAdapterPresence(
- BluetoothChooser::AdapterPresence::POWERED_OFF);
- return;
- }
-
- StartDeviceDiscovery(session, chooser_id);
-}
-
-void BluetoothDispatcherHost::OnDiscoverySessionStarted(
- int chooser_id,
- std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- VLOG(1) << "Started discovery session for " << chooser_id;
- if (RequestDeviceSession* session =
- request_device_sessions_.Lookup(chooser_id)) {
- session->discovery_session = std::move(discovery_session);
-
- // Arrange to stop discovery later.
- discovery_session_timer_.Reset();
- } else {
- VLOG(1) << "Chooser " << chooser_id
- << " was closed before the session finished starting. Stopping.";
- StopDiscoverySession(std::move(discovery_session));
- }
-}
-
-void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int chooser_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- VLOG(1) << "Failed to start discovery session for " << chooser_id;
- if (RequestDeviceSession* session =
- request_device_sessions_.Lookup(chooser_id)) {
- if (session->chooser && !session->discovery_session) {
- session->chooser->ShowDiscoveryState(
- BluetoothChooser::DiscoveryState::FAILED_TO_START);
- }
- }
- // Ignore discovery session start errors when the dialog was already closed by
- // the time they happen.
-}
-
-void BluetoothDispatcherHost::OnBluetoothChooserEvent(
- int chooser_id,
- BluetoothChooser::Event event,
- const std::string& device_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id);
- DCHECK(session) << "Shouldn't receive an event (" << static_cast<int>(event)
- << ") from a closed chooser.";
- CHECK(session->chooser) << "Shouldn't receive an event ("
- << static_cast<int>(event)
- << ") from a closed chooser.";
- switch (event) {
- case BluetoothChooser::Event::RESCAN:
- StartDeviceDiscovery(session, chooser_id);
- // No need to close the chooser so we return.
- return;
- case BluetoothChooser::Event::DENIED_PERMISSION:
- case BluetoothChooser::Event::CANCELLED:
- case BluetoothChooser::Event::SELECTED:
- break;
- case BluetoothChooser::Event::SHOW_OVERVIEW_HELP:
- VLOG(1) << "Overview Help link pressed.";
- break;
- case BluetoothChooser::Event::SHOW_ADAPTER_OFF_HELP:
- VLOG(1) << "Adapter Off Help link pressed.";
- break;
- case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP:
- VLOG(1) << "Need Location Help link pressed.";
- break;
- }
-
- // Synchronously ensure nothing else calls into the chooser after it has
- // asked to be closed.
- session->chooser.reset();
-
- // Yield to the event loop to make sure we don't destroy the session
- // within a BluetoothDispatcherHost stack frame.
- if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&BluetoothDispatcherHost::FinishClosingChooser,
- weak_ptr_on_ui_thread_, chooser_id, event, device_id))) {
- LOG(WARNING) << "No TaskRunner; not closing requestDevice dialog.";
- }
-}
-
-void BluetoothDispatcherHost::FinishClosingChooser(
- int chooser_id,
- BluetoothChooser::Event event,
- const std::string& device_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id);
- DCHECK(session) << "Session removed unexpectedly.";
-
- if ((event != BluetoothChooser::Event::DENIED_PERMISSION) &&
- (event != BluetoothChooser::Event::SELECTED)) {
- RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
- Send(new BluetoothMsg_RequestDeviceError(
- session->thread_id, session->request_id,
- WebBluetoothError::CHOOSER_CANCELLED));
- request_device_sessions_.Remove(chooser_id);
- return;
- }
- if (event == BluetoothChooser::Event::DENIED_PERMISSION) {
- RecordRequestDeviceOutcome(
- UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_DENIED_PERMISSION);
- VLOG(1) << "Bluetooth chooser denied permission";
- Send(new BluetoothMsg_RequestDeviceError(
- session->thread_id, session->request_id,
- WebBluetoothError::CHOOSER_NOT_SHOWN_USER_DENIED_PERMISSION_TO_SCAN));
- request_device_sessions_.Remove(chooser_id);
- return;
- }
- DCHECK_EQ(static_cast<int>(event),
- static_cast<int>(BluetoothChooser::Event::SELECTED));
-
- // |device_id| is the Device Address that RequestDeviceSession passed to
- // chooser->AddDevice().
- const device::BluetoothDevice* const device = adapter_->GetDevice(device_id);
- if (device == nullptr) {
- VLOG(1) << "Device " << device_id << " no longer in adapter";
- RecordRequestDeviceOutcome(UMARequestDeviceOutcome::CHOSEN_DEVICE_VANISHED);
- Send(new BluetoothMsg_RequestDeviceError(
- session->thread_id, session->request_id,
- WebBluetoothError::CHOSEN_DEVICE_VANISHED));
- request_device_sessions_.Remove(chooser_id);
- return;
- }
-
- const std::string& device_id_for_origin = allowed_devices_map_.AddDevice(
- session->origin, device->GetAddress(), session->filters,
- session->optional_services);
-
- VLOG(1) << "Device: " << device->GetName();
- VLOG(1) << "UUIDs: ";
-
- device::BluetoothDevice::UUIDList filtered_uuids;
- for (BluetoothUUID uuid : device->GetUUIDs()) {
- if (allowed_devices_map_.IsOriginAllowedToAccessService(
- session->origin, device_id_for_origin, uuid.canonical_value())) {
- VLOG(1) << "\t Allowed: " << uuid.canonical_value();
- filtered_uuids.push_back(uuid);
- } else {
- VLOG(1) << "\t Not Allowed: " << uuid.canonical_value();
- }
- }
-
- content::BluetoothDevice device_ipc(
- device_id_for_origin, // id
- device->GetName(), // name
- content::BluetoothDevice::UUIDsFromBluetoothUUIDs(
- filtered_uuids)); // uuids
- RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS);
- Send(new BluetoothMsg_RequestDeviceSuccess(session->thread_id,
- session->request_id, device_ipc));
- request_device_sessions_.Remove(chooser_id);
-}
-
-CacheQueryResult BluetoothDispatcherHost::QueryCacheForDevice(
- const url::Origin& origin,
- const std::string& device_id) {
- const std::string& device_address =
- allowed_devices_map_.GetDeviceAddress(origin, device_id);
- if (device_address.empty()) {
- bad_message::ReceivedBadMessage(
- this, bad_message::BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN);
- return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER);
- }
-
- CacheQueryResult result;
- result.device = adapter_->GetDevice(device_address);
-
- // When a device can't be found in the BluetoothAdapter, that generally
- // indicates that it's gone out of range. We reject with a NetworkError in
- // that case.
- // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-connectgatt
- if (result.device == nullptr) {
- result.outcome = CacheQueryOutcome::NO_DEVICE;
- }
- return result;
-}
-
-void BluetoothDispatcherHost::AddAdapterObserver(
- device::BluetoothAdapter::Observer* observer) {
- adapter_observers_.insert(observer);
- if (adapter_) {
- adapter_->AddObserver(observer);
- }
-}
-
-void BluetoothDispatcherHost::RemoveAdapterObserver(
- device::BluetoothAdapter::Observer* observer) {
- size_t removed = adapter_observers_.erase(observer);
- DCHECK(removed);
- if (adapter_) {
- adapter_->RemoveObserver(observer);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.h b/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.h
deleted file mode 100644
index b1715af4e5c..00000000000
--- a/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.h
+++ /dev/null
@@ -1,187 +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_BLUETOOTH_BLUETOOTH_DISPATCHER_HOST_H_
-#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DISPATCHER_HOST_H_
-
-#include <stdint.h>
-
-#include <map>
-
-#include "base/id_map.h"
-#include "base/macros.h"
-#include "base/memory/scoped_vector.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/bluetooth/bluetooth_allowed_devices_map.h"
-#include "content/public/browser/bluetooth_chooser.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "device/bluetooth/bluetooth_adapter.h"
-#include "device/bluetooth/bluetooth_gatt_notify_session.h"
-#include "device/bluetooth/bluetooth_remote_gatt_service.h"
-
-namespace device {
-class BluetoothUUID;
-}
-
-namespace content {
-
-class WebBluetoothServiceImpl;
-
-struct BluetoothScanFilter;
-struct CacheQueryResult;
-
-// Dispatches and sends bluetooth related messages sent to/from a child
-// process BluetoothDispatcher from/to the main browser process.
-//
-// Intended to be instantiated by the RenderProcessHost and installed as
-// a filter on the channel. BrowserMessageFilter is refcounted and typically
-// lives as long as it is installed on a channel.
-//
-// UI Thread Note:
-// BluetoothDispatcherHost is constructed, operates, and destroyed on the UI
-// thread because BluetoothAdapter and related objects live there.
-class CONTENT_EXPORT BluetoothDispatcherHost final
- : public BrowserMessageFilter,
- public device::BluetoothAdapter::Observer {
- public:
- BluetoothDispatcherHost(int render_process_id);
- // BrowserMessageFilter:
- void OnDestruct() const override;
- void OverrideThreadForMessage(const IPC::Message& message,
- BrowserThread::ID* thread) override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- void SetBluetoothAdapterForTesting(
- scoped_refptr<device::BluetoothAdapter> mock_adapter);
-
- // Temporary functions so that WebBluetoothServices can add themselves as
- // observers of the Bluetooth Adapter without having to get an adapter for
- // themselves.
- // TODO(ortuno): Remove once WebBluetoothServiceImpl gets its own adapter.
- // https://crbug.com/508771
- void AddAdapterObserver(device::BluetoothAdapter::Observer* observer);
- void RemoveAdapterObserver(device::BluetoothAdapter::Observer* observer);
-
- protected:
- ~BluetoothDispatcherHost() override;
-
- private:
- friend class WebBluetoothServiceImpl;
- friend class base::DeleteHelper<BluetoothDispatcherHost>;
- friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
-
- struct RequestDeviceSession;
-
- // Set |adapter_| to a BluetoothAdapter instance and register observers,
- // releasing references to previous |adapter_|.
- //
- // We currently keep track of observers that used BluetoothDispatcherHost
- // to register themselves on the adapter and remove them from |adapter_| and
- // add them to |adapter| when this function is called.
- // TODO(ortuno): Observers should add/remove themselves to/from the adapter.
- // http://crbug.com/603291
- void set_adapter(scoped_refptr<device::BluetoothAdapter> adapter);
-
- // Makes sure a BluetoothDiscoverySession is active for |session|, and resets
- // its timeout.
- void StartDeviceDiscovery(RequestDeviceSession* session, int chooser_id);
-
- // Stops all BluetoothDiscoverySessions being run for requestDevice()
- // choosers.
- void StopDeviceDiscovery();
-
- // BluetoothAdapter::Observer:
- void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
- bool powered) override;
- void DeviceAdded(device::BluetoothAdapter* adapter,
- device::BluetoothDevice* device) override;
- void DeviceRemoved(device::BluetoothAdapter* adapter,
- device::BluetoothDevice* device) override;
-
- // IPC Handlers, see definitions in bluetooth_messages.h.
- void OnRequestDevice(
- int thread_id,
- int request_id,
- int frame_routing_id,
- const std::vector<content::BluetoothScanFilter>& filters,
- const std::vector<device::BluetoothUUID>& optional_services);
-
- // Callbacks for BluetoothDevice::OnRequestDevice.
- // If necessary, the adapter must be obtained before continuing to Impl.
- void OnGetAdapter(base::Closure continuation,
- scoped_refptr<device::BluetoothAdapter> adapter);
- void OnRequestDeviceImpl(
- int thread_id,
- int request_id,
- int frame_routing_id,
- const std::vector<content::BluetoothScanFilter>& filters,
- const std::vector<device::BluetoothUUID>& optional_services);
-
- // Callbacks for BluetoothAdapter::StartDiscoverySession.
- void OnDiscoverySessionStarted(
- int chooser_id,
- std::unique_ptr<device::BluetoothDiscoverySession> discovery_session);
- void OnDiscoverySessionStartedError(int chooser_id);
-
- // BluetoothChooser::EventHandler:
- void OnBluetoothChooserEvent(int chooser_id,
- BluetoothChooser::Event event,
- const std::string& device_id);
-
- // The chooser implementation yields to the event loop to avoid re-entering
- // code that's still using the RequestDeviceSession, and continues with this
- // function.
- void FinishClosingChooser(int chooser_id,
- BluetoothChooser::Event event,
- const std::string& device_id);
-
- // Functions to query the platform cache for the bluetooth object.
- // result.outcome == CacheQueryOutcome::SUCCESS if the object was found in the
- // cache. Otherwise result.outcome that can used to record the outcome and
- // result.error will contain the error that should be send to the renderer.
- // One of the possible outcomes is BAD_RENDERER. In this case the outcome
- // was already recorded and since there renderer crashed there is no need to
- // send a response.
- // Queries the platform cache for a Device with |device_id| for |origin|.
- // Fills in the |outcome| field and the |device| field if successful.
- CacheQueryResult QueryCacheForDevice(const url::Origin& origin,
- const std::string& device_id);
-
- int render_process_id_;
-
- // Maps a (thread_id,request_id) to information about its requestDevice call,
- // including the chooser dialog.
- // An entry is added to this map in OnRequestDevice, and should be removed
- // again everywhere a requestDevice() reply is sent.
- IDMap<RequestDeviceSession, IDMapOwnPointer> request_device_sessions_;
-
- BluetoothAllowedDevicesMap allowed_devices_map_;
-
- // Defines how long to scan for and how long to discover services for.
- int current_delay_time_;
-
- // A BluetoothAdapter instance representing an adapter of the system.
- scoped_refptr<device::BluetoothAdapter> adapter_;
-
- std::unordered_set<device::BluetoothAdapter::Observer*> adapter_observers_;
-
- // Automatically stops Bluetooth discovery a set amount of time after it was
- // started. We have a single timer for all of Web Bluetooth because it's
- // simpler than tracking timeouts for each RequestDeviceSession individually,
- // and because there's no harm in extending the length of a few discovery
- // sessions when other sessions are active.
- base::Timer discovery_session_timer_;
-
- // |weak_ptr_on_ui_thread_| provides weak pointers, e.g. for callbacks, and
- // because it exists and has been bound to the UI thread enforces that all
- // copies verify they are also used on the UI thread.
- base::WeakPtr<BluetoothDispatcherHost> weak_ptr_on_ui_thread_;
- base::WeakPtrFactory<BluetoothDispatcherHost> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(BluetoothDispatcherHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DISPATCHER_HOST_H_
diff --git a/chromium/content/browser/bluetooth/bluetooth_metrics.cc b/chromium/content/browser/bluetooth/bluetooth_metrics.cc
index 692ebb31fff..6e8684f77c2 100644
--- a/chromium/content/browser/bluetooth/bluetooth_metrics.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_metrics.cc
@@ -8,10 +8,11 @@
#include <map>
#include <set>
+#include <unordered_set>
+
#include "base/hash.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
-#include "content/common/bluetooth/bluetooth_scan_filter.h"
#include "device/bluetooth/bluetooth_uuid.h"
using device::BluetoothUUID;
@@ -22,11 +23,14 @@ namespace {
// UMA_HISTOGRAM_SPARSE_SLOWLY (positive int).
//
// Hash values can be produced manually using tool: bluetooth_metrics_hash.
-int HashUUID(const std::string& canonical_uuid) {
- DCHECK(canonical_uuid == BluetoothUUID(canonical_uuid).canonical_value());
+int HashUUID(const base::Optional<BluetoothUUID>& uuid) {
+ if (!uuid) {
+ return 0;
+ }
- // TODO(520284): Other than verifying that uuid is canonical, this logic
+ // TODO(520284): Other than verifying that |uuid| contains a value, this logic
// should be migrated to a dedicated histogram macro for hashed strings.
+ const std::string& canonical_uuid = uuid->canonical_value();
uint32_t data =
base::SuperFastHash(canonical_uuid.data(), canonical_uuid.size());
@@ -55,54 +59,57 @@ void RecordRequestDeviceOutcome(UMARequestDeviceOutcome outcome) {
}
static void RecordRequestDeviceFilters(
- const std::vector<content::BluetoothScanFilter>& filters) {
+ const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) {
UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.Filters.Count",
filters.size());
- for (const content::BluetoothScanFilter& filter : filters) {
+ for (const auto& filter : filters) {
UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.FilterSize",
- filter.services.size());
- for (const BluetoothUUID& service : filter.services) {
+ filter->services.size());
+ for (const base::Optional<BluetoothUUID>& service : filter->services) {
// TODO(ortuno): Use a macro to histogram strings.
// http://crbug.com/520284
UMA_HISTOGRAM_SPARSE_SLOWLY(
- "Bluetooth.Web.RequestDevice.Filters.Services",
- HashUUID(service.canonical_value()));
+ "Bluetooth.Web.RequestDevice.Filters.Services", HashUUID(service));
}
}
}
static void RecordRequestDeviceOptionalServices(
- const std::vector<BluetoothUUID>& optional_services) {
+ const mojo::Array<base::Optional<BluetoothUUID>>& optional_services) {
UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.OptionalServices.Count",
optional_services.size());
- for (const BluetoothUUID& service : optional_services) {
+ for (const base::Optional<BluetoothUUID>& service : optional_services) {
// TODO(ortuno): Use a macro to histogram strings.
// http://crbug.com/520284
UMA_HISTOGRAM_SPARSE_SLOWLY(
"Bluetooth.Web.RequestDevice.OptionalServices.Services",
- HashUUID(service.canonical_value()));
+ HashUUID(service));
}
}
static void RecordUnionOfServices(
- const std::vector<content::BluetoothScanFilter>& filters,
- const std::vector<BluetoothUUID>& optional_services) {
- std::set<BluetoothUUID> union_of_services(optional_services.begin(),
- optional_services.end());
+ 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 content::BluetoothScanFilter& filter : filters)
- union_of_services.insert(filter.services.begin(), filter.services.end());
+ for (const auto& filter : options->filters) {
+ for (const base::Optional<BluetoothUUID>& service : filter->services) {
+ union_of_services.insert(service->canonical_value());
+ }
+ }
UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.UnionOfServices.Count",
union_of_services.size());
}
-void RecordRequestDeviceArguments(
- const std::vector<content::BluetoothScanFilter>& filters,
- const std::vector<device::BluetoothUUID>& optional_services) {
- RecordRequestDeviceFilters(filters);
- RecordRequestDeviceOptionalServices(optional_services);
- RecordUnionOfServices(filters, optional_services);
+void RecordRequestDeviceOptions(
+ const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) {
+ RecordRequestDeviceFilters(options->filters);
+ RecordRequestDeviceOptionalServices(options->optional_services);
+ RecordUnionOfServices(options);
}
// GATTServer.Connect
@@ -126,24 +133,48 @@ void RecordConnectGATTTimeFailed(const base::TimeDelta& duration) {
UMA_HISTOGRAM_MEDIUM_TIMES("Bluetooth.Web.ConnectGATT.TimeFailed", duration);
}
-// getPrimaryService
+// getPrimaryService & getPrimaryServices
-void RecordGetPrimaryServiceService(const BluetoothUUID& service) {
- // TODO(ortuno): Use a macro to histogram strings.
- // http://crbug.com/520284
- UMA_HISTOGRAM_SPARSE_SLOWLY("Bluetooth.Web.GetPrimaryService.Services",
- HashUUID(service.canonical_value()));
+void RecordGetPrimaryServicesOutcome(
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ UMAGetPrimaryServiceOutcome outcome) {
+ switch (quantity) {
+ case blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Bluetooth.Web.GetPrimaryService.Outcome", static_cast<int>(outcome),
+ static_cast<int>(UMAGetPrimaryServiceOutcome::COUNT));
+ return;
+ case blink::mojom::WebBluetoothGATTQueryQuantity::MULTIPLE:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Bluetooth.Web.GetPrimaryServices.Outcome", static_cast<int>(outcome),
+ static_cast<int>(UMAGetPrimaryServiceOutcome::COUNT));
+ return;
+ }
}
-void RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome outcome) {
- UMA_HISTOGRAM_ENUMERATION(
- "Bluetooth.Web.GetPrimaryService.Outcome", static_cast<int>(outcome),
- static_cast<int>(UMAGetPrimaryServiceOutcome::COUNT));
+void RecordGetPrimaryServicesOutcome(
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ CacheQueryOutcome outcome) {
+ DCHECK(outcome == CacheQueryOutcome::NO_DEVICE);
+ RecordGetPrimaryServicesOutcome(quantity,
+ UMAGetPrimaryServiceOutcome::NO_DEVICE);
}
-void RecordGetPrimaryServiceOutcome(CacheQueryOutcome outcome) {
- DCHECK(outcome == CacheQueryOutcome::NO_DEVICE);
- RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NO_DEVICE);
+void RecordGetPrimaryServicesServices(
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ const base::Optional<BluetoothUUID>& service) {
+ // TODO(ortuno): Use a macro to histogram strings.
+ // http://crbug.com/520284
+ switch (quantity) {
+ case blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE:
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Bluetooth.Web.GetPrimaryService.Services",
+ HashUUID(service));
+ return;
+ case blink::mojom::WebBluetoothGATTQueryQuantity::MULTIPLE:
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Bluetooth.Web.GetPrimaryServices.Services",
+ HashUUID(service));
+ return;
+ }
}
// getCharacteristic & getCharacteristics
@@ -190,7 +221,7 @@ void RecordGetCharacteristicsOutcome(
void RecordGetCharacteristicsCharacteristic(
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
- const std::string& characteristic) {
+ const base::Optional<BluetoothUUID>& characteristic) {
switch (quantity) {
case blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE:
UMA_HISTOGRAM_SPARSE_SLOWLY(
diff --git a/chromium/content/browser/bluetooth/bluetooth_metrics.h b/chromium/content/browser/bluetooth/bluetooth_metrics.h
index af5ad350f22..34aae8c2dfc 100644
--- a/chromium/content/browser/bluetooth/bluetooth_metrics.h
+++ b/chromium/content/browser/bluetooth/bluetooth_metrics.h
@@ -23,7 +23,7 @@ struct BluetoothScanFilter;
// General Metrics
-// Enumaration of each Web Bluetooth API entry point.
+// Enumeration of each Web Bluetooth API entry point.
enum class UMAWebBluetoothFunction {
REQUEST_DEVICE = 0,
CONNECT_GATT = 1,
@@ -35,6 +35,7 @@ enum class UMAWebBluetoothFunction {
CHARACTERISTIC_STOP_NOTIFICATIONS = 7,
REMOTE_GATT_SERVER_DISCONNECT = 8,
SERVICE_GET_CHARACTERISTICS = 9,
+ GET_PRIMARY_SERVICES = 10,
// NOTE: Add new actions immediately above this line. Make sure to update
// the enum list in tools/metrics/histograms/histograms.xml accordingly.
COUNT
@@ -44,7 +45,7 @@ enum class UMAWebBluetoothFunction {
// API.
void RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction function);
-// Enumation for outcomes of querying the bluetooth cache.
+// Enumeration for outcomes of querying the bluetooth cache.
enum class CacheQueryOutcome {
SUCCESS = 0,
BAD_RENDERER = 1,
@@ -77,6 +78,7 @@ enum class UMARequestDeviceOutcome {
// tools/metrics/histograms/histograms.xml accordingly.
COUNT
};
+
// There should be a call to this function before every
// Send(BluetoothMsg_RequestDeviceSuccess...) or
// Send(BluetoothMsg_RequestDeviceError...).
@@ -89,11 +91,11 @@ void RecordRequestDeviceOutcome(UMARequestDeviceOutcome outcome);
// - Number of optional services used.
// - UUID of the optional services.
// - Size of the union of all services.
-void RecordRequestDeviceArguments(
- const std::vector<content::BluetoothScanFilter>& filters,
- const std::vector<device::BluetoothUUID>& optional_services);
+void RecordRequestDeviceOptions(
+ const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options);
+
+// GattServer.connect() Metrics
-// connectGATT() Metrics
enum class UMAConnectGATTOutcome {
SUCCESS = 0,
NO_DEVICE = 1,
@@ -117,39 +119,58 @@ enum class UMAConnectGATTOutcome {
// accordingly.
COUNT
};
+
// There should be a call to this function before every
// Send(BluetoothMsg_ConnectGATTSuccess) and
// Send(BluetoothMsg_ConnectGATTError).
void RecordConnectGATTOutcome(UMAConnectGATTOutcome outcome);
+
// Records the outcome of the cache query for connectGATT. Should only be called
// if QueryCacheForDevice fails.
void RecordConnectGATTOutcome(CacheQueryOutcome outcome);
+
// Records how long it took for the connection to succeed.
void RecordConnectGATTTimeSuccess(const base::TimeDelta& duration);
+
// Records how long it took for the connection to fail.
void RecordConnectGATTTimeFailed(const base::TimeDelta& duration);
-// getPrimaryService() Metrics
+// getPrimaryService() and getPrimaryServices() Metrics
+
enum class UMAGetPrimaryServiceOutcome {
SUCCESS = 0,
NO_DEVICE = 1,
NOT_FOUND = 2,
+ NO_SERVICES = 3,
// Note: Add new GetPrimaryService outcomes immediately above this line.
// Make sure to update the enum list in
// tools/metrics/histograms/histograms.xml accordingly.
COUNT
};
-// Record the service uuid used when calling getPrimaryService.
-void RecordGetPrimaryServiceService(const device::BluetoothUUID& service);
-// There should be a call to this function for every call to
-// Send(BluetoothMsg_GetPrimaryServiceSuccess) and
-// Send(BluetoothMsg_GetPrimaryServiceError).
-void RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome outcome);
-// Records the outcome of the cache query for getPrimaryService. Should only be
+
+// There should be a call to this function whenever
+// RemoteServerGetPrimaryServicesCallback is run.
+// Pass blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE for
+// getPrimaryService.
+// Pass blink::mojom::WebBluetoothGATTQueryQuantity::MULTIPLE for
+// getPrimaryServices.
+void RecordGetPrimaryServicesOutcome(
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ UMAGetPrimaryServiceOutcome outcome);
+
+// Records the outcome of the cache query for getPrimaryServices. Should only be
// called if QueryCacheForDevice fails.
-void RecordGetPrimaryServiceOutcome(CacheQueryOutcome outcome);
+void RecordGetPrimaryServicesOutcome(
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ CacheQueryOutcome outcome);
+
+// Records the UUID of the service used when calling getPrimaryService.
+void RecordGetPrimaryServicesServices(
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ const base::Optional<device::BluetoothUUID>& service);
// getCharacteristic() and getCharacteristics() Metrics
+
enum class UMAGetCharacteristicOutcome {
SUCCESS = 0,
NO_DEVICE = 1,
@@ -172,15 +193,17 @@ enum class UMAGetCharacteristicOutcome {
void RecordGetCharacteristicsOutcome(
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
UMAGetCharacteristicOutcome outcome);
+
// Records the outcome of the cache query for getCharacteristics. Should only be
// called if QueryCacheForService fails.
void RecordGetCharacteristicsOutcome(
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
CacheQueryOutcome outcome);
+
// Records the UUID of the characteristic used when calling getCharacteristic.
void RecordGetCharacteristicsCharacteristic(
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
- const std::string& characteristic);
+ const base::Optional<device::BluetoothUUID>& characteristic);
// GATT Operations Metrics
@@ -226,6 +249,7 @@ void RecordGATTOperationOutcome(UMAGATTOperation operation,
// Send(BluetoothMsg_ReadCharacteristicValueSuccess) and
// Send(BluetoothMsg_ReadCharacteristicValueError).
void RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome error);
+
// Records the outcome of a cache query for readValue. Should only be called if
// QueryCacheForCharacteristic fails.
void RecordCharacteristicReadValueOutcome(CacheQueryOutcome outcome);
@@ -235,6 +259,7 @@ void RecordCharacteristicReadValueOutcome(CacheQueryOutcome outcome);
// Send(BluetoothMsg_WriteCharacteristicValueSuccess) and
// Send(BluetoothMsg_WriteCharacteristicValueError).
void RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome error);
+
// Records the outcome of a cache query for writeValue. Should only be called if
// QueryCacheForCharacteristic fails.
void RecordCharacteristicWriteValueOutcome(CacheQueryOutcome outcome);
@@ -244,6 +269,7 @@ void RecordCharacteristicWriteValueOutcome(CacheQueryOutcome outcome);
// Send(BluetoothMsg_StartNotificationsSuccess) and
// Send(BluetoothMsg_StopNotificationsError).
void RecordStartNotificationsOutcome(UMAGATTOperationOutcome outcome);
+
// Records the outcome of a cache query for startNotifications. Should only be
// called if QueryCacheForCharacteristic fails.
void RecordStartNotificationsOutcome(CacheQueryOutcome outcome);
diff --git a/chromium/content/browser/bluetooth/cache_query_result.h b/chromium/content/browser/bluetooth/cache_query_result.h
index 076c5e90624..6f187dbc44c 100644
--- a/chromium/content/browser/bluetooth/cache_query_result.h
+++ b/chromium/content/browser/bluetooth/cache_query_result.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_BLUETOOTH_CACHE_QUERY_RESULT_H_
#include "content/browser/bluetooth/bluetooth_metrics.h"
-#include "content/common/bluetooth/bluetooth_messages.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
namespace device {
class BluetoothDevice;
@@ -18,10 +18,7 @@ namespace content {
// Struct that holds the result of a cache query.
//
-// WebBluetoothServiceImpl and BluetoothDispatcherHost have functions
-// that return a CacheQueryResult so we make a separate header for it.
-// TODO(ortuno): Move into WebBluetoothServiceImpl once we move all functions
-// off BluetoothDispatcherHost.
+// TODO(ortuno): Move into WebBluetoothServiceImpl.
// https://crbug.com/508771
struct CacheQueryResult {
CacheQueryResult() : outcome(CacheQueryOutcome::SUCCESS) {}
@@ -30,21 +27,21 @@ struct CacheQueryResult {
~CacheQueryResult() {}
- blink::WebBluetoothError GetWebError() const {
+ blink::mojom::WebBluetoothError GetWebError() const {
switch (outcome) {
case CacheQueryOutcome::SUCCESS:
case CacheQueryOutcome::BAD_RENDERER:
NOTREACHED();
- return blink::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
+ return blink::mojom::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
case CacheQueryOutcome::NO_DEVICE:
- return blink::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
+ return blink::mojom::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
case CacheQueryOutcome::NO_SERVICE:
- return blink::WebBluetoothError::SERVICE_NO_LONGER_EXISTS;
+ return blink::mojom::WebBluetoothError::SERVICE_NO_LONGER_EXISTS;
case CacheQueryOutcome::NO_CHARACTERISTIC:
- return blink::WebBluetoothError::CHARACTERISTIC_NO_LONGER_EXISTS;
+ return blink::mojom::WebBluetoothError::CHARACTERISTIC_NO_LONGER_EXISTS;
}
NOTREACHED();
- return blink::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
+ return blink::mojom::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
}
device::BluetoothDevice* device = nullptr;
diff --git a/chromium/content/browser/bluetooth/first_device_bluetooth_chooser.cc b/chromium/content/browser/bluetooth/first_device_bluetooth_chooser.cc
deleted file mode 100644
index 866d623d5d8..00000000000
--- a/chromium/content/browser/bluetooth/first_device_bluetooth_chooser.cc
+++ /dev/null
@@ -1,49 +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/bluetooth/first_device_bluetooth_chooser.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-FirstDeviceBluetoothChooser::FirstDeviceBluetoothChooser(
- const EventHandler& event_handler)
- : event_handler_(event_handler) {}
-
-FirstDeviceBluetoothChooser::~FirstDeviceBluetoothChooser() {}
-
-void FirstDeviceBluetoothChooser::SetAdapterPresence(AdapterPresence presence) {
- switch (presence) {
- case AdapterPresence::ABSENT:
- case AdapterPresence::POWERED_OFF:
- // Without a user-visible dialog, if the adapter is off, there's no way to
- // ask the user to turn it on again, so we should cancel.
- event_handler_.Run(Event::CANCELLED, "");
- break;
- case AdapterPresence::POWERED_ON:
- break;
- }
-}
-
-void FirstDeviceBluetoothChooser::ShowDiscoveryState(DiscoveryState state) {
- switch (state) {
- case DiscoveryState::FAILED_TO_START:
- case DiscoveryState::IDLE:
- // Without a user-visible dialog, if discovery finishes without finding a
- // device, we'll never find one, so we should cancel.
- VLOG(1) << "FirstDeviceBluetoothChooser found nothing before going idle.";
- event_handler_.Run(Event::CANCELLED, "");
- break;
- case DiscoveryState::DISCOVERING:
- break;
- }
-}
-
-void FirstDeviceBluetoothChooser::AddDevice(const std::string& deviceId,
- const base::string16& deviceName) {
- event_handler_.Run(Event::SELECTED, deviceId);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/bluetooth/first_device_bluetooth_chooser.h b/chromium/content/browser/bluetooth/first_device_bluetooth_chooser.h
deleted file mode 100644
index 2cc4ecf909a..00000000000
--- a/chromium/content/browser/bluetooth/first_device_bluetooth_chooser.h
+++ /dev/null
@@ -1,39 +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_BLUETOOTH_FIRST_DEVICE_BLUETOOTH_CHOOSER_H_
-#define CONTENT_BROWSER_BLUETOOTH_FIRST_DEVICE_BLUETOOTH_CHOOSER_H_
-
-#include "base/macros.h"
-#include "content/public/browser/bluetooth_chooser.h"
-
-namespace content {
-
-// Implements a Bluetooth chooser that, instead of showing a dialog, selects the
-// first added device, or cancels if no device is added before discovery stops.
-// This is used as a default chooser implementation for platforms without a full
-// UI.
-class FirstDeviceBluetoothChooser : public BluetoothChooser {
- public:
- // See the BluetoothChooser::EventHandler comments for how |event_handler| is
- // used.
- explicit FirstDeviceBluetoothChooser(const EventHandler& event_handler);
- ~FirstDeviceBluetoothChooser() override;
-
- // BluetoothChooser:
- void SetAdapterPresence(AdapterPresence presence) override;
- void ShowDiscoveryState(DiscoveryState state) override;
- void AddDevice(const std::string& device_id,
- const base::string16& device_name) override;
- void RemoveDevice(const std::string& device_id) override {}
-
- private:
- EventHandler event_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(FirstDeviceBluetoothChooser);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BLUETOOTH_FIRST_DEVICE_BLUETOOTH_CHOOSER_H_
diff --git a/chromium/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc b/chromium/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
index 8a76e565ece..66d58c53173 100644
--- a/chromium/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
+++ b/chromium/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
@@ -354,4 +354,14 @@ TEST_F(FrameConnectedBluetoothDevicesTest, Destruction_MultipleMaps) {
EXPECT_FALSE(contents()->IsConnectedToBluetoothDevice());
}
+TEST_F(FrameConnectedBluetoothDevicesTest,
+ DestroyedByWebContentsImplDestruction) {
+ // Tests that we don't crash when FrameConnectedBluetoothDevices contains
+ // at least one device, and it is destroyed while WebContentsImpl is being
+ // destroyed.
+
+ // TODO(ortuno): Write test.
+ // http://crbug.com/615319
+}
+
} // namespace content
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
index 2bacdc9e8d2..b4ee20fef4d 100644
--- a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -4,7 +4,7 @@
// ID Not In Map Note:
// A service, characteristic, or descriptor ID not in the corresponding
-// BluetoothDispatcherHost map [service_id_to_device_address_,
+// WebBluetoothServiceImpl map [service_id_to_device_address_,
// characteristic_id_to_service_id_, descriptor_to_characteristic_] implies a
// hostile renderer because a renderer obtains the corresponding ID from this
// class and it will be added to the map at that time.
@@ -13,16 +13,22 @@
#include <algorithm>
+#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/bluetooth/bluetooth_adapter_factory_wrapper.h"
#include "content/browser/bluetooth/bluetooth_blacklist.h"
-#include "content/browser/bluetooth/bluetooth_dispatcher_host.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"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
+using device::BluetoothUUID;
+
namespace content {
namespace {
@@ -126,14 +132,15 @@ blink::mojom::WebBluetoothError TranslateGATTErrorAndRecord(
// Replace when implemented. http://crbug.com/552022
std::vector<device::BluetoothRemoteGattCharacteristic*>
GetCharacteristicsByUUID(device::BluetoothRemoteGattService* service,
- const std::string& characteristic_uuid) {
+ const BluetoothUUID& characteristic_uuid) {
std::vector<device::BluetoothRemoteGattCharacteristic*> characteristics;
- VLOG(1) << "Looking for characteristic: " << characteristic_uuid;
+ VLOG(1) << "Looking for characteristic: "
+ << characteristic_uuid.canonical_value();
for (device::BluetoothRemoteGattCharacteristic* characteristic :
service->GetCharacteristics()) {
VLOG(1) << "Characteristic in cache: "
<< characteristic->GetUUID().canonical_value();
- if (characteristic->GetUUID().canonical_value() == characteristic_uuid) {
+ if (characteristic->GetUUID() == characteristic_uuid) {
characteristics.push_back(characteristic);
}
}
@@ -144,14 +151,29 @@ GetCharacteristicsByUUID(device::BluetoothRemoteGattService* service,
// Replace when implemented. http://crbug.com/552022
std::vector<device::BluetoothRemoteGattService*> GetPrimaryServicesByUUID(
device::BluetoothDevice* device,
- const std::string& service_uuid) {
+ const BluetoothUUID& service_uuid) {
+ std::vector<device::BluetoothRemoteGattService*> services;
+ VLOG(1) << "Looking for service: " << service_uuid.canonical_value();
+ for (device::BluetoothRemoteGattService* service :
+ device->GetGattServices()) {
+ VLOG(1) << "Service in cache: " << service->GetUUID().canonical_value();
+ if (service->GetUUID() == service_uuid && service->IsPrimary()) {
+ services.push_back(service);
+ }
+ }
+ return services;
+}
+
+// TODO(ortuno): This should really be a BluetoothDevice method.
+// Replace when implemented. http://crbug.com/552022
+std::vector<device::BluetoothRemoteGattService*> GetPrimaryServices(
+ device::BluetoothDevice* device) {
std::vector<device::BluetoothRemoteGattService*> services;
- VLOG(1) << "Looking for service: " << service_uuid;
+ VLOG(1) << "Looking for services.";
for (device::BluetoothRemoteGattService* service :
device->GetGattServices()) {
VLOG(1) << "Service in cache: " << service->GetUUID().canonical_value();
- if (service->GetUUID().canonical_value() == service_uuid &&
- service->IsPrimary()) {
+ if (service->IsPrimary()) {
services.push_back(service);
}
}
@@ -170,13 +192,11 @@ WebBluetoothServiceImpl::WebBluetoothServiceImpl(
weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(web_contents());
-
- GetBluetoothDispatcherHost()->AddAdapterObserver(this);
}
WebBluetoothServiceImpl::~WebBluetoothServiceImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- GetBluetoothDispatcherHost()->RemoveAdapterObserver(this);
+ ClearState();
}
void WebBluetoothServiceImpl::SetClientConnectionErrorHandler(
@@ -193,11 +213,22 @@ void WebBluetoothServiceImpl::DidFinishNavigation(
}
}
-void WebBluetoothServiceImpl::AdapterPresentChanged(
+void WebBluetoothServiceImpl::AdapterPoweredChanged(
device::BluetoothAdapter* adapter,
- bool present) {
- if (!present) {
- ClearState();
+ bool powered) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (device_chooser_controller_.get()) {
+ device_chooser_controller_->AdapterPoweredChanged(powered);
+ }
+}
+
+void WebBluetoothServiceImpl::DeviceAdded(device::BluetoothAdapter* adapter,
+ device::BluetoothDevice* device) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (device_chooser_controller_.get()) {
+ VLOG(1) << "Adding device to device chooser controller: "
+ << device->GetAddress();
+ device_chooser_controller_->AddFilteredDevice(*device);
}
}
@@ -276,14 +307,35 @@ void WebBluetoothServiceImpl::SetClient(
client_.Bind(std::move(client));
}
+void WebBluetoothServiceImpl::RequestDevice(
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
+ const RequestDeviceCallback& callback) {
+ RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::REQUEST_DEVICE);
+ RecordRequestDeviceOptions(options);
+
+ if (!GetAdapter()) {
+ if (GetBluetoothAdapterFactoryWrapper()->IsBluetoothAdapterAvailable()) {
+ GetBluetoothAdapterFactoryWrapper()->AcquireAdapter(
+ this, base::Bind(&WebBluetoothServiceImpl::RequestDeviceImpl,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(std::move(options)), callback));
+ return;
+ }
+ RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER);
+ callback.Run(blink::mojom::WebBluetoothError::NO_BLUETOOTH_ADAPTER,
+ nullptr /* device */);
+ return;
+ }
+ RequestDeviceImpl(std::move(options), callback, GetAdapter());
+}
+
void WebBluetoothServiceImpl::RemoteServerConnect(
const mojo::String& device_id,
const RemoteServerConnectCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT);
- const CacheQueryResult query_result =
- GetBluetoothDispatcherHost()->QueryCacheForDevice(GetOrigin(), device_id);
+ const CacheQueryResult query_result = QueryCacheForDevice(device_id);
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
RecordConnectGATTOutcome(query_result.outcome);
@@ -328,32 +380,34 @@ void WebBluetoothServiceImpl::RemoteServerDisconnect(
}
}
-void WebBluetoothServiceImpl::RemoteServerGetPrimaryService(
+void WebBluetoothServiceImpl::RemoteServerGetPrimaryServices(
const mojo::String& device_id,
- const mojo::String& service_uuid,
- const RemoteServerGetPrimaryServiceCallback& callback) {
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ const base::Optional<BluetoothUUID>& services_uuid,
+ const RemoteServerGetPrimaryServicesCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_PRIMARY_SERVICE);
- RecordGetPrimaryServiceService(device::BluetoothUUID(service_uuid));
+ RecordWebBluetoothFunctionCall(
+ quantity == blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE
+ ? UMAWebBluetoothFunction::GET_PRIMARY_SERVICE
+ : UMAWebBluetoothFunction::GET_PRIMARY_SERVICES);
+ RecordGetPrimaryServicesServices(quantity, services_uuid);
- if (!GetBluetoothDispatcherHost()
- ->allowed_devices_map_.IsOriginAllowedToAccessService(
- GetOrigin(), device_id, service_uuid)) {
+ 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 */);
return;
}
- const CacheQueryResult query_result =
- GetBluetoothDispatcherHost()->QueryCacheForDevice(GetOrigin(), device_id);
+ const CacheQueryResult query_result = QueryCacheForDevice(device_id);
if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) {
- binding_.Close();
return;
}
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
- RecordGetPrimaryServiceOutcome(query_result.outcome);
+ RecordGetPrimaryServicesOutcome(quantity, query_result.outcome);
callback.Run(query_result.GetWebError(), nullptr /* service */);
return;
}
@@ -363,32 +417,32 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryService(
// We can't know if a service is present or not until GATT service discovery
// is complete for the device.
if (query_result.device->IsGattServicesDiscoveryComplete()) {
- RemoteServerGetPrimaryServiceImpl(service_uuid, callback,
- query_result.device);
+ RemoteServerGetPrimaryServicesImpl(device_id, quantity, services_uuid,
+ callback, query_result.device);
return;
}
VLOG(1) << "Services not yet discovered.";
- pending_primary_services_requests_[device_address].push_back(
- base::Bind(&WebBluetoothServiceImpl::RemoteServerGetPrimaryServiceImpl,
- base::Unretained(this), service_uuid, callback));
+ pending_primary_services_requests_[device_address].push_back(base::Bind(
+ &WebBluetoothServiceImpl::RemoteServerGetPrimaryServicesImpl,
+ base::Unretained(this), device_id, quantity, services_uuid, callback));
}
void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
const mojo::String& service_instance_id,
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
- const mojo::String& characteristics_uuid,
+ const base::Optional<BluetoothUUID>& characteristics_uuid,
const RemoteServiceGetCharacteristicsCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
RecordWebBluetoothFunctionCall(
quantity == blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE
? UMAWebBluetoothFunction::SERVICE_GET_CHARACTERISTIC
: UMAWebBluetoothFunction::SERVICE_GET_CHARACTERISTICS);
RecordGetCharacteristicsCharacteristic(quantity, characteristics_uuid);
- if (!characteristics_uuid.is_null() &&
- BluetoothBlacklist::Get().IsExcluded(
- device::BluetoothUUID(characteristics_uuid))) {
+ if (characteristics_uuid &&
+ BluetoothBlacklist::Get().IsExcluded(characteristics_uuid.value())) {
RecordGetCharacteristicsOutcome(quantity,
UMAGetCharacteristicOutcome::BLACKLISTED);
callback.Run(
@@ -401,7 +455,6 @@ void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
QueryCacheForService(service_instance_id);
if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) {
- binding_.Close();
return;
}
@@ -412,10 +465,10 @@ void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
}
std::vector<device::BluetoothRemoteGattCharacteristic*> characteristics =
- characteristics_uuid.is_null()
- ? query_result.service->GetCharacteristics()
- : GetCharacteristicsByUUID(query_result.service,
- characteristics_uuid);
+ characteristics_uuid
+ ? GetCharacteristicsByUUID(query_result.service,
+ characteristics_uuid.value())
+ : query_result.service->GetCharacteristics();
mojo::Array<blink::mojom::WebBluetoothRemoteGATTCharacteristicPtr>
response_characteristics;
@@ -451,15 +504,15 @@ void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics(
std::move(response_characteristics));
return;
}
+
RecordGetCharacteristicsOutcome(
- quantity, characteristics_uuid.is_null()
- ? UMAGetCharacteristicOutcome::NO_CHARACTERISTICS
- : UMAGetCharacteristicOutcome::NOT_FOUND);
- callback.Run(characteristics_uuid.is_null()
- ? blink::mojom::WebBluetoothError::NO_CHARACTERISTICS_FOUND
- : blink::mojom::WebBluetoothError::CHARACTERISTIC_NOT_FOUND,
+ quantity, characteristics_uuid
+ ? UMAGetCharacteristicOutcome::NOT_FOUND
+ : UMAGetCharacteristicOutcome::NO_CHARACTERISTICS);
+ callback.Run(characteristics_uuid
+ ? blink::mojom::WebBluetoothError::CHARACTERISTIC_NOT_FOUND
+ : blink::mojom::WebBluetoothError::NO_CHARACTERISTICS_FOUND,
nullptr /* characteristics */);
- return;
}
void WebBluetoothServiceImpl::RemoteCharacteristicReadValue(
@@ -614,39 +667,136 @@ void WebBluetoothServiceImpl::RemoteCharacteristicStopNotifications(
weak_ptr_factory_.GetWeakPtr(), characteristic_instance_id, callback));
}
-void WebBluetoothServiceImpl::RemoteServerGetPrimaryServiceImpl(
- const std::string& service_uuid,
- const RemoteServerGetPrimaryServiceCallback& callback,
+void WebBluetoothServiceImpl::RequestDeviceImpl(
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
+ const RequestDeviceCallback& callback,
+ device::BluetoothAdapter* adapter) {
+ // requestDevice() can only be called when processing a user-gesture and any
+ // user gesture outside of a chooser should close the chooser. This does
+ // not happen on all platforms so we don't DCHECK that the old one is closed.
+ // We destroy the old chooser before constructing the new one to make sure
+ // they can't conflict.
+ device_chooser_controller_.reset();
+
+ device_chooser_controller_.reset(new BluetoothDeviceChooserController(
+ this, render_frame_host_, adapter,
+ GetBluetoothAdapterFactoryWrapper()->GetScanDuration()));
+
+ device_chooser_controller_->GetDevice(
+ std::move(options),
+ base::Bind(&WebBluetoothServiceImpl::OnGetDeviceSuccess,
+ weak_ptr_factory_.GetWeakPtr(), callback),
+ base::Bind(&WebBluetoothServiceImpl::OnGetDeviceFailed,
+ weak_ptr_factory_.GetWeakPtr(), callback));
+}
+
+void WebBluetoothServiceImpl::RemoteServerGetPrimaryServicesImpl(
+ const mojo::String& device_id,
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ const base::Optional<BluetoothUUID>& services_uuid,
+ const RemoteServerGetPrimaryServicesCallback& callback,
device::BluetoothDevice* device) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(device->IsGattServicesDiscoveryComplete());
std::vector<device::BluetoothRemoteGattService*> services =
- GetPrimaryServicesByUUID(device, service_uuid);
+ services_uuid ? GetPrimaryServicesByUUID(device, services_uuid.value())
+ : GetPrimaryServices(device);
- if (services.empty()) {
- VLOG(1) << "Service not found in device.";
- RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NOT_FOUND);
- callback.Run(blink::mojom::WebBluetoothError::SERVICE_NOT_FOUND,
- nullptr /* service */);
+ mojo::Array<blink::mojom::WebBluetoothRemoteGATTServicePtr> response_services;
+ for (device::BluetoothRemoteGattService* service : services) {
+ if (!allowed_devices_map_.IsOriginAllowedToAccessService(
+ GetOrigin(), device_id, service->GetUUID())) {
+ continue;
+ }
+ std::string service_instance_id = service->GetIdentifier();
+ const std::string& device_address = device->GetAddress();
+ auto insert_result = service_id_to_device_address_.insert(
+ make_pair(service_instance_id, device_address));
+ // If value is already in map, DCHECK it's valid.
+ if (!insert_result.second)
+ DCHECK_EQ(insert_result.first->second, device_address);
+
+ blink::mojom::WebBluetoothRemoteGATTServicePtr service_ptr =
+ blink::mojom::WebBluetoothRemoteGATTService::New();
+ service_ptr->instance_id = service_instance_id;
+ service_ptr->uuid = service->GetUUID().canonical_value();
+ response_services.push_back(std::move(service_ptr));
+
+ if (quantity == blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE) {
+ break;
+ }
+ }
+
+ if (!response_services.empty()) {
+ VLOG(1) << "Services found in device.";
+ RecordGetPrimaryServicesOutcome(quantity,
+ UMAGetPrimaryServiceOutcome::SUCCESS);
+ callback.Run(blink::mojom::WebBluetoothError::SUCCESS,
+ std::move(response_services));
+ return;
+ }
+
+ VLOG(1) << "Services not found in device.";
+ RecordGetPrimaryServicesOutcome(
+ 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 */);
+}
+
+void WebBluetoothServiceImpl::OnGetDeviceSuccess(
+ const RequestDeviceCallback& callback,
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
+ const std::string& device_address) {
+ device_chooser_controller_.reset();
+
+ const device::BluetoothDevice* const device =
+ GetAdapter()->GetDevice(device_address);
+ 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,
+ nullptr /* device */);
return;
}
- VLOG(1) << "Service found in device.";
- std::string service_instance_id = services[0]->GetIdentifier();
- std::string device_address = device->GetAddress();
- auto insert_result = service_id_to_device_address_.insert(
- make_pair(service_instance_id, device_address));
- if (!insert_result.second)
- DCHECK_EQ(insert_result.first->second, device_address);
+ const std::string device_id_for_origin =
+ allowed_devices_map_.AddDevice(GetOrigin(), device_address, options);
- RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::SUCCESS);
- blink::mojom::WebBluetoothRemoteGATTServicePtr service_ptr =
- blink::mojom::WebBluetoothRemoteGATTService::New();
- service_ptr->instance_id = services[0]->GetIdentifier();
- service_ptr->uuid = services[0]->GetUUID().canonical_value();
- callback.Run(blink::mojom::WebBluetoothError::SUCCESS,
- std::move(service_ptr));
+ 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;
+ // TODO(615720): Use the upcoming GetName (was GetDeviceName).
+ device_ptr->name = base::UTF16ToUTF8(device->GetNameForDisplay());
+ device_ptr->uuids = std::move(filtered_uuids);
+
+ RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS);
+ callback.Run(blink::mojom::WebBluetoothError::SUCCESS, std::move(device_ptr));
+}
+
+void WebBluetoothServiceImpl::OnGetDeviceFailed(
+ const RequestDeviceCallback& callback,
+ blink::mojom::WebBluetoothError error) {
+ // Errors are recorded by the *device_chooser_controller_.
+ callback.Run(error, nullptr /* device */);
+ device_chooser_controller_.reset();
}
void WebBluetoothServiceImpl::OnCreateGATTConnectionSuccess(
@@ -734,6 +884,27 @@ void WebBluetoothServiceImpl::OnStopNotifySessionComplete(
callback.Run();
}
+CacheQueryResult WebBluetoothServiceImpl::QueryCacheForDevice(
+ const std::string& device_id) {
+ const std::string& device_address =
+ allowed_devices_map_.GetDeviceAddress(GetOrigin(), device_id);
+ if (device_address.empty()) {
+ CrashRendererAndClosePipe(bad_message::BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN);
+ return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER);
+ }
+
+ CacheQueryResult result;
+ result.device = GetAdapter()->GetDevice(device_address);
+
+ // When a device can't be found in the BluetoothAdapter, that generally
+ // indicates that it's gone out of range. We reject with a NetworkError in
+ // that case.
+ if (result.device == nullptr) {
+ result.outcome = CacheQueryOutcome::NO_DEVICE;
+ }
+ return result;
+}
+
CacheQueryResult WebBluetoothServiceImpl::QueryCacheForService(
const std::string& service_instance_id) {
auto device_iter = service_id_to_device_address_.find(service_instance_id);
@@ -745,23 +916,14 @@ CacheQueryResult WebBluetoothServiceImpl::QueryCacheForService(
}
const std::string& device_id =
- GetBluetoothDispatcherHost()->allowed_devices_map_.GetDeviceId(
- GetOrigin(), device_iter->second);
+ allowed_devices_map_.GetDeviceId(GetOrigin(), device_iter->second);
// Kill the renderer if origin is not allowed to access the device.
if (device_id.empty()) {
CrashRendererAndClosePipe(bad_message::BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN);
return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER);
}
- CacheQueryResult result =
- GetBluetoothDispatcherHost()->QueryCacheForDevice(GetOrigin(), device_id);
-
- // TODO(ortuno): Remove once QueryCacheForDevice closes binding_.
- // http://crbug.com/508771
- if (result.outcome == CacheQueryOutcome::BAD_RENDERER) {
- binding_.Close();
- }
-
+ CacheQueryResult result = QueryCacheForDevice(device_id);
if (result.outcome != CacheQueryOutcome::SUCCESS) {
return result;
}
@@ -769,10 +931,8 @@ CacheQueryResult WebBluetoothServiceImpl::QueryCacheForService(
result.service = result.device->GetGattService(service_instance_id);
if (result.service == nullptr) {
result.outcome = CacheQueryOutcome::NO_SERVICE;
- } else if (!GetBluetoothDispatcherHost()
- ->allowed_devices_map_.IsOriginAllowedToAccessService(
- GetOrigin(), device_id,
- result.service->GetUUID().canonical_value())) {
+ } else if (!allowed_devices_map_.IsOriginAllowedToAccessService(
+ GetOrigin(), device_id, result.service->GetUUID())) {
CrashRendererAndClosePipe(bad_message::BDH_SERVICE_NOT_ALLOWED_FOR_ORIGIN);
return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER);
}
@@ -810,10 +970,15 @@ RenderProcessHost* WebBluetoothServiceImpl::GetRenderProcessHost() {
return render_frame_host_->GetProcess();
}
-BluetoothDispatcherHost* WebBluetoothServiceImpl::GetBluetoothDispatcherHost() {
+BluetoothAdapterFactoryWrapper*
+WebBluetoothServiceImpl::GetBluetoothAdapterFactoryWrapper() {
RenderProcessHostImpl* render_process_host_impl =
static_cast<RenderProcessHostImpl*>(GetRenderProcessHost());
- return render_process_host_impl->GetBluetoothDispatcherHost();
+ return render_process_host_impl->GetBluetoothAdapterFactoryWrapper();
+}
+
+device::BluetoothAdapter* WebBluetoothServiceImpl::GetAdapter() {
+ return GetBluetoothAdapterFactoryWrapper()->GetAdapter(this);
}
void WebBluetoothServiceImpl::CrashRendererAndClosePipe(
@@ -833,6 +998,9 @@ void WebBluetoothServiceImpl::ClearState() {
service_id_to_device_address_.clear();
connected_devices_.reset(
new FrameConnectedBluetoothDevices(render_frame_host_));
+ allowed_devices_map_ = BluetoothAllowedDevicesMap();
+ device_chooser_controller_.reset();
+ GetBluetoothAdapterFactoryWrapper()->ReleaseAdapter(this);
}
} // namespace content
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
index 44e1858594e..4c07543c96e 100644
--- a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -10,7 +10,9 @@
#include <vector>
#include "base/macros.h"
+#include "base/optional.h"
#include "content/browser/bad_message.h"
+#include "content/browser/bluetooth/bluetooth_allowed_devices_map.h"
#include "content/browser/bluetooth/cache_query_result.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
@@ -28,7 +30,8 @@ class Origin;
namespace content {
-class BluetoothDispatcherHost;
+class BluetoothDeviceChooserController;
+class BluetoothAdapterFactoryWrapper;
class FrameConnectedBluetoothDevices;
class RenderFrameHost;
class RenderProcessHost;
@@ -53,6 +56,8 @@ class WebBluetoothServiceImpl : public blink::mojom::WebBluetoothService,
blink::mojom::WebBluetoothServiceRequest request);
~WebBluetoothServiceImpl() override;
+ void CrashRendererAndClosePipe(bad_message::BadMessageReason reason);
+
// Sets the connection error handler for WebBluetoothServiceImpl's Binding.
void SetClientConnectionErrorHandler(base::Closure closure);
@@ -66,8 +71,10 @@ class WebBluetoothServiceImpl : public blink::mojom::WebBluetoothService,
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
// BluetoothAdapter::Observer:
- void AdapterPresentChanged(device::BluetoothAdapter* adapter,
- bool present) override;
+ void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
+ bool powered) override;
+ void DeviceAdded(device::BluetoothAdapter* adapter,
+ device::BluetoothDevice* device) override;
void DeviceChanged(device::BluetoothAdapter* adapter,
device::BluetoothDevice* device) override;
void GattServicesDiscovered(device::BluetoothAdapter* adapter,
@@ -87,18 +94,21 @@ class WebBluetoothServiceImpl : public blink::mojom::WebBluetoothService,
// WebBluetoothService methods:
void SetClient(
blink::mojom::WebBluetoothServiceClientAssociatedPtrInfo client) override;
+ void RequestDevice(blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
+ const RequestDeviceCallback& callback) override;
void RemoteServerConnect(
const mojo::String& device_id,
const RemoteServerConnectCallback& callback) override;
void RemoteServerDisconnect(const mojo::String& device_id) override;
- void RemoteServerGetPrimaryService(
+ void RemoteServerGetPrimaryServices(
const mojo::String& device_id,
- const mojo::String& service_uuid,
- const RemoteServerGetPrimaryServiceCallback& callback) override;
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ const base::Optional<device::BluetoothUUID>& services_uuid,
+ const RemoteServerGetPrimaryServicesCallback& callback) override;
void RemoteServiceGetCharacteristics(
const mojo::String& service_instance_id,
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
- const mojo::String& characteristics_uuid,
+ const base::Optional<device::BluetoothUUID>& characteristics_uuid,
const RemoteServiceGetCharacteristicsCallback& callback) override;
void RemoteCharacteristicReadValue(
const mojo::String& characteristic_instance_id,
@@ -114,13 +124,28 @@ class WebBluetoothServiceImpl : public blink::mojom::WebBluetoothService,
const mojo::String& characteristic_instance_id,
const RemoteCharacteristicStopNotificationsCallback& callback) override;
+ void RequestDeviceImpl(
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
+ const RequestDeviceCallback& callback,
+ device::BluetoothAdapter* adapter);
+
// Should only be run after the services have been discovered for
// |device_address|.
- void RemoteServerGetPrimaryServiceImpl(
- const std::string& service_uuid,
- const RemoteServerGetPrimaryServiceCallback& callback,
+ void RemoteServerGetPrimaryServicesImpl(
+ const mojo::String& device_id,
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ const base::Optional<device::BluetoothUUID>& services_uuid,
+ const RemoteServerGetPrimaryServicesCallback& callback,
device::BluetoothDevice* device);
+ // Callbacks for BluetoothDeviceChooserController::GetDevice.
+ void OnGetDeviceSuccess(
+ const RequestDeviceCallback& callback,
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
+ const std::string& device_id);
+ void OnGetDeviceFailed(const RequestDeviceCallback& callback,
+ blink::mojom::WebBluetoothError error);
+
// Callbacks for BluetoothDevice::CreateGattConnection.
void OnCreateGATTConnectionSuccess(
const std::string& device_id,
@@ -168,6 +193,10 @@ class WebBluetoothServiceImpl : public blink::mojom::WebBluetoothService,
// renderer, record the reason and close the pipe, so it's safe to drop
// any callbacks.
+ // Queries the platform cache for a Device with |device_id| for |origin|.
+ // Fills in the |outcome| field and the |device| field if successful.
+ CacheQueryResult QueryCacheForDevice(const std::string& device_id);
+
// Queries the platform cache for a Service with |service_instance_id|. Fills
// in the |outcome| field, and |device| and |service| fields if successful.
CacheQueryResult QueryCacheForService(const std::string& service_instance_id);
@@ -179,13 +208,19 @@ class WebBluetoothServiceImpl : public blink::mojom::WebBluetoothService,
const std::string& characteristic_instance_id);
RenderProcessHost* GetRenderProcessHost();
- BluetoothDispatcherHost* GetBluetoothDispatcherHost();
- void CrashRendererAndClosePipe(bad_message::BadMessageReason reason);
+ BluetoothAdapterFactoryWrapper* GetBluetoothAdapterFactoryWrapper();
+ device::BluetoothAdapter* GetAdapter();
url::Origin GetOrigin();
// Clears all state (maps, sets, etc).
void ClearState();
+ // Used to open a BluetoothChooser and start a device discovery session.
+ std::unique_ptr<BluetoothDeviceChooserController> device_chooser_controller_;
+
+ // Keeps track of which devices the frame's origin is allowed to access.
+ BluetoothAllowedDevicesMap allowed_devices_map_;
+
// Maps to get the object's parent based on its instanceID.
std::unordered_map<std::string, std::string> service_id_to_device_address_;
std::unordered_map<std::string, std::string> characteristic_id_to_service_id_;
diff --git a/chromium/content/browser/bookmarklet_browsertest.cc b/chromium/content/browser/bookmarklet_browsertest.cc
index 5ec10d505a5..b4ae75ab4d2 100644
--- a/chromium/content/browser/bookmarklet_browsertest.cc
+++ b/chromium/content/browser/bookmarklet_browsertest.cc
@@ -23,7 +23,7 @@ class BookmarkletTest : public ContentBrowserTest {
std::string GetBodyText() {
std::string body_text;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(document.body.innerText);",
&body_text));
return body_text;
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index 061240a62a9..1a0af7bb25a 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -18,8 +18,9 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "components/tracing/tracing_switches.h"
+#include "components/tracing/common/tracing_switches.h"
#include "content/browser/histogram_message_filter.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/memory/memory_message_filter.h"
@@ -82,7 +83,16 @@ void NotifyProcessKilled(const ChildProcessData& data, int exit_code) {
BrowserChildProcessHost* BrowserChildProcessHost::Create(
content::ProcessType process_type,
BrowserChildProcessHostDelegate* delegate) {
- return new BrowserChildProcessHostImpl(process_type, delegate);
+ return new BrowserChildProcessHostImpl(
+ process_type, delegate, mojo::edk::GenerateRandomToken());
+}
+
+BrowserChildProcessHost* BrowserChildProcessHost::Create(
+ content::ProcessType process_type,
+ BrowserChildProcessHostDelegate* delegate,
+ const std::string& mojo_child_token) {
+ return new BrowserChildProcessHostImpl(
+ process_type, delegate, mojo_child_token);
}
BrowserChildProcessHost* BrowserChildProcessHost::FromID(int child_process_id) {
@@ -124,12 +134,15 @@ void BrowserChildProcessHostImpl::RemoveObserver(
BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
content::ProcessType process_type,
- BrowserChildProcessHostDelegate* delegate)
+ BrowserChildProcessHostDelegate* delegate,
+ const std::string& mojo_child_token)
: data_(process_type),
delegate_(delegate),
+ mojo_child_token_(mojo_child_token),
power_monitor_message_broadcaster_(this),
is_channel_connected_(false),
- notify_child_disconnected_(false) {
+ notify_child_disconnected_(false),
+ weak_factory_(this) {
data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
#if USE_ATTACHMENT_BROKER
@@ -229,6 +242,10 @@ void BrowserChildProcessHostImpl::Launch(
cmd_line,
data_.id,
this,
+ mojo_child_token_,
+ base::Bind(&BrowserChildProcessHostImpl::OnMojoError,
+ weak_factory_.GetWeakPtr(),
+ base::ThreadTaskRunnerHandle::Get()),
terminate_on_shutdown));
}
@@ -261,9 +278,14 @@ void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) {
data_.handle = handle;
}
-ServiceRegistry* BrowserChildProcessHostImpl::GetServiceRegistry() {
+shell::InterfaceRegistry* BrowserChildProcessHostImpl::GetInterfaceRegistry() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return delegate_->GetServiceRegistry();
+ return delegate_->GetInterfaceRegistry();
+}
+
+shell::InterfaceProvider* BrowserChildProcessHostImpl::GetRemoteInterfaces() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return delegate_->GetRemoteInterfaces();
}
void BrowserChildProcessHostImpl::ForceShutdown() {
@@ -457,6 +479,33 @@ bool BrowserChildProcessHostImpl::IsProcessLaunched() const {
return child_process_.get() && child_process_->GetProcess().IsValid();
}
+// static
+void BrowserChildProcessHostImpl::OnMojoError(
+ base::WeakPtr<BrowserChildProcessHostImpl> process,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const std::string& error) {
+ if (!task_runner->BelongsToCurrentThread()) {
+ task_runner->PostTask(
+ FROM_HERE, base::Bind(&BrowserChildProcessHostImpl::OnMojoError,
+ process, task_runner, error));
+ }
+ if (!process)
+ return;
+ HistogramBadMessageTerminated(process->data_.process_type);
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableKillAfterBadIPC)) {
+ return;
+ }
+ LOG(ERROR) << "Terminating child process for bad Mojo message: " << error;
+
+ // Create a memory dump with the error message aliased. This will make it easy
+ // to determine details about what interface call failed.
+ base::debug::Alias(&error);
+ base::debug::DumpWithoutCrashing();
+ process->child_process_->GetProcess().Terminate(
+ RESULT_CODE_KILLED_BAD_MESSAGE, false);
+}
+
#if defined(OS_WIN)
void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) {
diff --git a/chromium/content/browser/browser_child_process_host_impl.h b/chromium/content/browser/browser_child_process_host_impl.h
index e2581ccec0c..520ce5784ef 100644
--- a/chromium/content/browser/browser_child_process_host_impl.h
+++ b/chromium/content/browser/browser_child_process_host_impl.h
@@ -11,7 +11,10 @@
#include <memory>
#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.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"
@@ -28,12 +31,16 @@ namespace base {
class CommandLine;
}
+namespace shell {
+class InterfaceProvider;
+class InterfaceRegistry;
+}
+
namespace content {
class BrowserChildProcessHostIterator;
class BrowserChildProcessObserver;
class BrowserMessageFilter;
-class ServiceRegistry;
// Plugins/workers and other child processes that live on the IO thread use this
// class. RenderProcessHostImpl is the main exception that doesn't use this
@@ -47,7 +54,8 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
public ChildProcessLauncher::Client {
public:
BrowserChildProcessHostImpl(content::ProcessType process_type,
- BrowserChildProcessHostDelegate* delegate);
+ BrowserChildProcessHostDelegate* delegate,
+ const std::string& mojo_child_token);
~BrowserChildProcessHostImpl() override;
// Terminates all child processes and deletes each BrowserChildProcessHost
@@ -70,7 +78,8 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
int* exit_code) override;
void SetName(const base::string16& name) override;
void SetHandle(base::ProcessHandle handle) override;
- ServiceRegistry* GetServiceRegistry() override;
+ shell::InterfaceRegistry* GetInterfaceRegistry() override;
+ shell::InterfaceProvider* GetRemoteInterfaces() override;
// ChildProcessHostDelegate implementation:
bool CanShutdown() override;
@@ -116,6 +125,11 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
// on the IO thread.
bool IsProcessLaunched() const;
+ static void OnMojoError(
+ base::WeakPtr<BrowserChildProcessHostImpl> process,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const std::string& error);
+
#if defined(OS_WIN)
// ObjectWatcher::Delegate implementation.
void OnObjectSignaled(HANDLE object) override;
@@ -124,6 +138,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
ChildProcessData data_;
BrowserChildProcessHostDelegate* delegate_;
std::unique_ptr<ChildProcessHost> child_process_host_;
+ const std::string mojo_child_token_;
std::unique_ptr<ChildProcessLauncher> child_process_;
@@ -138,6 +153,8 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
bool is_channel_connected_;
bool notify_child_disconnected_;
+
+ base::WeakPtrFactory<BrowserChildProcessHostImpl> weak_factory_;
};
} // namespace content
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index a782fc41c6a..a1c1d0acdfc 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -17,12 +17,12 @@
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/rand_util.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/mojo/browser_shell_connection.h"
#include "content/browser/mojo/constants.h"
#include "content/browser/push_messaging/push_messaging_router.h"
#include "content/browser/storage_partition_impl_map.h"
@@ -53,21 +53,43 @@ namespace content {
namespace {
-base::LazyInstance<std::set<std::string>> g_used_user_ids =
- LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<std::vector<std::pair<BrowserContext*, std::string>>>
-g_context_to_user_id = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<std::map<std::string, BrowserContext*>>
+ g_user_id_to_context = LAZY_INSTANCE_INITIALIZER;
+
+class ShellUserIdHolder : public base::SupportsUserData::Data {
+ public:
+ explicit ShellUserIdHolder(const std::string& user_id) : user_id_(user_id) {}
+ ~ShellUserIdHolder() override {}
+
+ const std::string& user_id() const { return user_id_; }
+
+ private:
+ std::string user_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellUserIdHolder);
+};
// Key names on BrowserContext.
const char kDownloadManagerKeyName[] = "download_manager";
const char kMojoShellConnection[] = "mojo-shell-connection";
const char kMojoWasInitialized[] = "mojo-was-initialized";
+const char kMojoShellUserId[] = "mojo-shell-user-id";
const char kStoragePartitionMapKeyName[] = "content_storage_partition_map";
#if defined(OS_CHROMEOS)
const char kMountPointsKey[] = "mount_points";
#endif // defined(OS_CHROMEOS)
+void RemoveBrowserContextFromUserIdMap(BrowserContext* browser_context) {
+ ShellUserIdHolder* holder = static_cast<ShellUserIdHolder*>(
+ browser_context->GetUserData(kMojoShellUserId));
+ if (holder) {
+ auto it = g_user_id_to_context.Get().find(holder->user_id());
+ if (it != g_user_id_to_context.Get().end())
+ g_user_id_to_context.Get().erase(it);
+ }
+}
+
StoragePartitionImplMap* GetStoragePartitionMap(
BrowserContext* browser_context) {
StoragePartitionImplMap* partition_map =
@@ -130,14 +152,14 @@ class BrowserContextShellConnectionHolder
std::unique_ptr<shell::Connection> connection,
shell::mojom::ShellClientRequest request)
: root_connection_(std::move(connection)),
- shell_connection_(new BrowserShellConnection(std::move(request))) {}
+ shell_connection_(MojoShellConnection::Create(std::move(request))) {}
~BrowserContextShellConnectionHolder() override {}
- BrowserShellConnection* shell_connection() { return shell_connection_.get(); }
+ MojoShellConnection* shell_connection() { return shell_connection_.get(); }
private:
std::unique_ptr<shell::Connection> root_connection_;
- std::unique_ptr<BrowserShellConnection> shell_connection_;
+ std::unique_ptr<MojoShellConnection> shell_connection_;
DISALLOW_COPY_AND_ASSIGN(BrowserContextShellConnectionHolder);
};
@@ -366,20 +388,31 @@ void BrowserContext::SetDownloadManagerForTesting(
void BrowserContext::Initialize(
BrowserContext* browser_context,
const base::FilePath& path) {
- // Generate a GUID for |browser_context| to use as the Mojo user id.
- std::string new_id = base::GenerateGUID();
- while (g_used_user_ids.Get().find(new_id) != g_used_user_ids.Get().end())
+
+ std::string new_id;
+ if (GetContentClient() && GetContentClient()->browser()) {
+ new_id = GetContentClient()->browser()->GetShellUserIdForBrowserContext(
+ browser_context);
+ } else {
+ // Some test scenarios initialize a BrowserContext without a content client.
new_id = base::GenerateGUID();
+ }
- g_used_user_ids.Get().insert(new_id);
- g_context_to_user_id.Get().push_back(std::make_pair(browser_context, new_id));
+ ShellUserIdHolder* holder = static_cast<ShellUserIdHolder*>(
+ browser_context->GetUserData(kMojoShellUserId));
+ if (holder)
+ user_service::ForgetShellUserIdUserDirAssociation(holder->user_id());
+ user_service::AssociateShellUserIdWithUserDir(new_id, path);
+ RemoveBrowserContextFromUserIdMap(browser_context);
+ g_user_id_to_context.Get()[new_id] = browser_context;
+ browser_context->SetUserData(kMojoShellUserId,
+ new ShellUserIdHolder(new_id));
- user_service::AssociateMojoUserIDWithUserDir(new_id, path);
browser_context->SetUserData(kMojoWasInitialized,
new base::SupportsUserData::Data);
- MojoShellConnection* shell = MojoShellConnection::Get();
- if (shell) {
+ MojoShellConnection* shell = MojoShellConnection::GetForProcess();
+ if (shell && base::ThreadTaskRunnerHandle::IsSet()) {
// NOTE: Many unit tests create a TestBrowserContext without initializing
// Mojo or the global Mojo shell connection.
@@ -400,9 +433,9 @@ void BrowserContext::Initialize(
std::move(shell_client_request));
browser_context->SetUserData(kMojoShellConnection, connection_holder);
- BrowserShellConnection* connection = connection_holder->shell_connection();
+ MojoShellConnection* connection = connection_holder->shell_connection();
- // New embedded application factories should be added to |connection| here.
+ // New embedded service factories should be added to |connection| here.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kMojoLocalStorage)) {
@@ -411,29 +444,32 @@ void BrowserContext::Initialize(
&user_service::CreateUserShellClient,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB));
- connection->AddEmbeddedApplication(user_service::kUserServiceName, info);
+ connection->AddEmbeddedService(user_service::kUserServiceName, info);
}
}
}
// static
-const std::string& BrowserContext::GetMojoUserIdFor(
+const std::string& BrowserContext::GetShellUserIdFor(
BrowserContext* browser_context) {
CHECK(browser_context->GetUserData(kMojoWasInitialized))
<< "Attempting to get the mojo user id for a BrowserContext that was "
<< "never Initialize()ed.";
- auto it = std::find_if(
- g_context_to_user_id.Get().begin(),
- g_context_to_user_id.Get().end(),
- [&browser_context](const std::pair<BrowserContext*, std::string>& p) {
- return p.first == browser_context; });
- CHECK(it != g_context_to_user_id.Get().end());
- return it->second;
+ ShellUserIdHolder* holder = static_cast<ShellUserIdHolder*>(
+ browser_context->GetUserData(kMojoShellUserId));
+ return holder->user_id();
}
// static
-shell::Connector* BrowserContext::GetMojoConnectorFor(
+BrowserContext* BrowserContext::GetBrowserContextForShellUserId(
+ const std::string& user_id) {
+ auto it = g_user_id_to_context.Get().find(user_id);
+ return it != g_user_id_to_context.Get().end() ? it->second : nullptr;
+}
+
+// static
+shell::Connector* BrowserContext::GetShellConnectorFor(
BrowserContext* browser_context) {
BrowserContextShellConnectionHolder* connection_holder =
static_cast<BrowserContextShellConnectionHolder*>(
@@ -448,6 +484,8 @@ BrowserContext::~BrowserContext() {
<< "Attempting to destroy a BrowserContext that never called "
<< "Initialize()";
+ RemoveBrowserContextFromUserIdMap(this);
+
if (GetUserData(kDownloadManagerKeyName))
GetDownloadManager(this)->Shutdown();
}
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index c56d426445c..db8ea8df063 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -25,7 +25,6 @@
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_device_source.h"
#include "base/process/process_metrics.h"
-#include "base/profiler/scoped_profile.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
@@ -37,10 +36,10 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "components/tracing/process_metrics_memory_dump_provider.h"
-#include "components/tracing/trace_config_file.h"
-#include "components/tracing/trace_to_console.h"
-#include "components/tracing/tracing_switches.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"
+#include "components/tracing/common/tracing_switches.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/device_sensors/device_inertial_sensor_service.h"
#include "content/browser/dom_storage/dom_storage_area.h"
@@ -54,6 +53,7 @@
#include "content/browser/gpu/gpu_process_host_ui_shim.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/mojo/mojo_shell_context.h"
#include "content/browser/net/browser_online_state_observer.h"
@@ -73,18 +73,20 @@
#include "content/public/browser/content_browser_client.h"
#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_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/result_codes.h"
#include "device/battery/battery_status_service.h"
-#include "ipc/mojo/scoped_ipc_support.h"
#include "media/base/media.h"
#include "media/base/user_input_monitor.h"
#include "media/midi/midi_manager.h"
#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/scoped_ipc_support.h"
#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 "skia/ext/event_tracer_impl.h"
#include "skia/ext/skia_memory_dump_provider.h"
#include "sql/sql_memory_dump_provider.h"
@@ -101,7 +103,7 @@
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
-#include "components/tracing/graphics_memory_dump_provider_android.h"
+#include "components/tracing/common/graphics_memory_dump_provider_android.h"
#include "content/browser/android/browser_startup_controller.h"
#include "content/browser/android/browser_surface_texture_manager.h"
#include "content/browser/android/tracing_controller_android.h"
@@ -109,6 +111,7 @@
#include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
#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/gl/gl_surface.h"
#endif
@@ -159,7 +162,6 @@
#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include "content/browser/renderer_host/render_sandbox_host_linux.h"
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
#if !defined(OS_ANDROID)
#include "content/public/browser/zygote_handle_linux.h"
@@ -186,15 +188,15 @@
#include "crypto/nss_util.h"
#endif
-#if defined(MOJO_SHELL_CLIENT)
-#include "services/shell/public/cpp/connector.h"
-#include "ui/views/mus/window_manager_connection.h"
-#endif
-
#if defined(ENABLE_VULKAN)
#include "gpu/vulkan/vulkan_implementation.h"
#endif
+#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
+#include "components/mus/common/gpu_service.h" // nogncheck
+#endif
+
+
// One of the linux specific headers defines this as a macro.
#ifdef DestroyAll
#undef DestroyAll
@@ -206,34 +208,10 @@ namespace {
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
void SetupSandbox(const base::CommandLine& parsed_command_line) {
TRACE_EVENT0("startup", "SetupSandbox");
- base::FilePath sandbox_binary;
-
- std::unique_ptr<sandbox::SetuidSandboxHost> setuid_sandbox_host(
- sandbox::SetuidSandboxHost::Create());
-
- const bool want_setuid_sandbox =
- !parsed_command_line.HasSwitch(switches::kNoSandbox) &&
- !parsed_command_line.HasSwitch(switches::kDisableSetuidSandbox) &&
- !setuid_sandbox_host->IsDisabledViaEnvironment();
-
- static const char no_suid_error[] =
- "Running without the SUID sandbox! See "
- "https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md "
- "for more information on developing with the sandbox on.";
- if (want_setuid_sandbox) {
- sandbox_binary = setuid_sandbox_host->GetSandboxBinaryPath();
- if (sandbox_binary.empty()) {
- // This needs to be fatal. Talk to security@chromium.org if you feel
- // otherwise.
- LOG(FATAL) << no_suid_error;
- }
- } else {
- LOG(ERROR) << no_suid_error;
- }
// Tickle the sandbox host and zygote host so they fork now.
RenderSandboxHostLinux::GetInstance()->Init();
- ZygoteHostImpl::GetInstance()->Init(sandbox_binary.value());
+ ZygoteHostImpl::GetInstance()->Init(parsed_command_line);
*GetGenericZygote() = CreateZygote();
RenderProcessHostImpl::EarlyZygoteLaunch();
}
@@ -305,8 +283,8 @@ static void SetUpGLibLogHandler() {
void WaitForMojoShellInitialize() {
// TODO(rockot): Remove this. http://crbug.com/594852.
base::RunLoop wait_loop;
- MojoShellConnectionImpl::Get()->shell_connection()->set_initialize_handler(
- wait_loop.QuitClosure());
+ MojoShellConnection::GetForProcess()->GetShellConnection()->
+ set_initialize_handler(wait_loop.QuitClosure());
wait_loop.Run();
}
#endif // defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
@@ -455,7 +433,6 @@ BrowserMainLoop::~BrowserMainLoop() {
void BrowserMainLoop::Init() {
TRACE_EVENT0("startup", "BrowserMainLoop::Init");
- TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::Init");
parts_.reset(
GetContentClient()->browser()->CreateBrowserMainParts(parameters_));
@@ -465,7 +442,6 @@ void BrowserMainLoop::Init() {
void BrowserMainLoop::EarlyInitialization() {
TRACE_EVENT0("startup", "BrowserMainLoop::EarlyInitialization");
- TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::EarlyInitialization");
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
// No thread should be created before this call, as SetupSandbox()
@@ -559,7 +535,6 @@ void BrowserMainLoop::MainMessageLoopStart() {
// PostMainMessageLoopStart() below.
TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart");
- TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::MainMessageLoopStart");
// Create a MessageLoop if one does not already exist for the current thread.
if (!base::MessageLoop::current())
@@ -725,7 +700,6 @@ int BrowserMainLoop::PreCreateThreads() {
if (parts_) {
TRACE_EVENT0("startup",
"BrowserMainLoop::CreateThreads:PreCreateThreads");
- TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::PreCreateThreads");
result_code_ = parts_->PreCreateThreads();
}
@@ -795,7 +769,6 @@ int BrowserMainLoop::PreCreateThreads() {
void BrowserMainLoop::CreateStartupTasks() {
TRACE_EVENT0("startup", "BrowserMainLoop::CreateStartupTasks");
- TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::CreateStartupTasks");
// First time through, we really want to create all the tasks
if (!startup_task_runner_.get()) {
@@ -845,7 +818,6 @@ void BrowserMainLoop::CreateStartupTasks() {
int BrowserMainLoop::CreateThreads() {
TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads");
- TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::CreateThreads");
base::Thread::Options io_message_loop_options;
io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO;
@@ -949,8 +921,6 @@ int BrowserMainLoop::PreMainMessageLoopRun() {
if (parts_) {
TRACE_EVENT0("startup",
"BrowserMainLoop::CreateThreads:PreMainMessageLoopRun");
- TRACK_SCOPED_REGION(
- "Startup", "BrowserMainLoop::PreMainMessageLoopRun");
parts_->PreMainMessageLoopRun();
}
@@ -1005,9 +975,6 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
parts_->PostMainMessageLoopRun();
}
- if (IsRunningInMojoShell())
- MojoShellConnection::Destroy();
-
#if defined(USE_AURA)
env_.reset();
#endif
@@ -1183,10 +1150,7 @@ void BrowserMainLoop::StopStartupTracingTimer() {
void BrowserMainLoop::InitializeMainThread() {
TRACE_EVENT0("startup", "BrowserMainLoop::InitializeMainThread");
- static const char kThreadName[] = "CrBrowserMain";
- base::PlatformThread::SetName(kThreadName);
- if (main_message_loop_)
- main_message_loop_->set_thread_name(kThreadName);
+ base::PlatformThread::SetName("CrBrowserMain");
// Register the main thread by instantiating it, but don't call any methods.
main_thread_.reset(
@@ -1197,28 +1161,26 @@ int BrowserMainLoop::BrowserThreadsStarted() {
TRACE_EVENT0("startup", "BrowserMainLoop::BrowserThreadsStarted");
// Bring up Mojo IPC and shell as early as possible.
- mojo_ipc_support_.reset(new IPC::ScopedIPCSupport(
+
+ // Disallow mojo sync call in the browser process.
+ bool sync_call_allowed = false;
+ MojoResult result = mojo::edk::SetProperty(
+ MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED, &sync_call_allowed);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+
+ mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport(
BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
->task_runner()));
- if (IsRunningInMojoShell()) {
- if (!MojoShellConnectionImpl::CreateUsingFactory()) {
- mojo::edk::SetParentPipeHandleFromCommandLine();
- MojoShellConnectionImpl::Create();
- MojoShellConnectionImpl::Get()->BindToRequestFromCommandLine();
- }
- }
mojo_shell_context_.reset(new MojoShellContext);
- if (IsRunningInMojoShell()) {
+ if (shell::ShellIsRemote()) {
#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
- MojoShellConnection* mojo_shell_connection = MojoShellConnection::Get();
- if (mojo_shell_connection) {
- // TODO(rockot): Remove the blocking wait for init.
- // http://crbug.com/594852.
+ // TODO(rockot): Remove the blocking wait for init.
+ // http://crbug.com/594852.
+ auto connection = MojoShellConnection::GetForProcess();
+ if (connection) {
WaitForMojoShellInitialize();
- views::WindowManagerConnection::Create(
- mojo_shell_connection->GetConnector(),
- mojo_shell_connection->GetIdentity());
+ mus::GpuService::Initialize(connection->GetConnector());
}
#endif
}
@@ -1305,11 +1267,15 @@ int BrowserMainLoop::BrowserThreadsStarted() {
UMA_HISTOGRAM_BOOLEAN("Windows.Win32kRendererLockdown",
IsWin32kRendererLockdownEnabled());
#endif
+
// RDH needs the IO thread to be created
{
TRACE_EVENT0("startup",
"BrowserMainLoop::BrowserThreadsStarted:InitResourceDispatcherHost");
resource_dispatcher_host_.reset(new ResourceDispatcherHostImpl());
+
+ loader_delegate_.reset(new LoaderDelegateImpl());
+ resource_dispatcher_host_->SetLoaderDelegate(loader_delegate_.get());
}
// MediaStreamManager needs the IO thread to be created.
@@ -1373,6 +1339,10 @@ int BrowserMainLoop::BrowserThreadsStarted() {
SystemHotkeyHelperMac::GetInstance()->DeferredLoadSystemHotkeys();
#endif // defined(OS_MACOSX)
+#if defined(OS_ANDROID)
+ media::SetMediaClientAndroid(GetContentClient()->GetMediaClientAndroid());
+#endif
+
return result_code_;
}
@@ -1383,7 +1353,6 @@ bool BrowserMainLoop::UsingInProcessGpu() const {
bool BrowserMainLoop::InitializeToolkit() {
TRACE_EVENT0("startup", "BrowserMainLoop::InitializeToolkit");
- TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::InitializeToolkit");
// TODO(evan): this function is rather subtle, due to the variety
// of intersecting ifdefs we have. To keep it easy to follow, there
@@ -1404,8 +1373,10 @@ bool BrowserMainLoop::InitializeToolkit() {
#if defined(USE_AURA)
#if defined(USE_X11)
- if (!gfx::GetXDisplay())
+ if (!gfx::GetXDisplay()) {
+ LOG(ERROR) << "Unable to open X display.";
return false;
+ }
#if !defined(OS_CHROMEOS)
// InitializeToolkit is called before CreateStartupTasks which one starts the
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index 4d3444586bc..62ba7ac9e03 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -35,10 +35,6 @@ class TraceEventSystemStatsMonitor;
} // namespace trace_event
} // namespace base
-namespace IPC {
-class ScopedIPCSupport;
-}
-
namespace media {
#if defined(OS_WIN)
class SystemMessageWindowWin;
@@ -54,6 +50,12 @@ class MidiManager;
} // namespace midi
} // namespace media
+namespace mojo {
+namespace edk {
+class ScopedIPCSupport;
+} // namespace edk
+} // namespace mojo
+
namespace net {
class NetworkChangeNotifier;
} // namespace net
@@ -68,6 +70,7 @@ namespace content {
class BrowserMainParts;
class BrowserOnlineStateObserver;
class BrowserThreadImpl;
+class LoaderDelegateImpl;
class MediaStreamManager;
class MojoShellContext;
class ResourceDispatcherHostImpl;
@@ -186,6 +189,7 @@ class CONTENT_EXPORT BrowserMainLoop {
// PreCreateThreads()
// CreateThreads()
// BrowserThreadsStarted()
+ // PreMainMessageLoopRun()
// Members initialized on construction ---------------------------------------
const MainFunctionParams& parameters_;
@@ -257,7 +261,7 @@ class CONTENT_EXPORT BrowserMainLoop {
// Members initialized in |BrowserThreadsStarted()| --------------------------
std::unique_ptr<base::Thread> indexed_db_thread_;
std::unique_ptr<MojoShellContext> mojo_shell_context_;
- std::unique_ptr<IPC::ScopedIPCSupport> mojo_ipc_support_;
+ std::unique_ptr<mojo::edk::ScopedIPCSupport> mojo_ipc_support_;
// |user_input_monitor_| has to outlive |audio_manager_|, so declared first.
std::unique_ptr<media::UserInputMonitor> user_input_monitor_;
@@ -278,6 +282,7 @@ class CONTENT_EXPORT BrowserMainLoop {
std::unique_ptr<ui::ClientNativePixmapFactory> client_native_pixmap_factory_;
#endif
+ std::unique_ptr<LoaderDelegateImpl> loader_delegate_;
std::unique_ptr<ResourceDispatcherHostImpl> resource_dispatcher_host_;
std::unique_ptr<MediaStreamManager> media_stream_manager_;
std::unique_ptr<SpeechRecognitionManagerImpl> speech_recognition_manager_;
diff --git a/chromium/content/browser/browser_main_runner.cc b/chromium/content/browser/browser_main_runner.cc
index 96a3454f149..1a8bfd3eedb 100644
--- a/chromium/content/browser/browser_main_runner.cc
+++ b/chromium/content/browser/browser_main_runner.cc
@@ -6,6 +6,7 @@
#include "base/base_switches.h"
#include "base/command_line.h"
+#include "base/debug/debugger.h"
#include "base/debug/leak_annotations.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -19,8 +20,8 @@
#include "base/trace_event/trace_event.h"
#include "base/tracked_objects.h"
#include "build/build_config.h"
-#include "components/tracing/trace_config_file.h"
-#include "components/tracing/tracing_switches.h"
+#include "components/tracing/browser/trace_config_file.h"
+#include "components/tracing/common/tracing_switches.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/browser_shutdown_profile_dumper.h"
#include "content/browser/notification_service_impl.h"
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index 71e28571717..2f6fd0e317b 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -42,6 +42,7 @@
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/guest_host.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents_observer.h"
@@ -102,6 +103,7 @@ BrowserPluginGuest::BrowserPluginGuest(bool has_render_view,
last_drag_status_(blink::WebDragStatusUnknown),
seen_embedder_system_drag_ended_(false),
seen_embedder_drag_source_ended_at_(false),
+ ignore_dragged_url_(true),
delegate_(delegate),
weak_ptr_factory_(this) {
DCHECK(web_contents);
@@ -440,8 +442,8 @@ void BrowserPluginGuest::ResendEventToEmbedder(
return;
DCHECK(browser_plugin_instance_id_);
- RenderWidgetHostImpl* host =
- embedder_web_contents()->GetMainFrame()->GetRenderWidgetHost();
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ embedder_web_contents()->GetMainFrame()->GetView());
gfx::Vector2d offset_from_embedder = guest_window_rect_.OffsetFromOrigin();
if (event.type == blink::WebInputEvent::GestureScrollUpdate) {
@@ -452,14 +454,17 @@ 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_;
- host->ForwardGestureEvent(resent_gesture_event);
+ view->ProcessGestureEvent(resent_gesture_event, ui::LatencyInfo());
} else if (event.type == blink::WebInputEvent::MouseWheel) {
blink::WebMouseWheelEvent resent_wheel_event;
memcpy(&resent_wheel_event, &event, sizeof(blink::WebMouseWheelEvent));
resent_wheel_event.x += offset_from_embedder.x();
resent_wheel_event.y += offset_from_embedder.y();
resent_wheel_event.resendingPluginId = browser_plugin_instance_id_;
- host->ForwardWheelEvent(resent_wheel_event);
+ // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
+ // https://crbug.com/613628
+ ui::LatencyInfo latency_info;
+ view->ProcessMouseWheelEvent(resent_wheel_event, latency_info);
} else {
NOTIMPLEMENTED();
}
@@ -530,7 +535,7 @@ void BrowserPluginGuest::EndSystemDragIfApplicable() {
last_drag_status_ = blink::WebDragStatusUnknown;
seen_embedder_system_drag_ended_ = false;
seen_embedder_drag_source_ended_at_ = false;
- dragged_url_ = GURL();
+ ignore_dragged_url_ = true;
}
}
@@ -799,14 +804,16 @@ void BrowserPluginGuest::OnDragStatusUpdate(int browser_plugin_instance_id,
const gfx::Point& location) {
RenderViewHost* host = GetWebContents()->GetRenderViewHost();
auto embedder = owner_web_contents_->GetBrowserPluginEmbedder();
+ DropData filtered_data(drop_data);
+ host->FilterDropData(&filtered_data);
switch (drag_status) {
case blink::WebDragStatusEnter:
+ host->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))
- dragged_url_ = drop_data.url;
- host->DragTargetDragEnter(drop_data, location, location, mask,
- drop_data.key_modifiers);
+ ignore_dragged_url_ = false;
break;
case blink::WebDragStatusOver:
host->DragTargetDragOver(location, location, mask,
@@ -815,15 +822,18 @@ void BrowserPluginGuest::OnDragStatusUpdate(int browser_plugin_instance_id,
case blink::WebDragStatusLeave:
embedder->DragLeftGuest(this);
host->DragTargetDragLeave();
+ ignore_dragged_url_ = true;
break;
case blink::WebDragStatusDrop:
- host->DragTargetDrop(location, location, drop_data.key_modifiers);
- if (dragged_url_.is_valid()) {
- delegate_->DidDropLink(dragged_url_);
- dragged_url_ = GURL();
- }
+ host->DragTargetDrop(filtered_data, location, location,
+ drop_data.key_modifiers);
+
+ if (!ignore_dragged_url_ && filtered_data.url.is_valid())
+ delegate_->DidDropLink(filtered_data.url);
+ ignore_dragged_url_ = true;
break;
case blink::WebDragStatusUnknown:
+ ignore_dragged_url_ = true;
NOTREACHED();
}
last_drag_status_ = drag_status;
@@ -975,7 +985,8 @@ void BrowserPluginGuest::OnShowPopup(
void BrowserPluginGuest::OnShowWidget(int route_id,
const gfx::Rect& initial_rect) {
- GetWebContents()->ShowCreatedWidget(route_id, initial_rect);
+ int process_id = GetWebContents()->GetRenderProcessHost()->GetID();
+ GetWebContents()->ShowCreatedWidget(process_id, route_id, initial_rect);
}
void BrowserPluginGuest::OnTakeFocus(bool reverse) {
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index bb27e539d85..ccfb0b990d3 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -52,7 +52,7 @@ struct FrameHostMsg_ShowPopup_Params;
namespace cc {
class CompositorFrame;
-struct SurfaceId;
+class SurfaceId;
struct SurfaceSequence;
} // namespace cc
@@ -437,8 +437,8 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// Whether or not our embedder has seen a DragSourceEndedAt() call.
bool seen_embedder_drag_source_ended_at_;
- // Indicates the URL dragged into the guest if any.
- GURL dragged_url_;
+ // Ignore the URL dragged into guest that is coming from guest.
+ bool ignore_dragged_url_;
// This is a queue of messages that are destined to be sent to the embedder
// once the guest is attached to a particular embedder.
diff --git a/chromium/content/browser/browser_shutdown_profile_dumper.cc b/chromium/content/browser/browser_shutdown_profile_dumper.cc
index 4330c6141ca..5310782802b 100644
--- a/chromium/content/browser/browser_shutdown_profile_dumper.cc
+++ b/chromium/content/browser/browser_shutdown_profile_dumper.cc
@@ -15,7 +15,7 @@
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_impl.h"
-#include "components/tracing/tracing_switches.h"
+#include "components/tracing/common/tracing_switches.h"
namespace content {
@@ -57,7 +57,9 @@ void BrowserShutdownProfileDumper::WriteTracesToDisc() {
// TraceLog::Flush() requires the calling thread to have a message loop.
// As the message loop of the current thread may have quit, start another
// thread for flushing the trace.
- base::WaitableEvent flush_complete_event(false, false);
+ base::WaitableEvent flush_complete_event(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
base::Thread flush_thread("browser_shutdown_trace_event_flush");
flush_thread.Start();
flush_thread.task_runner()->PostTask(
diff --git a/chromium/content/browser/browser_side_navigation_browsertest.cc b/chromium/content/browser/browser_side_navigation_browsertest.cc
index 96a2cb91a02..b6d27f09f82 100644
--- a/chromium/content/browser/browser_side_navigation_browsertest.cc
+++ b/chromium/content/browser/browser_side_navigation_browsertest.cc
@@ -11,6 +11,7 @@
#include "content/common/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -105,8 +106,8 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
GURL url(embedded_test_server()->GetURL("/title2.html"));
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(clickSameSiteLink());", &success));
+ shell(), "window.domAutomationController.send(clickSameSiteLink());",
+ &success));
EXPECT_TRUE(success);
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(url, observer.last_navigation_url());
@@ -144,13 +145,11 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- base::StringPrintf(kReplacePortNumber, port_number),
+ shell(), base::StringPrintf(kReplacePortNumber, port_number),
&success));
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(clickCrossSiteLink());",
+ shell(), "window.domAutomationController.send(clickCrossSiteLink());",
&success));
EXPECT_TRUE(success);
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
@@ -228,4 +227,48 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, POSTNavigation) {
->GetHasPostData());
}
+// Ensure that browser side navigation can load browser initiated navigations
+// to view-source URLs.
+IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+ ViewSourceNavigation_BrowserInitiated) {
+ TestNavigationObserver observer(shell()->web_contents());
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+ GURL view_source_url(content::kViewSourceScheme + std::string(":") +
+ url.spec());
+ NavigateToURL(shell(), view_source_url);
+ EXPECT_EQ(url, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+}
+
+// Ensure that browser side navigation blocks content initiated navigations to
+// view-source URLs.
+IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+ ViewSourceNavigation_RendererInitiated) {
+ TestNavigationObserver observer(shell()->web_contents());
+ GURL kUrl(embedded_test_server()->GetURL("/simple_links.html"));
+ NavigateToURL(shell(), kUrl);
+ EXPECT_EQ(kUrl, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+
+ std::unique_ptr<ConsoleObserverDelegate> console_delegate(
+ new ConsoleObserverDelegate(
+ shell()->web_contents(),
+ "Not allowed to load local resource: view-source:about:blank"));
+ shell()->web_contents()->SetDelegate(console_delegate.get());
+
+ bool success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "window.domAutomationController.send(clickViewSourceLink());", &success));
+ EXPECT_TRUE(success);
+ console_delegate->Wait();
+ // Original page shouldn't navigate away.
+ EXPECT_EQ(kUrl, shell()->web_contents()->GetURL());
+ EXPECT_FALSE(shell()
+ ->web_contents()
+ ->GetController()
+ .GetLastCommittedEntry()
+ ->IsViewSourceMode());
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_thread_impl.cc b/chromium/content/browser/browser_thread_impl.cc
index 90b581882fb..669a29387f4 100644
--- a/chromium/content/browser/browser_thread_impl.cc
+++ b/chromium/content/browser/browser_thread_impl.cc
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/profiler/scoped_tracker.h"
#include "base/single_thread_task_runner.h"
+#include "base/threading/platform_thread.h"
#include "base/threading/sequenced_worker_pool.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread_delegate.h"
@@ -40,6 +41,14 @@ static const char* const g_browser_thread_names[BrowserThread::ID_COUNT] = {
"Chrome_IOThread", // IO
};
+static const char* GetThreadName(BrowserThread::ID thread) {
+ if (BrowserThread::UI < thread && thread < BrowserThread::ID_COUNT)
+ return g_browser_thread_names[thread];
+ if (thread == BrowserThread::UI)
+ return "Chrome_UIThread";
+ return "Unknown Thread";
+}
+
// An implementation of SingleThreadTaskRunner to be used in conjunction
// with BrowserThread.
class BrowserThreadTaskRunner : public base::SingleThreadTaskRunner {
@@ -120,14 +129,13 @@ base::LazyInstance<BrowserThreadGlobals>::Leaky
} // namespace
BrowserThreadImpl::BrowserThreadImpl(ID identifier)
- : Thread(g_browser_thread_names[identifier]),
- identifier_(identifier) {
+ : Thread(GetThreadName(identifier)), identifier_(identifier) {
Initialize();
}
BrowserThreadImpl::BrowserThreadImpl(ID identifier,
base::MessageLoop* message_loop)
- : Thread(message_loop->thread_name()), identifier_(identifier) {
+ : Thread(GetThreadName(identifier)), identifier_(identifier) {
set_message_loop(message_loop);
Initialize();
}
@@ -417,24 +425,12 @@ bool BrowserThread::CurrentlyOn(ID identifier) {
base::MessageLoop::current();
}
-static const char* GetThreadName(BrowserThread::ID thread) {
- if (BrowserThread::UI < thread && thread < BrowserThread::ID_COUNT)
- return g_browser_thread_names[thread];
- if (thread == BrowserThread::UI)
- return "Chrome_UIThread";
- return "Unknown Thread";
-}
-
// static
std::string BrowserThread::GetDCheckCurrentlyOnErrorMessage(ID expected) {
- const base::MessageLoop* message_loop = base::MessageLoop::current();
- ID actual_browser_thread;
- const char* actual_name = "Unknown Thread";
- if (message_loop && !message_loop->thread_name().empty()) {
- actual_name = message_loop->thread_name().c_str();
- } else if (GetCurrentThreadIdentifier(&actual_browser_thread)) {
- actual_name = GetThreadName(actual_browser_thread);
- }
+ std::string actual_name = base::PlatformThread::GetName();
+ if (actual_name.empty())
+ actual_name = "Unknown Thread";
+
std::string result = "Must be called on ";
result += GetThreadName(expected);
result += "; actually called on ";
diff --git a/chromium/content/browser/cache_storage/cache_storage.cc b/chromium/content/browser/cache_storage/cache_storage.cc
index c1e9820e0ee..3bf66235ea8 100644
--- a/chromium/content/browser/cache_storage/cache_storage.cc
+++ b/chromium/content/browser/cache_storage/cache_storage.cc
@@ -27,6 +27,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/cache_storage/cache_storage.pb.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/directory_lister.h"
@@ -39,8 +40,6 @@ namespace content {
namespace {
-const int kCachePreservationInSecs = 30;
-
std::string HexedHash(const std::string& value) {
std::string value_hash = base::SHA1HashString(value);
std::string valued_hexed_hash = base::ToLowerASCII(
@@ -48,10 +47,11 @@ std::string HexedHash(const std::string& value) {
return valued_hexed_hash;
}
-void SizeRetrievedFromCache(const scoped_refptr<CacheStorageCache>& cache,
- const base::Closure& closure,
- int64_t* accumulator,
- int64_t size) {
+void SizeRetrievedFromCache(
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ const base::Closure& closure,
+ int64_t* accumulator,
+ int64_t size) {
*accumulator += size;
closure.Run();
}
@@ -78,7 +78,8 @@ struct CacheStorage::CacheMatchResponse {
// Handles the loading and clean up of CacheStorageCache objects.
class CacheStorage::CacheLoader {
public:
- typedef base::Callback<void(scoped_refptr<CacheStorageCache>)> CacheCallback;
+ typedef base::Callback<void(std::unique_ptr<CacheStorageCache>)>
+ CacheCallback;
typedef base::Callback<void(bool)> BoolCallback;
typedef base::Callback<void(std::unique_ptr<std::vector<std::string>>)>
StringVectorCallback;
@@ -88,11 +89,13 @@ class CacheStorage::CacheLoader {
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
storage::QuotaManagerProxy* quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
+ CacheStorage* cache_storage,
const GURL& origin)
: cache_task_runner_(cache_task_runner),
request_context_getter_(request_context_getter),
quota_manager_proxy_(quota_manager_proxy),
blob_context_(blob_context),
+ cache_storage_(cache_storage),
origin_(origin) {
DCHECK(!origin_.is_empty());
}
@@ -101,7 +104,7 @@ class CacheStorage::CacheLoader {
// Creates a CacheStorageCache with the given name. It does not attempt to
// load the backend, that happens lazily when the cache is used.
- virtual scoped_refptr<CacheStorageCache> CreateCache(
+ virtual std::unique_ptr<CacheStorageCache> CreateCache(
const std::string& cache_name) = 0;
// Deletes any pre-existing cache of the same name and then loads it.
@@ -129,6 +132,10 @@ class CacheStorage::CacheLoader {
storage::QuotaManagerProxy* quota_manager_proxy_;
base::WeakPtr<storage::BlobStorageContext> blob_context_;
+
+ // Raw pointer is safe because this object is owned by cache_storage_.
+ CacheStorage* cache_storage_;
+
GURL origin_;
};
@@ -142,32 +149,33 @@ class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
scoped_refptr<net::URLRequestContextGetter> request_context,
storage::QuotaManagerProxy* quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
+ CacheStorage* cache_storage,
const GURL& origin)
: CacheLoader(cache_task_runner,
request_context,
quota_manager_proxy,
blob_context,
+ cache_storage,
origin) {}
- scoped_refptr<CacheStorageCache> CreateCache(
+ std::unique_ptr<CacheStorageCache> CreateCache(
const std::string& cache_name) override {
return CacheStorageCache::CreateMemoryCache(
- origin_, cache_name, request_context_getter_, quota_manager_proxy_,
- blob_context_);
+ origin_, cache_name, cache_storage_, request_context_getter_,
+ quota_manager_proxy_, blob_context_);
}
void PrepareNewCacheDestination(const std::string& cache_name,
const CacheCallback& callback) override {
- scoped_refptr<CacheStorageCache> cache = CreateCache(cache_name);
- cache_refs_.insert(std::make_pair(cache_name, cache));
+ std::unique_ptr<CacheStorageCache> cache = CreateCache(cache_name);
callback.Run(std::move(cache));
}
void CleanUpDeletedCache(const std::string& cache_name,
const BoolCallback& callback) override {
- CacheRefMap::iterator it = cache_refs_.find(cache_name);
- DCHECK(it != cache_refs_.end());
- cache_refs_.erase(it);
+ CacheHandles::iterator it = cache_handles_.find(cache_name);
+ DCHECK(it != cache_handles_.end());
+ cache_handles_.erase(it);
callback.Run(true);
}
@@ -181,14 +189,21 @@ class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
callback.Run(std::move(cache_names));
}
+ void StoreCacheHandle(const std::string& cache_name,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle) {
+ DCHECK(!ContainsKey(cache_handles_, cache_name));
+ cache_handles_.insert(std::make_pair(cache_name, std::move(cache_handle)));
+ }
+
private:
- typedef std::map<std::string, scoped_refptr<CacheStorageCache>> CacheRefMap;
+ typedef std::map<std::string, std::unique_ptr<CacheStorageCacheHandle>>
+ CacheHandles;
~MemoryLoader() override {}
// Keep a reference to each cache to ensure that it's not freed before the
// client calls CacheStorage::Delete or the CacheStorage is
// freed.
- CacheRefMap cache_refs_;
+ CacheHandles cache_handles_;
};
class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
@@ -198,16 +213,18 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
scoped_refptr<net::URLRequestContextGetter> request_context,
storage::QuotaManagerProxy* quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
+ CacheStorage* cache_storage,
const GURL& origin)
: CacheLoader(cache_task_runner,
request_context,
quota_manager_proxy,
blob_context,
+ cache_storage,
origin),
origin_path_(origin_path),
weak_ptr_factory_(this) {}
- scoped_refptr<CacheStorageCache> CreateCache(
+ std::unique_ptr<CacheStorageCache> CreateCache(
const std::string& cache_name) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(ContainsKey(cache_name_to_cache_dir_, cache_name));
@@ -215,8 +232,8 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
std::string cache_dir = cache_name_to_cache_dir_[cache_name];
base::FilePath cache_path = origin_path_.AppendASCII(cache_dir);
return CacheStorageCache::CreatePersistentCache(
- origin_, cache_name, cache_path, request_context_getter_,
- quota_manager_proxy_, blob_context_);
+ origin_, cache_name, cache_storage_, cache_path,
+ request_context_getter_, quota_manager_proxy_, blob_context_);
}
void PrepareNewCacheDestination(const std::string& cache_name,
@@ -248,7 +265,7 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
const CacheCallback& callback,
const std::string& cache_dir) {
if (cache_dir.empty()) {
- callback.Run(scoped_refptr<CacheStorageCache>());
+ callback.Run(std::unique_ptr<CacheStorageCache>());
return;
}
@@ -467,6 +484,7 @@ CacheStorage::CacheStorage(
const GURL& origin)
: initialized_(false),
initializing_(false),
+ memory_only_(memory_only),
scheduler_(new CacheStorageScheduler()),
origin_path_(path),
cache_task_runner_(cache_task_runner),
@@ -474,13 +492,13 @@ CacheStorage::CacheStorage(
origin_(origin),
weak_factory_(this) {
if (memory_only)
- cache_loader_.reset(
- new MemoryLoader(cache_task_runner_.get(), std::move(request_context),
- quota_manager_proxy.get(), blob_context, origin));
+ cache_loader_.reset(new MemoryLoader(
+ cache_task_runner_.get(), std::move(request_context),
+ quota_manager_proxy.get(), blob_context, this, origin));
else
cache_loader_.reset(new SimpleCacheLoader(
origin_path_, cache_task_runner_.get(), std::move(request_context),
- quota_manager_proxy.get(), blob_context, origin));
+ quota_manager_proxy.get(), blob_context, this, origin));
}
CacheStorage::~CacheStorage() {
@@ -676,7 +694,7 @@ void CacheStorage::LazyInitDidLoadIndex(
for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) {
cache_map_.insert(std::make_pair(indexed_cache_names->at(i),
- base::WeakPtr<CacheStorageCache>()));
+ std::unique_ptr<CacheStorageCache>()));
ordered_cache_names_.push_back(indexed_cache_names->at(i));
}
@@ -688,9 +706,10 @@ void CacheStorage::LazyInitDidLoadIndex(
void CacheStorage::OpenCacheImpl(const std::string& cache_name,
const CacheAndErrorCallback& callback) {
- scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
- if (cache.get()) {
- callback.Run(std::move(cache), CACHE_STORAGE_OK);
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ GetLoadedCache(cache_name);
+ if (cache_handle) {
+ callback.Run(std::move(cache_handle), CACHE_STORAGE_OK);
return;
}
@@ -702,39 +721,45 @@ void CacheStorage::OpenCacheImpl(const std::string& cache_name,
void CacheStorage::CreateCacheDidCreateCache(
const std::string& cache_name,
const CacheAndErrorCallback& callback,
- scoped_refptr<CacheStorageCache> cache) {
+ std::unique_ptr<CacheStorageCache> cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
static_cast<bool>(cache));
- if (!cache.get()) {
- callback.Run(scoped_refptr<CacheStorageCache>(),
+ if (!cache) {
+ callback.Run(std::unique_ptr<CacheStorageCacheHandle>(),
CACHE_STORAGE_ERROR_STORAGE);
return;
}
- cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr()));
+ CacheStorageCache* cache_ptr = cache.get();
+
+ cache_map_.insert(std::make_pair(cache_name, std::move(cache)));
ordered_cache_names_.push_back(cache_name);
- TemporarilyPreserveCache(cache);
+ if (memory_only_) {
+ static_cast<MemoryLoader*>(cache_loader_.get())
+ ->StoreCacheHandle(cache_name, CreateCacheHandle(cache_ptr));
+ }
cache_loader_->WriteIndex(
ordered_cache_names_,
base::Bind(&CacheStorage::CreateCacheDidWriteIndex,
- weak_factory_.GetWeakPtr(), callback, std::move(cache)));
+ weak_factory_.GetWeakPtr(), callback,
+ base::Passed(CreateCacheHandle(cache_ptr))));
}
void CacheStorage::CreateCacheDidWriteIndex(
const CacheAndErrorCallback& callback,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(cache.get());
+ DCHECK(cache_handle);
// TODO(jkarlin): Handle !success.
- callback.Run(std::move(cache), CACHE_STORAGE_OK);
+ callback.Run(std::move(cache_handle), CACHE_STORAGE_OK);
}
void CacheStorage::HasCacheImpl(const std::string& cache_name,
@@ -745,14 +770,17 @@ void CacheStorage::HasCacheImpl(const std::string& cache_name,
void CacheStorage::DeleteCacheImpl(const std::string& cache_name,
const BoolAndErrorCallback& callback) {
- scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
- if (!cache.get()) {
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ GetLoadedCache(cache_name);
+ if (!cache_handle) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(callback, false, CACHE_STORAGE_ERROR_NOT_FOUND));
return;
}
CacheMap::iterator map_iter = cache_map_.find(cache_name);
+ deleted_caches_.insert(
+ std::make_pair(cache_handle->value(), std::move(map_iter->second)));
cache_map_.erase(map_iter);
// Delete the name from ordered_cache_names_.
@@ -761,16 +789,19 @@ void CacheStorage::DeleteCacheImpl(const std::string& cache_name,
DCHECK(iter != ordered_cache_names_.end());
ordered_cache_names_.erase(iter);
- cache->GetSizeThenClose(base::Bind(&CacheStorage::DeleteCacheDidClose,
- weak_factory_.GetWeakPtr(), cache_name,
- callback, ordered_cache_names_, cache));
+ CacheStorageCache* cache_ptr = cache_handle->value();
+ cache_ptr->GetSizeThenClose(
+ base::Bind(&CacheStorage::DeleteCacheDidClose, weak_factory_.GetWeakPtr(),
+ cache_name, callback, ordered_cache_names_,
+ base::Passed(std::move(cache_handle))));
}
-void CacheStorage::DeleteCacheDidClose(const std::string& cache_name,
- const BoolAndErrorCallback& callback,
- const StringVector& ordered_cache_names,
- scoped_refptr<CacheStorageCache> cache,
- int64_t cache_size) {
+void CacheStorage::DeleteCacheDidClose(
+ const std::string& cache_name,
+ const BoolAndErrorCallback& callback,
+ const StringVector& ordered_cache_names,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ int64_t cache_size) {
cache_loader_->WriteIndex(
ordered_cache_names,
base::Bind(&CacheStorage::DeleteCacheDidWriteIndex,
@@ -809,24 +840,27 @@ void CacheStorage::MatchCacheImpl(
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
const CacheStorageCache::ResponseCallback& callback) {
- scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ GetLoadedCache(cache_name);
- if (!cache.get()) {
+ if (!cache_handle) {
callback.Run(CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND,
std::unique_ptr<ServiceWorkerResponse>(),
std::unique_ptr<storage::BlobDataHandle>());
return;
}
- // Pass the cache along to the callback to keep the cache open until match is
- // done.
- cache->Match(std::move(request),
- base::Bind(&CacheStorage::MatchCacheDidMatch,
- weak_factory_.GetWeakPtr(), cache, callback));
+ // Pass the cache handle along to the callback to keep the cache open until
+ // match is done.
+ CacheStorageCache* cache_ptr = cache_handle->value();
+ cache_ptr->Match(
+ std::move(request),
+ base::Bind(&CacheStorage::MatchCacheDidMatch, weak_factory_.GetWeakPtr(),
+ base::Passed(std::move(cache_handle)), callback));
}
void CacheStorage::MatchCacheDidMatch(
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
const CacheStorageCache::ResponseCallback& callback,
CacheStorageError error,
std::unique_ptr<ServiceWorkerResponse> response,
@@ -847,19 +881,21 @@ void CacheStorage::MatchAllCachesImpl(
base::Passed(base::WrapUnique(match_responses)), callback));
for (size_t i = 0, max = ordered_cache_names_.size(); i < max; ++i) {
- scoped_refptr<CacheStorageCache> cache =
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
GetLoadedCache(ordered_cache_names_[i]);
- DCHECK(cache.get());
-
- cache->Match(base::WrapUnique(new ServiceWorkerFetchRequest(*request)),
- base::Bind(&CacheStorage::MatchAllCachesDidMatch,
- weak_factory_.GetWeakPtr(), cache,
- &match_responses->at(i), barrier_closure));
+ DCHECK(cache_handle);
+
+ CacheStorageCache* cache_ptr = cache_handle->value();
+ cache_ptr->Match(base::WrapUnique(new ServiceWorkerFetchRequest(*request)),
+ base::Bind(&CacheStorage::MatchAllCachesDidMatch,
+ weak_factory_.GetWeakPtr(),
+ base::Passed(std::move(cache_handle)),
+ &match_responses->at(i), barrier_closure));
}
}
void CacheStorage::MatchAllCachesDidMatch(
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheMatchResponse* out_match_response,
const base::Closure& barrier_closure,
CacheStorageError error,
@@ -888,54 +924,70 @@ void CacheStorage::MatchAllCachesDidMatchAll(
std::unique_ptr<storage::BlobDataHandle>());
}
-scoped_refptr<CacheStorageCache> CacheStorage::GetLoadedCache(
- const std::string& cache_name) {
+void CacheStorage::AddCacheHandleRef(CacheStorageCache* cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(initialized_);
-
- CacheMap::iterator map_iter = cache_map_.find(cache_name);
- if (map_iter == cache_map_.end())
- return scoped_refptr<CacheStorageCache>();
+ auto iter = cache_handle_counts_.find(cache);
+ if (iter == cache_handle_counts_.end()) {
+ cache_handle_counts_[cache] = 1;
+ return;
+ }
- base::WeakPtr<CacheStorageCache> cache = map_iter->second;
+ iter->second += 1;
+}
- if (!cache) {
- scoped_refptr<CacheStorageCache> new_cache =
- cache_loader_->CreateCache(cache_name);
- map_iter->second = new_cache->AsWeakPtr();
+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);
+
+ iter->second -= 1;
+ if (iter->second == 0) {
+ // Delete the CacheStorageCache object. It's either in the main cache map or
+ // the CacheStorage::Delete operation has run on the cache, in which case
+ // it's in the deleted caches map.
+ auto cache_map_iter = cache_map_.find(cache->cache_name());
+
+ if (cache_map_iter == cache_map_.end()) {
+ auto deleted_caches_iter = deleted_caches_.find(cache);
+ DCHECK(deleted_caches_iter != deleted_caches_.end());
+ deleted_caches_.erase(deleted_caches_iter);
+ return;
+ }
- TemporarilyPreserveCache(new_cache);
- return new_cache;
+ cache_map_iter->second.reset();
+ cache_handle_counts_.erase(iter);
}
+}
- return make_scoped_refptr(cache.get());
+std::unique_ptr<CacheStorageCacheHandle> CacheStorage::CreateCacheHandle(
+ CacheStorageCache* cache) {
+ DCHECK(cache);
+ return std::unique_ptr<CacheStorageCacheHandle>(new CacheStorageCacheHandle(
+ cache->AsWeakPtr(), weak_factory_.GetWeakPtr()));
}
-void CacheStorage::TemporarilyPreserveCache(
- scoped_refptr<CacheStorageCache> cache) {
+std::unique_ptr<CacheStorageCacheHandle> CacheStorage::GetLoadedCache(
+ const std::string& cache_name) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!ContainsKey(preserved_caches_, cache.get()));
+ DCHECK(initialized_);
- preserved_caches_[cache.get()] = cache;
- SchedulePreservedCacheRemoval(base::Bind(&CacheStorage::RemovePreservedCache,
- weak_factory_.GetWeakPtr(),
- base::Unretained(cache.get())));
-}
+ CacheMap::iterator map_iter = cache_map_.find(cache_name);
+ if (map_iter == cache_map_.end())
+ return std::unique_ptr<CacheStorageCacheHandle>();
-void CacheStorage::SchedulePreservedCacheRemoval(
- const base::Closure& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ CacheStorageCache* cache = map_iter->second.get();
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, callback,
- base::TimeDelta::FromSeconds(kCachePreservationInSecs));
-}
+ if (!cache) {
+ std::unique_ptr<CacheStorageCache> new_cache =
+ cache_loader_->CreateCache(cache_name);
+ CacheStorageCache* cache_ptr = new_cache.get();
+ map_iter->second = std::move(new_cache);
-void CacheStorage::RemovePreservedCache(const CacheStorageCache* cache) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(ContainsKey(preserved_caches_, cache));
+ return CreateCacheHandle(cache_ptr);
+ }
- preserved_caches_.erase(cache);
+ return CreateCacheHandle(cache);
}
void CacheStorage::GetSizeThenCloseAllCachesImpl(const SizeCallback& callback) {
@@ -951,8 +1003,11 @@ void CacheStorage::GetSizeThenCloseAllCachesImpl(const SizeCallback& callback) {
base::Passed(std::move(accumulator)), callback));
for (const std::string& cache_name : ordered_cache_names_) {
- scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
- cache->GetSizeThenClose(base::Bind(&SizeRetrievedFromCache, cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ GetLoadedCache(cache_name);
+ CacheStorageCache* cache = cache_handle->value();
+ cache->GetSizeThenClose(base::Bind(&SizeRetrievedFromCache,
+ base::Passed(std::move(cache_handle)),
barrier_closure, accumulator_ptr));
}
}
@@ -970,9 +1025,12 @@ void CacheStorage::SizeImpl(const SizeCallback& callback) {
base::Passed(std::move(accumulator)), callback));
for (const std::string& cache_name : ordered_cache_names_) {
- scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
- cache->Size(base::Bind(&SizeRetrievedFromCache, cache, barrier_closure,
- accumulator_ptr));
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ GetLoadedCache(cache_name);
+ CacheStorageCache* cache = cache_handle->value();
+ cache->Size(base::Bind(&SizeRetrievedFromCache,
+ base::Passed(std::move(cache_handle)),
+ barrier_closure, accumulator_ptr));
}
}
@@ -997,11 +1055,11 @@ void CacheStorage::PendingBoolAndErrorCallback(
void CacheStorage::PendingCacheAndErrorCallback(
const CacheAndErrorCallback& callback,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error) {
base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
- callback.Run(std::move(cache), error);
+ callback.Run(std::move(cache_handle), error);
if (cache_storage)
scheduler_->CompleteOperationAndRunNext();
}
diff --git a/chromium/content/browser/cache_storage/cache_storage.h b/chromium/content/browser/cache_storage/cache_storage.h
index 2cea28b2cd7..20376c1257e 100644
--- a/chromium/content/browser/cache_storage/cache_storage.h
+++ b/chromium/content/browser/cache_storage/cache_storage.h
@@ -31,6 +31,7 @@ class BlobStorageContext;
namespace content {
class CacheStorageScheduler;
+class CacheStorageCacheHandle;
// TODO(jkarlin): Constrain the total bytes used per origin.
@@ -41,7 +42,7 @@ class CONTENT_EXPORT CacheStorage {
public:
typedef std::vector<std::string> StringVector;
typedef base::Callback<void(bool, CacheStorageError)> BoolAndErrorCallback;
- typedef base::Callback<void(scoped_refptr<CacheStorageCache>,
+ typedef base::Callback<void(std::unique_ptr<CacheStorageCacheHandle>,
CacheStorageError)>
CacheAndErrorCallback;
typedef base::Callback<void(const StringVector&, CacheStorageError)>
@@ -64,7 +65,10 @@ class CONTENT_EXPORT CacheStorage {
virtual ~CacheStorage();
// Get the cache for the given key. If the cache is not found it is
- // created.
+ // created. The CacheStorgeCacheHandle in the callback prolongs the lifetime
+ // of the cache. Once all handles to a cache are deleted the cache is deleted.
+ // The cache will also be deleted in the CacheStorage's destructor so be sure
+ // to check the handle's value before using it.
void OpenCache(const std::string& cache_name,
const CacheAndErrorCallback& callback);
@@ -106,24 +110,25 @@ class CONTENT_EXPORT CacheStorage {
void CompleteAsyncOperationForTesting();
private:
- friend class TestCacheStorage;
+ friend class CacheStorageCacheHandle;
+ friend class CacheStorageCache;
class CacheLoader;
class MemoryLoader;
class SimpleCacheLoader;
struct CacheMatchResponse;
- typedef std::map<std::string, base::WeakPtr<CacheStorageCache>> CacheMap;
+ typedef std::map<std::string, std::unique_ptr<CacheStorageCache>> CacheMap;
- // Return a CacheStorageCache for the given name if the name is known. If the
- // CacheStorageCache has been deleted, creates a new one.
- scoped_refptr<CacheStorageCache> GetLoadedCache(
- const std::string& cache_name);
+ // Functions for exposing handles to CacheStorageCache to clients.
+ std::unique_ptr<CacheStorageCacheHandle> CreateCacheHandle(
+ CacheStorageCache* cache);
+ void AddCacheHandleRef(CacheStorageCache* cache);
+ void DropCacheHandleRef(CacheStorageCache* cache);
- // Holds a reference to a cache for thirty seconds.
- void TemporarilyPreserveCache(scoped_refptr<CacheStorageCache> cache);
- virtual void SchedulePreservedCacheRemoval(
- const base::Closure& callback); // Virtual for testing.
- void RemovePreservedCache(const CacheStorageCache* cache);
+ // Returns a CacheStorageCacheHandle for the given name if the name is known.
+ // If the CacheStorageCache has been deleted, creates a new one.
+ std::unique_ptr<CacheStorageCacheHandle> GetLoadedCache(
+ const std::string& cache_name);
// Initializer and its callback are below.
void LazyInit();
@@ -136,10 +141,11 @@ class CONTENT_EXPORT CacheStorage {
const CacheAndErrorCallback& callback);
void CreateCacheDidCreateCache(const std::string& cache_name,
const CacheAndErrorCallback& callback,
- scoped_refptr<CacheStorageCache> cache);
- void CreateCacheDidWriteIndex(const CacheAndErrorCallback& callback,
- scoped_refptr<CacheStorageCache> cache,
- bool success);
+ std::unique_ptr<CacheStorageCache> cache);
+ void CreateCacheDidWriteIndex(
+ const CacheAndErrorCallback& callback,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ bool success);
// The HasCache callbacks are below.
void HasCacheImpl(const std::string& cache_name,
@@ -149,11 +155,12 @@ class CONTENT_EXPORT CacheStorage {
void DeleteCacheImpl(const std::string& cache_name,
const BoolAndErrorCallback& callback);
- void DeleteCacheDidClose(const std::string& cache_name,
- const BoolAndErrorCallback& callback,
- const StringVector& ordered_cache_names,
- scoped_refptr<CacheStorageCache> cache,
- int64_t cache_size);
+ void DeleteCacheDidClose(
+ const std::string& cache_name,
+ const BoolAndErrorCallback& callback,
+ const StringVector& ordered_cache_names,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ int64_t cache_size);
void DeleteCacheDidWriteIndex(const std::string& cache_name,
const BoolAndErrorCallback& callback,
int cache_size,
@@ -168,7 +175,7 @@ class CONTENT_EXPORT CacheStorage {
void MatchCacheImpl(const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
const CacheStorageCache::ResponseCallback& callback);
- void MatchCacheDidMatch(scoped_refptr<CacheStorageCache> cache,
+ void MatchCacheDidMatch(std::unique_ptr<CacheStorageCacheHandle> cache_handle,
const CacheStorageCache::ResponseCallback& callback,
CacheStorageError error,
std::unique_ptr<ServiceWorkerResponse> response,
@@ -178,7 +185,7 @@ class CONTENT_EXPORT CacheStorage {
void MatchAllCachesImpl(std::unique_ptr<ServiceWorkerFetchRequest> request,
const CacheStorageCache::ResponseCallback& callback);
void MatchAllCachesDidMatch(
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheMatchResponse* out_match_response,
const base::Closure& barrier_closure,
CacheStorageError error,
@@ -196,9 +203,10 @@ class CONTENT_EXPORT CacheStorage {
void PendingBoolAndErrorCallback(const BoolAndErrorCallback& callback,
bool found,
CacheStorageError error);
- void PendingCacheAndErrorCallback(const CacheAndErrorCallback& callback,
- scoped_refptr<CacheStorageCache> cache,
- CacheStorageError error);
+ void PendingCacheAndErrorCallback(
+ const CacheAndErrorCallback& callback,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ CacheStorageError error);
void PendingStringsAndErrorCallback(const StringsAndErrorCallback& callback,
const StringVector& strings,
CacheStorageError error);
@@ -214,12 +222,23 @@ class CONTENT_EXPORT CacheStorage {
bool initialized_;
bool initializing_;
+ // True if the backend is supposed to reside in memory only.
+ bool memory_only_;
+
// The pending operation scheduler.
std::unique_ptr<CacheStorageScheduler> scheduler_;
// The map of cache names to CacheStorageCache objects.
CacheMap cache_map_;
+ // Caches that have been deleted but must still be held onto until all handles
+ // have been released.
+ std::map<CacheStorageCache*, std::unique_ptr<CacheStorageCache>>
+ deleted_caches_;
+
+ // CacheStorageCacheHandle reference counts
+ std::map<CacheStorageCache*, size_t> cache_handle_counts_;
+
// The names of caches in the order that they were created.
StringVector ordered_cache_names_;
@@ -232,11 +251,6 @@ class CONTENT_EXPORT CacheStorage {
// Performs backend specific operations (memory vs disk).
std::unique_ptr<CacheLoader> cache_loader_;
- // Holds ref pointers to recently opened caches so that they can be reused
- // without having the open the cache again.
- std::map<const CacheStorageCache*, scoped_refptr<CacheStorageCache>>
- preserved_caches_;
-
// The quota manager.
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
diff --git a/chromium/content/browser/cache_storage/cache_storage.proto b/chromium/content/browser/cache_storage/cache_storage.proto
index 07a61700cff..9850fa85684 100644
--- a/chromium/content/browser/cache_storage/cache_storage.proto
+++ b/chromium/content/browser/cache_storage/cache_storage.proto
@@ -43,6 +43,7 @@ message CacheResponse {
repeated CacheHeaderMap headers = 4;
optional string url = 5;
optional int64 response_time = 6;
+ repeated string cors_exposed_header_names = 7;
}
message CacheMetadata {
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.cc b/chromium/content/browser/cache_storage/cache_storage_cache.cc
index f94071a319e..5a9bb3dbc86 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.cc
@@ -18,6 +18,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/cache_storage/cache_storage.pb.h"
#include "content/browser/cache_storage/cache_storage_blob_to_disk_cache.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/referrer.h"
@@ -42,14 +43,15 @@ namespace {
class CacheStorageCacheDataHandle
: public storage::BlobDataBuilder::DataHandle {
public:
- CacheStorageCacheDataHandle(scoped_refptr<CacheStorageCache> cache,
- disk_cache::ScopedEntryPtr entry)
- : cache_(cache), entry_(std::move(entry)) {}
+ CacheStorageCacheDataHandle(
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ disk_cache::ScopedEntryPtr entry)
+ : cache_handle_(std::move(cache_handle)), entry_(std::move(entry)) {}
private:
~CacheStorageCacheDataHandle() override {}
- scoped_refptr<CacheStorageCache> cache_;
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle_;
disk_cache::ScopedEntryPtr entry_;
DISALLOW_COPY_AND_ASSIGN(CacheStorageCacheDataHandle);
@@ -280,32 +282,32 @@ struct CacheStorageCache::PutContext {
};
// static
-scoped_refptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache(
+std::unique_ptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache(
const GURL& origin,
const std::string& cache_name,
+ CacheStorage* cache_storage,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context) {
- return make_scoped_refptr(new CacheStorageCache(
- origin, cache_name, base::FilePath(), std::move(request_context_getter),
- std::move(quota_manager_proxy), blob_context));
+ return std::unique_ptr<CacheStorageCache>(
+ new CacheStorageCache(origin, cache_name, base::FilePath(), cache_storage,
+ std::move(request_context_getter),
+ std::move(quota_manager_proxy), blob_context));
}
// static
-scoped_refptr<CacheStorageCache> CacheStorageCache::CreatePersistentCache(
+std::unique_ptr<CacheStorageCache> CacheStorageCache::CreatePersistentCache(
const GURL& origin,
const std::string& cache_name,
+ CacheStorage* cache_storage,
const base::FilePath& path,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context) {
- return make_scoped_refptr(new CacheStorageCache(
- origin, cache_name, path, std::move(request_context_getter),
- std::move(quota_manager_proxy), blob_context));
-}
-
-CacheStorageCache::~CacheStorageCache() {
- quota_manager_proxy_->NotifyOriginNoLongerInUse(origin_);
+ return std::unique_ptr<CacheStorageCache>(
+ new CacheStorageCache(origin, cache_name, path, cache_storage,
+ std::move(request_context_getter),
+ std::move(quota_manager_proxy), blob_context));
}
base::WeakPtr<CacheStorageCache> CacheStorageCache::AsWeakPtr() {
@@ -427,12 +429,12 @@ void CacheStorageCache::BatchDidGetUsageAndQuota(
std::unique_ptr<ErrorCallback> callback_copy(new ErrorCallback(callback));
ErrorCallback* callback_ptr = callback_copy.get();
base::Closure barrier_closure = base::BarrierClosure(
- operations.size(),
- base::Bind(&CacheStorageCache::BatchDidAllOperations, this,
- base::Passed(std::move(callback_copy))));
+ operations.size(), base::Bind(&CacheStorageCache::BatchDidAllOperations,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(std::move(callback_copy))));
ErrorCallback completion_callback =
- base::Bind(&CacheStorageCache::BatchDidOneOperation, this,
- barrier_closure, callback_ptr);
+ base::Bind(&CacheStorageCache::BatchDidOneOperation,
+ weak_ptr_factory_.GetWeakPtr(), barrier_closure, callback_ptr);
for (const auto& operation : operations) {
switch (operation.operation_type) {
@@ -535,16 +537,22 @@ void CacheStorageCache::GetSizeThenClose(const SizeCallback& callback) {
weak_ptr_factory_.GetWeakPtr(), pending_callback)));
}
+CacheStorageCache::~CacheStorageCache() {
+ quota_manager_proxy_->NotifyOriginNoLongerInUse(origin_);
+}
+
CacheStorageCache::CacheStorageCache(
const GURL& origin,
const std::string& cache_name,
const base::FilePath& path,
+ CacheStorage* cache_storage,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context)
: origin_(origin),
cache_name_(cache_name),
path_(path),
+ cache_storage_(cache_storage),
request_context_getter_(std::move(request_context_getter)),
quota_manager_proxy_(std::move(quota_manager_proxy)),
blob_storage_context_(blob_context),
@@ -954,7 +962,8 @@ void CacheStorageCache::Put(const CacheStorageBatchOperation& operation,
operation.response.blob_size, operation.response.stream_url,
operation.response.error, operation.response.response_time,
false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */));
+ std::string() /* cache_storage_cache_name */,
+ operation.response.cors_exposed_header_names));
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
@@ -971,6 +980,12 @@ void CacheStorageCache::Put(const CacheStorageBatchOperation& operation,
}
}
+ UMA_HISTOGRAM_ENUMERATION(
+ "ServiceWorkerCache.Cache.AllWritesResponseType",
+ operation.response.response_type,
+ blink::WebServiceWorkerResponseType::WebServiceWorkerResponseTypeLast +
+ 1);
+
ErrorCallback pending_callback =
base::Bind(&CacheStorageCache::PendingErrorCallback,
weak_ptr_factory_.GetWeakPtr(), callback);
@@ -1066,6 +1081,8 @@ void CacheStorageCache::PutDidCreateEntry(
header_map->set_name(it->first);
header_map->set_value(it->second);
}
+ for (const auto& header : put_context->response->cors_exposed_header_names)
+ response_metadata->add_cors_exposed_header_names(header);
std::unique_ptr<std::string> serialized(new std::string());
if (!metadata.SerializeToString(serialized.get())) {
@@ -1155,16 +1172,20 @@ void CacheStorageCache::UpdateCacheSize() {
if (backend_state_ != BACKEND_OPEN)
return;
- // Note that the callback holds a refptr to |this| since UpdateCacheSize is
- // often called after an operation completes and the cache might be freed.
- int rv = backend_->CalculateSizeOfAllEntries(
- base::Bind(&CacheStorageCache::UpdateCacheSizeGotSize, this));
+ // Note that the callback holds a cache handle to keep the cache alive during
+ // the operation since this UpdateCacheSize is often run after an operation
+ // completes and runs its callback.
+ int rv = backend_->CalculateSizeOfAllEntries(base::Bind(
+ &CacheStorageCache::UpdateCacheSizeGotSize,
+ weak_ptr_factory_.GetWeakPtr(), base::Passed(CreateCacheHandle())));
if (rv != net::ERR_IO_PENDING)
- UpdateCacheSizeGotSize(rv);
+ UpdateCacheSizeGotSize(CreateCacheHandle(), rv);
}
-void CacheStorageCache::UpdateCacheSizeGotSize(int current_cache_size) {
+void CacheStorageCache::UpdateCacheSizeGotSize(
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ int current_cache_size) {
int64_t old_cache_size = cache_size_;
cache_size_ = current_cache_size;
@@ -1528,7 +1549,10 @@ void CacheStorageCache::PopulateResponseMetadata(
ServiceWorkerHeaderMap(), "", 0, GURL(),
blink::WebServiceWorkerResponseErrorUnknown,
base::Time::FromInternalValue(metadata.response().response_time()),
- true /* is_in_cache_storage */, cache_name_);
+ true /* is_in_cache_storage */, cache_name_,
+ ServiceWorkerHeaderList(
+ metadata.response().cors_exposed_header_names().begin(),
+ metadata.response().cors_exposed_header_names().end()));
for (int i = 0; i < metadata.response().headers_size(); ++i) {
const CacheHeaderMap header = metadata.response().headers(i);
@@ -1550,9 +1574,14 @@ CacheStorageCache::PopulateResponseBody(disk_cache::ScopedEntryPtr entry,
disk_cache::Entry* temp_entry = entry.get();
blob_data.AppendDiskCacheEntryWithSideData(
- new CacheStorageCacheDataHandle(this, std::move(entry)), temp_entry,
- INDEX_RESPONSE_BODY, INDEX_SIDE_DATA);
+ new CacheStorageCacheDataHandle(CreateCacheHandle(), std::move(entry)),
+ temp_entry, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA);
return blob_storage_context_->AddFinishedBlob(&blob_data);
}
+std::unique_ptr<CacheStorageCacheHandle>
+CacheStorageCache::CreateCacheHandle() {
+ return cache_storage_->CreateCacheHandle(this);
+}
+
} // namespace content
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.h b/chromium/content/browser/cache_storage/cache_storage_cache.h
index 4b3a72e3207..787e13ad24a 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.h
@@ -13,7 +13,6 @@
#include "base/files/file_path.h"
#include "base/id_map.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "content/common/cache_storage/cache_storage_types.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -33,8 +32,9 @@ class QuotaManagerProxy;
}
namespace content {
-
+class CacheStorage;
class CacheStorageBlobToDiskCache;
+class CacheStorageCacheHandle;
class CacheMetadata;
class CacheStorageScheduler;
class TestCacheStorageCache;
@@ -43,8 +43,7 @@ class TestCacheStorageCache;
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ The
// asynchronous methods are executed serially. Callbacks to the public functions
// will be called so long as the cache object lives.
-class CONTENT_EXPORT CacheStorageCache
- : public base::RefCounted<CacheStorageCache> {
+class CONTENT_EXPORT CacheStorageCache {
public:
using ErrorCallback = base::Callback<void(CacheStorageError)>;
using ResponseCallback =
@@ -64,15 +63,17 @@ class CONTENT_EXPORT CacheStorageCache
enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA };
- static scoped_refptr<CacheStorageCache> CreateMemoryCache(
+ static std::unique_ptr<CacheStorageCache> CreateMemoryCache(
const GURL& origin,
const std::string& cache_name,
+ CacheStorage* cache_storage,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context);
- static scoped_refptr<CacheStorageCache> CreatePersistentCache(
+ static std::unique_ptr<CacheStorageCache> CreatePersistentCache(
const GURL& origin,
const std::string& cache_name,
+ CacheStorage* cache_storage,
const base::FilePath& path,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
@@ -142,8 +143,13 @@ class CONTENT_EXPORT CacheStorageCache
// the cache's size.
void GetSizeThenClose(const SizeCallback& callback);
+ // Async operations in progress will cancel and not run their callbacks.
+ virtual ~CacheStorageCache();
+
base::FilePath path() const { return path_; }
+ std::string cache_name() const { return cache_name_; }
+
base::WeakPtr<CacheStorageCache> AsWeakPtr();
private:
@@ -175,13 +181,11 @@ class CONTENT_EXPORT CacheStorageCache
const GURL& origin,
const std::string& cache_name,
const base::FilePath& path,
+ CacheStorage* cache_storage,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context);
- // Async operations in progress will cancel and not run their callbacks.
- virtual ~CacheStorageCache();
-
// Returns true if the backend is ready to operate.
bool LazyInitialize();
@@ -280,9 +284,10 @@ class CONTENT_EXPORT CacheStorageCache
// Asynchronously calculates the current cache size, notifies the quota
// manager of any change from the last report, and sets cache_size_ to the new
- // size. Runs |callback| once complete.
+ // size.
void UpdateCacheSize();
- void UpdateCacheSizeGotSize(int current_cache_size);
+ void UpdateCacheSizeGotSize(std::unique_ptr<CacheStorageCacheHandle>,
+ int current_cache_size);
// Returns ERROR_NOT_FOUND if not found. Otherwise deletes and returns OK.
void Delete(const CacheStorageBatchOperation& operation,
@@ -355,12 +360,19 @@ class CONTENT_EXPORT CacheStorageCache
disk_cache::ScopedEntryPtr entry,
ServiceWorkerResponse* response);
+ // Virtual for testing.
+ virtual std::unique_ptr<CacheStorageCacheHandle> CreateCacheHandle();
+
// Be sure to check |backend_state_| before use.
std::unique_ptr<disk_cache::Backend> backend_;
GURL origin_;
const std::string cache_name_;
base::FilePath path_;
+
+ // Raw pointer is safe because CacheStorage owns this object.
+ CacheStorage* cache_storage_;
+
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache_handle.cc b/chromium/content/browser/cache_storage/cache_storage_cache_handle.cc
new file mode 100644
index 00000000000..13cdebd541e
--- /dev/null
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_handle.cc
@@ -0,0 +1,28 @@
+// 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/cache_storage/cache_storage_cache_handle.h"
+
+namespace content {
+
+CacheStorageCacheHandle::~CacheStorageCacheHandle() {
+ if (cache_storage_ && cache_storage_cache_)
+ cache_storage_->DropCacheHandleRef(cache_storage_cache_.get());
+}
+
+std::unique_ptr<CacheStorageCacheHandle> CacheStorageCacheHandle::Clone() {
+ return std::unique_ptr<CacheStorageCacheHandle>(
+ new CacheStorageCacheHandle(cache_storage_cache_, cache_storage_));
+}
+
+CacheStorageCacheHandle::CacheStorageCacheHandle(
+ base::WeakPtr<CacheStorageCache> cache_storage_cache,
+ base::WeakPtr<CacheStorage> cache_storage)
+ : cache_storage_cache_(cache_storage_cache), cache_storage_(cache_storage) {
+ DCHECK(cache_storage);
+ DCHECK(cache_storage_cache_);
+ cache_storage_->AddCacheHandleRef(cache_storage_cache_.get());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache_handle.h b/chromium/content/browser/cache_storage/cache_storage_cache_handle.h
new file mode 100644
index 00000000000..9a043bbd0e8
--- /dev/null
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_handle.h
@@ -0,0 +1,41 @@
+// 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_CACHE_STORAGE_CACHE_STORAGE_CACHE_HANDLE_H_
+#define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_CACHE_HANDLE_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/browser/cache_storage/cache_storage.h"
+#include "content/browser/cache_storage/cache_storage_cache.h"
+
+namespace content {
+
+// Holds a reference to a CacheStorageCache. The CacheStorage will keep the
+// CacheStorageCache alive until the last handle is destroyed or the
+// CacheStorage is deleted.
+class CONTENT_EXPORT CacheStorageCacheHandle {
+ public:
+ ~CacheStorageCacheHandle();
+
+ // Returns the underlying CacheStorageCache*. Will return nullptr if the
+ // CacheStorage has been deleted.
+ CacheStorageCache* value() { return cache_storage_cache_.get(); }
+
+ std::unique_ptr<CacheStorageCacheHandle> Clone();
+
+ private:
+ friend class CacheStorage;
+
+ CacheStorageCacheHandle(base::WeakPtr<CacheStorageCache> cache_storage_cache,
+ base::WeakPtr<CacheStorage> cache_storage);
+
+ base::WeakPtr<CacheStorageCache> cache_storage_cache_;
+ base::WeakPtr<CacheStorage> cache_storage_;
+
+ DISALLOW_COPY_AND_ASSIGN(CacheStorageCacheHandle);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_CACHE_HANDLE_H_
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 81af984dbb1..e800a4b11d1 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -19,6 +19,7 @@
#include "base/strings/string_split.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/fileapi/mock_url_request_delegate.h"
#include "content/browser/quota/mock_quota_manager_proxy.h"
#include "content/common/cache_storage/cache_storage_types.h"
@@ -228,6 +229,11 @@ bool ResponseMetadataEqual(const ServiceWorkerResponse& expected,
if (expected.cache_storage_cache_name != actual.cache_storage_cache_name)
return false;
+ EXPECT_EQ(expected.cors_exposed_header_names,
+ actual.cors_exposed_header_names);
+ if (expected.cors_exposed_header_names != actual.cors_exposed_header_names)
+ return false;
+
return true;
}
@@ -246,11 +252,10 @@ bool ResponseSideDataEqual(const std::string& expected_side_data,
}
ServiceWorkerResponse SetCacheName(const ServiceWorkerResponse& original) {
- return ServiceWorkerResponse(
- original.url, original.status_code, original.status_text,
- original.response_type, original.headers, original.blob_uuid,
- original.blob_size, original.stream_url, original.error,
- original.response_time, true, kCacheName);
+ ServiceWorkerResponse result(original);
+ result.is_in_cache_storage = true;
+ result.cache_storage_cache_name = kCacheName;
+ return result;
}
} // namespace
@@ -262,12 +267,14 @@ class TestCacheStorageCache : public CacheStorageCache {
const GURL& origin,
const std::string& cache_name,
const base::FilePath& path,
+ CacheStorage* cache_storage,
const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context)
: CacheStorageCache(origin,
cache_name,
path,
+ cache_storage,
request_context_getter,
quota_manager_proxy,
blob_context),
@@ -299,7 +306,11 @@ class TestCacheStorageCache : public CacheStorageCache {
}
private:
- ~TestCacheStorageCache() override {}
+ std::unique_ptr<CacheStorageCacheHandle> CreateCacheHandle() override {
+ // Returns an empty handle. There is no need for CacheStorage and its
+ // handles in these tests.
+ return std::unique_ptr<CacheStorageCacheHandle>();
+ }
bool delay_backend_creation_;
ErrorCallback backend_creation_callback_;
@@ -345,11 +356,11 @@ class CacheStorageCacheTest : public testing::Test {
CreateRequests(blob_storage_context);
- cache_ = make_scoped_refptr(new TestCacheStorageCache(
- GURL(kOrigin), kCacheName, temp_dir_.path(),
- BrowserContext::GetDefaultStoragePartition(&browser_context_)->
- GetURLRequestContext(),
- quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr()));
+ cache_ = base::MakeUnique<TestCacheStorageCache>(
+ GURL(kOrigin), kCacheName, temp_dir_.path(), nullptr /* CacheStorage */,
+ BrowserContext::GetDefaultStoragePartition(&browser_context_)
+ ->GetURLRequestContext(),
+ quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr());
}
void TearDown() override {
@@ -388,7 +399,8 @@ class CacheStorageCacheTest : public testing::Test {
blob_handle_->uuid(), expected_blob_data_.size(), GURL(),
blink::WebServiceWorkerResponseErrorUnknown, base::Time::Now(),
false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */);
+ std::string() /* cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */);
body_response_with_query_ = ServiceWorkerResponse(
GURL("http://example.com/body.html?query=test"), 200, "OK",
@@ -396,14 +408,16 @@ class CacheStorageCacheTest : public testing::Test {
blob_handle_->uuid(), expected_blob_data_.size(), GURL(),
blink::WebServiceWorkerResponseErrorUnknown, base::Time::Now(),
false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */);
+ std::string() /* cache_storage_cache_name */,
+ {"a"} /* cors_exposed_header_names */);
no_body_response_ = ServiceWorkerResponse(
GURL("http://example.com/no_body.html"), 200, "OK",
blink::WebServiceWorkerResponseTypeDefault, headers, "", 0, GURL(),
blink::WebServiceWorkerResponseErrorUnknown, base::Time::Now(),
false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */);
+ std::string() /* cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */);
}
std::unique_ptr<ServiceWorkerFetchRequest> CopyFetchRequest(
@@ -663,7 +677,7 @@ class CacheStorageCacheTest : public testing::Test {
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
storage::BlobStorageContext* blob_storage_context_;
- scoped_refptr<TestCacheStorageCache> cache_;
+ std::unique_ptr<TestCacheStorageCache> cache_;
ServiceWorkerFetchRequest body_request_;
ServiceWorkerResponse body_response_;
@@ -1224,12 +1238,13 @@ TEST_P(CacheStorageCacheTestP, WriteSideData_NotFound) {
TEST_F(CacheStorageCacheTest, CaselessServiceWorkerResponseHeaders) {
// CacheStorageCache depends on ServiceWorkerResponse having caseless
// headers so that it can quickly lookup vary headers.
- ServiceWorkerResponse response(GURL("http://www.example.com"), 200, "OK",
- blink::WebServiceWorkerResponseTypeDefault,
- ServiceWorkerHeaderMap(), "", 0, GURL(),
- blink::WebServiceWorkerResponseErrorUnknown,
- base::Time(), false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */);
+ ServiceWorkerResponse response(
+ GURL("http://www.example.com"), 200, "OK",
+ blink::WebServiceWorkerResponseTypeDefault, ServiceWorkerHeaderMap(), "",
+ 0, GURL(), blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* is_in_cache_storage */,
+ std::string() /* cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */);
response.headers["content-type"] = "foo";
response.headers["Content-Type"] = "bar";
EXPECT_EQ("bar", response.headers["content-type"]);
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 a12c93d6b6c..c34259ffc8e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -12,9 +12,12 @@
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/bad_message.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/common/cache_storage/cache_storage_messages.h"
@@ -30,6 +33,7 @@ namespace content {
namespace {
const uint32_t kFilteredMessageClasses[] = {CacheStorageMsgStart};
+const int32_t kCachePreservationSeconds = 5;
blink::WebServiceWorkerCacheError ToWebServiceWorkerCacheError(
CacheStorageError err) {
@@ -58,12 +62,14 @@ bool OriginCanAccessCacheStorage(const url::Origin& origin) {
return !origin.unique() && IsOriginSecure(GURL(origin.Serialize()));
}
+void StopPreservingCache(
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle) {}
+
} // namespace
CacheStorageDispatcherHost::CacheStorageDispatcherHost()
: BrowserMessageFilter(kFilteredMessageClasses,
- arraysize(kFilteredMessageClasses)) {
-}
+ arraysize(kFilteredMessageClasses)) {}
CacheStorageDispatcherHost::~CacheStorageDispatcherHost() {
}
@@ -216,20 +222,21 @@ void CacheStorageDispatcherHost::OnCacheMatch(
const ServiceWorkerFetchRequest& request,
const CacheStorageCacheQueryParams& match_params) {
IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
- if (it == id_to_cache_map_.end()) {
+ if (it == id_to_cache_map_.end() || !it->second->value()) {
Send(new CacheStorageMsg_CacheMatchError(
thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound));
return;
}
- scoped_refptr<CacheStorageCache> cache = it->second;
+ CacheStorageCache* cache = it->second->value();
std::unique_ptr<ServiceWorkerFetchRequest> scoped_request(
new ServiceWorkerFetchRequest(request.url, request.method,
request.headers, request.referrer,
request.is_reload));
- cache->Match(std::move(scoped_request),
- base::Bind(&CacheStorageDispatcherHost::OnCacheMatchCallback,
- this, thread_id, request_id, cache));
+ cache->Match(
+ std::move(scoped_request),
+ base::Bind(&CacheStorageDispatcherHost::OnCacheMatchCallback, this,
+ thread_id, request_id, base::Passed(it->second->Clone())));
}
void CacheStorageDispatcherHost::OnCacheMatchAll(
@@ -239,18 +246,18 @@ void CacheStorageDispatcherHost::OnCacheMatchAll(
const ServiceWorkerFetchRequest& request,
const CacheStorageCacheQueryParams& match_params) {
IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
- if (it == id_to_cache_map_.end()) {
+ if (it == id_to_cache_map_.end() || !it->second->value()) {
Send(new CacheStorageMsg_CacheMatchError(
thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound));
return;
}
- scoped_refptr<CacheStorageCache> cache = it->second;
+ CacheStorageCache* cache = it->second->value();
if (request.url.is_empty()) {
cache->MatchAll(
std::unique_ptr<ServiceWorkerFetchRequest>(), match_params,
base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallback, this,
- thread_id, request_id, cache));
+ thread_id, request_id, base::Passed(it->second->Clone())));
return;
}
@@ -262,13 +269,14 @@ void CacheStorageDispatcherHost::OnCacheMatchAll(
cache->MatchAll(
std::move(scoped_request), match_params,
base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallback, this,
- thread_id, request_id, cache));
+ thread_id, request_id, base::Passed(it->second->Clone())));
return;
}
cache->Match(
std::move(scoped_request),
base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter,
- this, thread_id, request_id, cache));
+ this, thread_id, request_id,
+ base::Passed(it->second->Clone())));
}
void CacheStorageDispatcherHost::OnCacheKeys(
@@ -278,16 +286,16 @@ void CacheStorageDispatcherHost::OnCacheKeys(
const ServiceWorkerFetchRequest& request,
const CacheStorageCacheQueryParams& match_params) {
IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
- if (it == id_to_cache_map_.end()) {
+ if (it == id_to_cache_map_.end() || !it->second->value()) {
Send(new CacheStorageMsg_CacheKeysError(
thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound));
return;
}
- scoped_refptr<CacheStorageCache> cache = it->second;
-
+ CacheStorageCache* cache = it->second->value();
cache->Keys(base::Bind(&CacheStorageDispatcherHost::OnCacheKeysCallback, this,
- thread_id, request_id, cache));
+ thread_id, request_id,
+ base::Passed(it->second->Clone())));
}
void CacheStorageDispatcherHost::OnCacheBatch(
@@ -296,15 +304,17 @@ void CacheStorageDispatcherHost::OnCacheBatch(
int cache_id,
const std::vector<CacheStorageBatchOperation>& operations) {
IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
- if (it == id_to_cache_map_.end()) {
+ if (it == id_to_cache_map_.end() || !it->second->value()) {
Send(new CacheStorageMsg_CacheBatchError(
thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound));
return;
}
- scoped_refptr<CacheStorageCache> cache = it->second;
+
+ CacheStorageCache* cache = it->second->value();
cache->BatchOperation(
- operations, base::Bind(&CacheStorageDispatcherHost::OnCacheBatchCallback,
- this, thread_id, request_id, cache));
+ operations,
+ base::Bind(&CacheStorageDispatcherHost::OnCacheBatchCallback, this,
+ thread_id, request_id, base::Passed(it->second->Clone())));
}
void CacheStorageDispatcherHost::OnCacheClosed(int cache_id) {
@@ -336,14 +346,22 @@ void CacheStorageDispatcherHost::OnCacheStorageHasCallback(
void CacheStorageDispatcherHost::OnCacheStorageOpenCallback(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error) {
if (error != CACHE_STORAGE_OK) {
Send(new CacheStorageMsg_CacheStorageOpenError(
thread_id, request_id, ToWebServiceWorkerCacheError(error)));
return;
}
- CacheID cache_id = StoreCacheReference(std::move(cache));
+
+ // Hang on to the cache for a few seconds. This way if the user quickly closes
+ // and reopens it the cache backend won't have to be reinitialized.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&StopPreservingCache, base::Passed(cache_handle->Clone())),
+ base::TimeDelta::FromSeconds(kCachePreservationSeconds));
+
+ CacheID cache_id = StoreCacheReference(std::move(cache_handle));
Send(new CacheStorageMsg_CacheStorageOpenSuccess(thread_id, request_id,
cache_id));
}
@@ -402,7 +420,7 @@ void CacheStorageDispatcherHost::OnCacheStorageMatchCallback(
void CacheStorageDispatcherHost::OnCacheMatchCallback(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error,
std::unique_ptr<ServiceWorkerResponse> response,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle) {
@@ -421,7 +439,7 @@ void CacheStorageDispatcherHost::OnCacheMatchCallback(
void CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error,
std::unique_ptr<ServiceWorkerResponse> response,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle) {
@@ -435,14 +453,14 @@ void CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter(
if (blob_data_handle)
blob_data_handles->push_back(*blob_data_handle);
}
- OnCacheMatchAllCallback(thread_id, request_id, std::move(cache), error,
+ OnCacheMatchAllCallback(thread_id, request_id, std::move(cache_handle), error,
std::move(responses), std::move(blob_data_handles));
}
void CacheStorageDispatcherHost::OnCacheMatchAllCallback(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error,
std::unique_ptr<CacheStorageCache::Responses> responses,
std::unique_ptr<CacheStorageCache::BlobDataHandles> blob_data_handles) {
@@ -462,7 +480,7 @@ void CacheStorageDispatcherHost::OnCacheMatchAllCallback(
void CacheStorageDispatcherHost::OnCacheKeysCallback(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error,
std::unique_ptr<CacheStorageCache::Requests> requests) {
if (error != CACHE_STORAGE_OK) {
@@ -486,7 +504,7 @@ void CacheStorageDispatcherHost::OnCacheKeysCallback(
void CacheStorageDispatcherHost::OnCacheBatchCallback(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error) {
if (error != CACHE_STORAGE_OK) {
Send(new CacheStorageMsg_CacheBatchError(
@@ -499,9 +517,9 @@ void CacheStorageDispatcherHost::OnCacheBatchCallback(
CacheStorageDispatcherHost::CacheID
CacheStorageDispatcherHost::StoreCacheReference(
- scoped_refptr<CacheStorageCache> cache) {
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle) {
int cache_id = next_cache_id_++;
- id_to_cache_map_[cache_id] = std::move(cache);
+ id_to_cache_map_[cache_id] = std::move(cache_handle);
return cache_id;
}
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 a62755fce03..d937bac0348 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -41,7 +41,8 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter {
friend class base::DeleteHelper<CacheStorageDispatcherHost>;
typedef int32_t CacheID; // TODO(jkarlin): Bump to 64 bit.
- typedef std::map<CacheID, scoped_refptr<CacheStorageCache>> IDToCacheMap;
+ typedef std::map<CacheID, std::unique_ptr<CacheStorageCacheHandle>>
+ IDToCacheMap;
typedef std::map<std::string, std::list<storage::BlobDataHandle>>
UUIDToBlobDataHandleList;
@@ -95,10 +96,11 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter {
int request_id,
bool has_cache,
CacheStorageError error);
- void OnCacheStorageOpenCallback(int thread_id,
- int request_id,
- scoped_refptr<CacheStorageCache> cache,
- CacheStorageError error);
+ void OnCacheStorageOpenCallback(
+ int thread_id,
+ int request_id,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ CacheStorageError error);
void OnCacheStorageDeleteCallback(int thread_id,
int request_id,
bool deleted,
@@ -118,21 +120,21 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter {
void OnCacheMatchCallback(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error,
std::unique_ptr<ServiceWorkerResponse> response,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle);
void OnCacheMatchAllCallbackAdapter(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error,
std::unique_ptr<ServiceWorkerResponse> response,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle);
void OnCacheMatchAllCallback(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error,
std::unique_ptr<std::vector<ServiceWorkerResponse>> responses,
std::unique_ptr<CacheStorageCache::BlobDataHandles> blob_data_handles);
@@ -144,18 +146,19 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter {
void OnCacheKeysCallback(
int thread_id,
int request_id,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error,
std::unique_ptr<CacheStorageCache::Requests> requests);
- void OnCacheBatchCallback(int thread_id,
- int request_id,
- scoped_refptr<CacheStorageCache> cache,
- CacheStorageError error);
+ void OnCacheBatchCallback(
+ int thread_id,
+ int request_id,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ CacheStorageError error);
- // Hangs onto a scoped_refptr for the cache if it isn't already doing so.
- // Returns a unique cache_id. Call DropCacheReference when the client is done
- // with this cache.
- CacheID StoreCacheReference(scoped_refptr<CacheStorageCache> cache);
+ // Hangs onto a cache handle. Returns a unique cache_id. Call
+ // DropCacheReference when the reference is no longer needed.
+ CacheID StoreCacheReference(
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle);
void DropCacheReference(CacheID cache_id);
// Stores blob handles while waiting for acknowledgement of receipt from the
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 123774e1dd9..0da84acf861 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -22,6 +22,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/cache_storage/cache_storage.pb.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_quota_client.h"
#include "content/browser/quota/mock_quota_manager_proxy.h"
#include "content/public/browser/browser_thread.h"
@@ -121,10 +122,11 @@ class CacheStorageManagerTest : public testing::Test {
run_loop->Quit();
}
- void CacheAndErrorCallback(base::RunLoop* run_loop,
- scoped_refptr<CacheStorageCache> cache,
- CacheStorageError error) {
- callback_cache_ = std::move(cache);
+ void CacheAndErrorCallback(
+ base::RunLoop* run_loop,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ CacheStorageError error) {
+ callback_cache_handle_ = std::move(cache_handle);
callback_error_ = error;
run_loop->Quit();
}
@@ -148,7 +150,7 @@ class CacheStorageManagerTest : public testing::Test {
std::unique_ptr<ServiceWorkerResponse> response,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle) {
callback_error_ = error;
- callback_cache_response_ = std::move(response);
+ callback_cache_handle_response_ = std::move(response);
callback_data_handle_ = std::move(blob_data_handle);
run_loop->Quit();
}
@@ -163,9 +165,9 @@ class CacheStorageManagerTest : public testing::Test {
bool error = callback_error_ != CACHE_STORAGE_OK;
if (error)
- EXPECT_TRUE(!callback_cache_.get());
+ EXPECT_FALSE(callback_cache_handle_);
else
- EXPECT_TRUE(callback_cache_.get());
+ EXPECT_TRUE(callback_cache_handle_);
return !error;
}
@@ -252,7 +254,8 @@ class CacheStorageManagerTest : public testing::Test {
ServiceWorkerHeaderMap(), blob_handle->uuid(), url.spec().size(),
GURL(), blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */);
+ std::string() /* cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */);
CacheStorageBatchOperation operation;
operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
@@ -349,10 +352,10 @@ class CacheStorageManagerTest : public testing::Test {
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
std::unique_ptr<CacheStorageManager> cache_manager_;
- scoped_refptr<CacheStorageCache> callback_cache_;
+ std::unique_ptr<CacheStorageCacheHandle> callback_cache_handle_;
int callback_bool_;
CacheStorageError callback_error_;
- std::unique_ptr<ServiceWorkerResponse> callback_cache_response_;
+ std::unique_ptr<ServiceWorkerResponse> callback_cache_handle_response_;
std::unique_ptr<storage::BlobDataHandle> callback_data_handle_;
std::vector<std::string> callback_strings_;
@@ -392,23 +395,26 @@ TEST_P(CacheStorageManagerTestP, OpenTwoCaches) {
TEST_P(CacheStorageManagerTestP, CachePointersDiffer) {
EXPECT_TRUE(Open(origin1_, "foo"));
- scoped_refptr<CacheStorageCache> cache = callback_cache_;
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, "bar"));
- EXPECT_NE(callback_cache_.get(), cache.get());
+ EXPECT_NE(callback_cache_handle_->value(), cache_handle->value());
}
TEST_P(CacheStorageManagerTestP, Open2CachesSameNameDiffOrigins) {
EXPECT_TRUE(Open(origin1_, "foo"));
- scoped_refptr<CacheStorageCache> cache = callback_cache_;
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin2_, "foo"));
- EXPECT_NE(cache.get(), callback_cache_.get());
+ EXPECT_NE(cache_handle->value(), callback_cache_handle_->value());
}
TEST_P(CacheStorageManagerTestP, OpenExistingCache) {
EXPECT_TRUE(Open(origin1_, "foo"));
- scoped_refptr<CacheStorageCache> cache = callback_cache_;
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_EQ(callback_cache_.get(), cache.get());
+ EXPECT_EQ(callback_cache_handle_->value(), cache_handle->value());
}
TEST_P(CacheStorageManagerTestP, HasCache) {
@@ -436,7 +442,8 @@ TEST_P(CacheStorageManagerTestP, DeleteTwice) {
TEST_P(CacheStorageManagerTestP, DeleteCacheReducesOriginSize) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
// The quota manager gets updated after the put operation runs its callback so
// run the event loop.
base::RunLoop().RunUntilIdle();
@@ -478,33 +485,38 @@ TEST_P(CacheStorageManagerTestP, DeletedKeysGone) {
TEST_P(CacheStorageManagerTestP, StorageMatchEntryExists) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
}
TEST_P(CacheStorageManagerTestP, StorageMatchNoEntry) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bar")));
EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
}
TEST_P(CacheStorageManagerTestP, StorageMatchNoCache) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
EXPECT_FALSE(StorageMatch(origin1_, "bar", GURL("http://example.com/foo")));
EXPECT_EQ(CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND, callback_error_);
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExists) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllNoEntry) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/bar")));
EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
}
@@ -519,8 +531,8 @@ TEST_F(CacheStorageManagerTest, StorageReuseCacheName) {
// with the same URL should work. (see crbug.com/542668)
const GURL kTestURL = GURL("http://example.com/foo");
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), kTestURL));
- EXPECT_TRUE(CacheMatch(callback_cache_.get(), kTestURL));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(), kTestURL));
+ EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), kTestURL));
std::unique_ptr<storage::BlobDataHandle> data_handle =
std::move(callback_data_handle_);
@@ -528,28 +540,29 @@ TEST_F(CacheStorageManagerTest, StorageReuseCacheName) {
// The cache is deleted but the handle to one of its entries is still
// open. Creating a new cache in the same directory would fail on Windows.
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), kTestURL));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(), kTestURL));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExistsTwice) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePutWithStatusCode(callback_cache_.get(),
+ EXPECT_TRUE(CachePutWithStatusCode(callback_cache_handle_->value(),
GURL("http://example.com/foo"), 200));
EXPECT_TRUE(Open(origin1_, "bar"));
- EXPECT_TRUE(CachePutWithStatusCode(callback_cache_.get(),
+ EXPECT_TRUE(CachePutWithStatusCode(callback_cache_handle_->value(),
GURL("http://example.com/foo"), 201));
EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
// The caches need to be searched in order of creation, so verify that the
// response came from the first cache.
- EXPECT_EQ(200, callback_cache_response_->status_code);
+ EXPECT_EQ(200, callback_cache_handle_response_->status_code);
}
TEST_P(CacheStorageManagerTestP, StorageMatchInOneOfMany) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin1_, "bar"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
EXPECT_TRUE(Open(origin1_, "baz"));
EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
@@ -557,9 +570,10 @@ TEST_P(CacheStorageManagerTestP, StorageMatchInOneOfMany) {
TEST_P(CacheStorageManagerTestP, Chinese) {
EXPECT_TRUE(Open(origin1_, "你好"));
- scoped_refptr<CacheStorageCache> cache = callback_cache_;
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, "你好"));
- EXPECT_EQ(callback_cache_.get(), cache.get());
+ EXPECT_EQ(callback_cache_handle_->value(), cache_handle->value());
EXPECT_TRUE(Keys(origin1_));
EXPECT_EQ(1u, callback_strings_.size());
EXPECT_STREQ("你好", callback_strings_[0].c_str());
@@ -567,9 +581,10 @@ TEST_P(CacheStorageManagerTestP, Chinese) {
TEST_F(CacheStorageManagerTest, EmptyKey) {
EXPECT_TRUE(Open(origin1_, ""));
- scoped_refptr<CacheStorageCache> cache = callback_cache_;
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle =
+ std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, ""));
- EXPECT_EQ(cache.get(), callback_cache_.get());
+ EXPECT_EQ(cache_handle->value(), callback_cache_handle_->value());
EXPECT_TRUE(Keys(origin1_));
EXPECT_EQ(1u, callback_strings_.size());
EXPECT_STREQ("", callback_strings_[0].c_str());
@@ -624,10 +639,32 @@ TEST_F(CacheStorageManagerTest, BadOriginName) {
EXPECT_STREQ("foo", callback_strings_[0].c_str());
}
+// With a persistent cache if the client drops its reference to a
+// CacheStorageCache it should be deleted.
+TEST_F(CacheStorageManagerTest, DropReference) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ base::WeakPtr<CacheStorageCache> cache =
+ callback_cache_handle_->value()->AsWeakPtr();
+ callback_cache_handle_ = nullptr;
+ EXPECT_FALSE(cache);
+}
+
+// With a memory cache the cache can't be freed from memory until the client
+// calls delete.
+TEST_F(CacheStorageManagerMemoryOnlyTest, MemoryLosesReferenceOnlyAfterDelete) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ base::WeakPtr<CacheStorageCache> cache =
+ callback_cache_handle_->value()->AsWeakPtr();
+ callback_cache_handle_ = nullptr;
+ EXPECT_TRUE(cache);
+ EXPECT_TRUE(Delete(origin1_, "foo"));
+ EXPECT_FALSE(cache);
+}
+
TEST_P(CacheStorageManagerTestP, DeleteBeforeRelease) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Delete(origin1_, "foo"));
- EXPECT_TRUE(callback_cache_->AsWeakPtr());
+ EXPECT_TRUE(callback_cache_handle_->value());
}
TEST_P(CacheStorageManagerTestP, OpenRunsSerially) {
@@ -642,25 +679,27 @@ TEST_P(CacheStorageManagerTestP, OpenRunsSerially) {
base::Unretained(this), base::Unretained(&open_loop)));
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(callback_cache_);
+ EXPECT_FALSE(callback_cache_handle_);
cache_storage->CompleteAsyncOperationForTesting();
open_loop.Run();
- EXPECT_TRUE(callback_cache_);
+ EXPECT_TRUE(callback_cache_handle_);
}
TEST_P(CacheStorageManagerTestP, GetOriginUsage) {
EXPECT_EQ(0, GetOriginUsage(origin1_));
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(0, GetOriginUsage(origin1_));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
int64_t foo_size = GetOriginUsage(origin1_);
EXPECT_LT(0, GetOriginUsage(origin1_));
EXPECT_EQ(0, GetOriginUsage(origin2_));
// Add the same entry into a second cache, the size should double.
EXPECT_TRUE(Open(origin1_, "bar"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
EXPECT_EQ(2 * foo_size, GetOriginUsage(origin1_));
}
@@ -668,12 +707,15 @@ TEST_P(CacheStorageManagerTestP, GetAllOriginsUsage) {
EXPECT_EQ(0ULL, GetAllOriginsUsage().size());
// Put one entry in a cache on origin 1.
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
// Put two entries (of identical size) in a cache on origin 2.
EXPECT_TRUE(Open(origin2_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/bar")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/bar")));
std::vector<CacheStorageUsageInfo> usage = GetAllOriginsUsage();
EXPECT_EQ(2ULL, usage.size());
@@ -697,22 +739,27 @@ TEST_P(CacheStorageManagerTestP, GetAllOriginsUsage) {
TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCaches) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo2")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo2")));
EXPECT_TRUE(Open(origin1_, "bar"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/bar")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/bar")));
int64_t origin_size = GetOriginUsage(origin1_);
EXPECT_LT(0, origin_size);
EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(origin1_));
- EXPECT_FALSE(CachePut(callback_cache_.get(), GURL("http://example.com/baz")));
+ EXPECT_FALSE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/baz")));
}
TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) {
// Create a referenced cache.
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
// Create an unreferenced directory next to the referenced one.
base::FilePath origin_path = CacheStorageManager::ConstructOriginPath(
@@ -728,8 +775,8 @@ TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) {
// Verify that the referenced cache still works.
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(
- CacheMatch(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
// Verify that the unreferenced cache is gone.
EXPECT_FALSE(base::DirectoryExists(unreferenced_path));
@@ -803,7 +850,7 @@ class CacheStorageMigrationTest : public CacheStorageManagerTest {
ASSERT_FALSE(base::DirectoryExists(new_path_));
ASSERT_TRUE(Open(origin1_, cache1_));
ASSERT_TRUE(Open(origin1_, cache2_));
- callback_cache_ = nullptr;
+ callback_cache_handle_.reset();
ASSERT_FALSE(base::DirectoryExists(legacy_path_));
ASSERT_TRUE(base::DirectoryExists(new_path_));
@@ -893,11 +940,11 @@ class MigratedLegacyCacheDirectoryNameTest : public CacheStorageManagerTest {
// Populate a legacy cache.
ASSERT_TRUE(Open(origin1_, legacy_cache_name_));
- EXPECT_TRUE(CachePut(callback_cache_.get(), stored_url_));
- base::FilePath new_path = callback_cache_->path();
+ 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_->Close(base::Bind(&base::DoNothing));
+ 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
@@ -946,29 +993,31 @@ TEST_F(MigratedLegacyCacheDirectoryNameTest, LegacyCacheMigrated) {
ASSERT_FALSE(base::DirectoryExists(legacy_path_));
// Verify that the existing entry still works.
- EXPECT_TRUE(CacheMatch(callback_cache_.get(), stored_url_));
+ EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), stored_url_));
// Verify that adding new entries works.
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo2")));
- EXPECT_TRUE(
- CacheMatch(callback_cache_.get(), GURL("http://example.com/foo2")));
+ 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_.get(), stored_url_));
- EXPECT_TRUE(CacheMatch(callback_cache_.get(), stored_url_));
+ 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_.get(), stored_url_));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo2")));
- EXPECT_TRUE(
- CacheMatch(callback_cache_.get(), GURL("http://example.com/foo2")));
+ 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 {
@@ -1067,7 +1116,8 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaID) {
TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginUsage) {
EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
EXPECT_LT(0, QuotaGetOriginUsage(origin1_));
}
@@ -1096,7 +1146,8 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteOriginData) {
EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
EXPECT_TRUE(Open(origin1_, "foo"));
// Call put to test that initialized caches are properly deleted too.
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(Open(origin2_, "baz"));
@@ -1120,11 +1171,12 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteEmptyOrigin) {
TEST_F(CacheStorageQuotaClientDiskOnlyTest, QuotaDeleteUnloadedOriginData) {
EXPECT_TRUE(Open(origin1_, "foo"));
// Call put to test that initialized caches are properly deleted too.
- EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
// Close the cache backend so that it writes out its index to disk.
base::RunLoop run_loop;
- callback_cache_->Close(run_loop.QuitClosure());
+ callback_cache_handle_->value()->Close(run_loop.QuitClosure());
run_loop.Run();
// Create a new CacheStorageManager that hasn't yet loaded the origin.
diff --git a/chromium/content/browser/cache_storage/cache_storage_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_unittest.cc
deleted file mode 100644
index 84e1e22aee0..00000000000
--- a/chromium/content/browser/cache_storage/cache_storage_unittest.cc
+++ /dev/null
@@ -1,139 +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/cache_storage/cache_storage.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#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/threading/thread_task_runner_handle.h"
-#include "content/browser/quota/mock_quota_manager_proxy.h"
-#include "content/public/test/mock_special_storage_policy.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "storage/browser/quota/quota_manager_proxy.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-const char kOrigin[] = "http://example.com/";
-}
-
-class TestCacheStorage : public CacheStorage {
- public:
- TestCacheStorage(
- const base::FilePath& file_path,
- scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy)
- : CacheStorage(file_path,
- false /* memory_only */,
- base::ThreadTaskRunnerHandle::Get().get(),
- scoped_refptr<net::URLRequestContextGetter>(),
- quota_manager_proxy,
- base::WeakPtr<storage::BlobStorageContext>(),
- GURL(kOrigin)),
- delay_preserved_cache_callback_(false) {}
-
- void RunPreservedCacheCallback() {
- ASSERT_FALSE(preserved_cache_callback_.is_null());
- preserved_cache_callback_.Run();
- preserved_cache_callback_.Reset();
- }
-
- void set_delay_preserved_cache_callback(bool should_delay) {
- delay_preserved_cache_callback_ = should_delay;
- }
-
- bool IsPreservingCache(const CacheStorageCache* cache) {
- return ContainsKey(preserved_caches_, cache);
- }
-
- private:
- void SchedulePreservedCacheRemoval(const base::Closure& callback) override {
- if (!delay_preserved_cache_callback_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
- return;
- }
- preserved_cache_callback_ = callback;
- }
-
- bool delay_preserved_cache_callback_;
- base::Closure preserved_cache_callback_;
-};
-
-class CacheStorageTest : public testing::Test {
- protected:
- CacheStorageTest()
- : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
-
- void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-
- quota_policy_ = new MockSpecialStoragePolicy;
- mock_quota_manager_ = new MockQuotaManager(
- false /* is incognito */, temp_dir_.path(),
- base::ThreadTaskRunnerHandle::Get().get(),
- base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get());
- quota_manager_proxy_ = new MockQuotaManagerProxy(
- mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
-
- test_cache_storage_.reset(
- new TestCacheStorage(temp_dir_.path(), quota_manager_proxy_));
- }
-
- bool OpenCache(const std::string& cache_name) {
- bool callback_called = false;
- test_cache_storage_->OpenCache(
- cache_name, base::Bind(&CacheStorageTest::OpenCacheCallback,
- base::Unretained(this), &callback_called));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(callback_called);
- return callback_error_ == CACHE_STORAGE_OK;
- }
-
- void OpenCacheCallback(bool* callback_called,
- scoped_refptr<CacheStorageCache> cache,
- CacheStorageError error) {
- *callback_called = true;
- callback_cache_ = cache;
- callback_error_ = error;
- }
-
- base::ScopedTempDir temp_dir_;
- TestBrowserThreadBundle browser_thread_bundle_;
- scoped_refptr<MockSpecialStoragePolicy> quota_policy_;
- scoped_refptr<MockQuotaManager> mock_quota_manager_;
- scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
- std::unique_ptr<TestCacheStorage> test_cache_storage_;
-
- scoped_refptr<CacheStorageCache> callback_cache_;
- CacheStorageError callback_error_;
-};
-
-TEST_F(CacheStorageTest, PreserveCache) {
- test_cache_storage_->set_delay_preserved_cache_callback(true);
- EXPECT_TRUE(OpenCache("foo"));
- EXPECT_TRUE(test_cache_storage_->IsPreservingCache(callback_cache_.get()));
- test_cache_storage_->RunPreservedCacheCallback();
- EXPECT_FALSE(test_cache_storage_->IsPreservingCache(callback_cache_.get()));
-
- // Try opening it again, since the cache is already open (callback_cache_ is
- // referencing it) the cache shouldn't be preserved again.
- EXPECT_TRUE(OpenCache("foo"));
- EXPECT_FALSE(test_cache_storage_->IsPreservingCache(callback_cache_.get()));
-
- // Remove the reference to the cache so that it's deleted. After that, the
- // next time it's opened will require the cache to be created again and
- // preserved.
- callback_cache_ = nullptr;
- EXPECT_TRUE(OpenCache("foo"));
- EXPECT_TRUE(test_cache_storage_->IsPreservingCache(callback_cache_.get()));
- test_cache_storage_->RunPreservedCacheCallback();
- EXPECT_FALSE(test_cache_storage_->IsPreservingCache(callback_cache_.get()));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/cert_store_impl.cc b/chromium/content/browser/cert_store_impl.cc
index cc0d880ecfc..6b183ace9af 100644
--- a/chromium/content/browser/cert_store_impl.cc
+++ b/chromium/content/browser/cert_store_impl.cc
@@ -16,17 +16,37 @@ CertStoreImpl* CertStoreImpl::GetInstance() {
return base::Singleton<CertStoreImpl>::get();
}
-CertStoreImpl::CertStoreImpl() {}
-
-CertStoreImpl::~CertStoreImpl() {}
-
int CertStoreImpl::StoreCert(net::X509Certificate* cert, int process_id) {
- return store_.Store(cert, process_id);
+ scoped_refptr<HashAndCert> hash_and_cert(new HashAndCert);
+ hash_and_cert->chain_hash =
+ net::X509Certificate::CalculateChainFingerprint256(
+ cert->os_cert_handle(), cert->GetIntermediateCertificates());
+ hash_and_cert->cert = cert;
+ return store_.Store(hash_and_cert.get(), process_id);
}
bool CertStoreImpl::RetrieveCert(int cert_id,
scoped_refptr<net::X509Certificate>* cert) {
- return store_.Retrieve(cert_id, cert);
+ scoped_refptr<HashAndCert> hash_and_cert;
+ if (store_.Retrieve(cert_id, &hash_and_cert)) {
+ *cert = hash_and_cert->cert;
+ return true;
+ }
+ return false;
+}
+
+CertStoreImpl::CertStoreImpl() {}
+
+CertStoreImpl::~CertStoreImpl() {}
+
+CertStoreImpl::HashAndCert::HashAndCert() = default;
+
+bool CertStoreImpl::HashAndCert::LessThan::operator()(
+ const scoped_refptr<HashAndCert>& lhs,
+ const scoped_refptr<HashAndCert>& rhs) const {
+ return net::SHA256HashValueLessThan()(lhs->chain_hash, rhs->chain_hash);
}
+CertStoreImpl::HashAndCert::~HashAndCert() = default;
+
} // namespace content
diff --git a/chromium/content/browser/cert_store_impl.h b/chromium/content/browser/cert_store_impl.h
index 2b08c52c802..b4ef08c0044 100644
--- a/chromium/content/browser/cert_store_impl.h
+++ b/chromium/content/browser/cert_store_impl.h
@@ -6,9 +6,11 @@
#define CONTENT_BROWSER_CERT_STORE_IMPL_H_
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
#include "content/browser/renderer_data_memoizing_store.h"
#include "content/public/browser/cert_store.h"
+#include "net/base/hash_value.h"
#include "net/cert/x509_certificate.h"
namespace content {
@@ -31,7 +33,30 @@ class CertStoreImpl : public CertStore {
private:
friend struct base::DefaultSingletonTraits<CertStoreImpl>;
- RendererDataMemoizingStore<net::X509Certificate> store_;
+ // Utility structure that allows memoization to be based on the
+ // hash of |cert|'s certificate chain, to avoid needing to compare
+ // every certificate individually. This is purely an optimization.
+ class HashAndCert : public base::RefCountedThreadSafe<HashAndCert> {
+ public:
+ HashAndCert();
+
+ // Comparator for RendererDataMemoizingStore.
+ struct LessThan {
+ bool operator()(const scoped_refptr<HashAndCert>& lhs,
+ const scoped_refptr<HashAndCert>& rhs) const;
+ };
+
+ net::SHA256HashValue chain_hash;
+ scoped_refptr<net::X509Certificate> cert;
+
+ private:
+ friend class base::RefCountedThreadSafe<HashAndCert>;
+
+ ~HashAndCert();
+
+ DISALLOW_COPY_AND_ASSIGN(HashAndCert);
+ };
+ RendererDataMemoizingStore<HashAndCert> store_;
DISALLOW_COPY_AND_ASSIGN(CertStoreImpl);
};
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index 6b88b049946..5d7a304e67e 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -25,6 +25,8 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/named_platform_channel_pair.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#if defined(OS_WIN)
@@ -142,9 +144,8 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
base::Process process;
#if defined(OS_WIN)
if (launch_elevated) {
- // TODO(rockot): We may want to support Mojo IPC to elevated processes as
- // well, but this isn't currently feasible without sharing a pipe path on
- // the command line as elevated process launch goes through ShellExecuteEx.
+ // When establishing a Mojo connection, the pipe path has already been added
+ // to the command line.
base::LaunchOptions options;
options.start_hidden = true;
process = base::LaunchElevatedProcess(*cmd_line, options);
@@ -197,11 +198,8 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
}
};
maybe_register(
- kV8NativesDataDescriptor32,
- gin::V8Initializer::GetOpenNativesFileForChildProcesses(&region, true));
- maybe_register(
- kV8NativesDataDescriptor64,
- gin::V8Initializer::GetOpenNativesFileForChildProcesses(&region, false));
+ kV8NativesDataDescriptor,
+ gin::V8Initializer::GetOpenNativesFileForChildProcesses(&region));
maybe_register(
kV8SnapshotDataDescriptor32,
gin::V8Initializer::GetOpenSnapshotFileForChildProcesses(&region, true));
@@ -394,12 +392,15 @@ ChildProcessLauncher::ChildProcessLauncher(
base::CommandLine* cmd_line,
int child_process_id,
Client* client,
+ const std::string& mojo_child_token,
+ const mojo::edk::ProcessErrorCallback& process_error_callback,
bool terminate_on_shutdown)
: client_(client),
termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
exit_code_(RESULT_CODE_NORMAL_EXIT),
zygote_(nullptr),
starting_(true),
+ process_error_callback_(process_error_callback),
#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
defined(UNDEFINED_SANITIZER)
@@ -407,6 +408,7 @@ ChildProcessLauncher::ChildProcessLauncher(
#else
terminate_child_on_shutdown_(terminate_on_shutdown),
#endif
+ mojo_child_token_(mojo_child_token),
weak_factory_(this) {
DCHECK(CalledOnValidThread());
CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
@@ -454,8 +456,19 @@ void ChildProcessLauncher::Launch(
NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch,
weak_factory_.GetWeakPtr(),
terminate_child_on_shutdown_));
- mojo::edk::ScopedPlatformHandle client_handle =
- mojo_platform_channel_.PassClientHandle();
+ mojo::edk::ScopedPlatformHandle client_handle;
+#if defined(OS_WIN)
+ if (delegate->ShouldLaunchElevated()) {
+ mojo::edk::NamedPlatformChannelPair named_pair;
+ mojo_host_platform_handle_ = named_pair.PassServerHandle();
+ named_pair.PrepareToPassClientHandleToChildProcess(cmd_line);
+ } else
+#endif
+ {
+ mojo::edk::PlatformChannelPair channel_pair;
+ mojo_host_platform_handle_ = channel_pair.PassServerHandle();
+ client_handle = channel_pair.PassClientHandle();
+ }
BrowserThread::PostTask(
BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_,
@@ -545,7 +558,9 @@ void ChildProcessLauncher::Notify(ZygoteHandle zygote,
if (process_.IsValid()) {
// Set up Mojo IPC to the new process.
mojo::edk::ChildProcessLaunched(process_.Handle(),
- mojo_platform_channel_.PassServerHandle());
+ std::move(mojo_host_platform_handle_),
+ mojo_child_token_,
+ process_error_callback_);
}
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
@@ -554,6 +569,7 @@ void ChildProcessLauncher::Notify(ZygoteHandle zygote,
if (process_.IsValid()) {
client_->OnProcessLaunched();
} else {
+ mojo::edk::ChildProcessLaunchFailed(mojo_child_token_);
termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED;
client_->OnProcessLaunchFailed(error_code);
}
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index d5efc1e4dd6..6f51a90a6d6 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -16,7 +16,8 @@
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox_types.h"
@@ -69,11 +70,17 @@ class CONTENT_EXPORT ChildProcessLauncher : public base::NonThreadSafe {
// the callback won't be called. If the process is still running by the time
// this object destructs, it will be terminated.
// Takes ownership of cmd_line.
+ //
+ // If |process_error_callback| is provided, it will be called if a Mojo error
+ // is encountered when processing messages from the child process. This
+ // callback must be safe to call from any thread.
ChildProcessLauncher(
SandboxedProcessLauncherDelegate* delegate,
base::CommandLine* cmd_line,
int child_process_id,
Client* client,
+ const std::string& mojo_child_token,
+ const mojo::edk::ProcessErrorCallback& process_error_callback,
bool terminate_on_shutdown = true);
~ChildProcessLauncher();
@@ -151,12 +158,15 @@ class CONTENT_EXPORT ChildProcessLauncher : public base::NonThreadSafe {
int exit_code_;
ZygoteHandle zygote_;
bool starting_;
+ const mojo::edk::ProcessErrorCallback process_error_callback_;
+
// Controls whether the child process should be terminated on browser
// shutdown. Default behavior is to terminate the child.
const bool terminate_child_on_shutdown_;
- // Platform channel used to establish Mojo IPC.
- mojo::edk::PlatformChannelPair mojo_platform_channel_;
+ // Host side platform handle to establish Mojo IPC.
+ mojo::edk::ScopedPlatformHandle mojo_host_platform_handle_;
+ const std::string mojo_child_token_;
base::WeakPtrFactory<ChildProcessLauncher> weak_factory_;
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index bd84239b04f..0def4b57ad0 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -4,6 +4,7 @@
#include "content/browser/child_process_security_policy_impl.h"
+#include <algorithm>
#include <utility>
#include "base/command_line.h"
@@ -393,16 +394,6 @@ void ChildProcessSecurityPolicyImpl::GrantRequestURL(
return; // The scheme has already been whitelisted for every child process.
if (IsPseudoScheme(url.scheme())) {
- // The view-source scheme is a special case of a pseudo-URL that eventually
- // results in requesting its embedded URL.
- if (url.SchemeIs(kViewSourceScheme)) {
- // URLs with the view-source scheme typically look like:
- // view-source:http://www.google.com/a
- // In order to request these URLs, the child_id needs to be able to
- // request the embedded URL.
- GrantRequestURL(child_id, GURL(url.GetContent()));
- }
-
return; // Can't grant the capability to request pseudo schemes.
}
@@ -585,25 +576,13 @@ bool ChildProcessSecurityPolicyImpl::CanRequestURL(
return false; // Can't request invalid URLs.
if (IsPseudoScheme(url.scheme())) {
- // There are a number of special cases for pseudo schemes.
-
- if (url.SchemeIs(kViewSourceScheme)) {
- // A view-source URL is allowed if the child process is permitted to
- // request the embedded URL. Careful to avoid pointless recursion.
- GURL child_url(url.GetContent());
- if (child_url.SchemeIs(kViewSourceScheme) &&
- url.SchemeIs(kViewSourceScheme))
- return false;
-
- return CanRequestURL(child_id, child_url);
- }
-
+ // Every child process can request <about:blank>.
if (base::LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL))
- return true; // Every child process can request <about:blank>.
-
- // URLs like <about:version> and <about:crash> shouldn't be requestable by
- // any child process. Also, this case covers <javascript:...>, which should
- // be handled internally by the process and not kicked up to the browser.
+ return true;
+ // URLs like <about:version>, <about:crash>, <view-source:...> shouldn't be
+ // requestable by any child process. Also, this case covers
+ // <javascript:...>, which should be handled internally by the process and
+ // not kicked up to the browser.
return false;
}
@@ -650,6 +629,15 @@ bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id,
return HasPermissionsForFile(child_id, file, READ_FILE_GRANT);
}
+bool ChildProcessSecurityPolicyImpl::CanReadAllFiles(
+ int child_id,
+ const std::vector<base::FilePath>& files) {
+ return std::all_of(files.begin(), files.end(),
+ [this, child_id](const base::FilePath& file) {
+ return CanReadFile(child_id, file);
+ });
+}
+
bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile(
int child_id,
const base::FilePath& file) {
diff --git a/chromium/content/browser/child_process_security_policy_impl.h b/chromium/content/browser/child_process_security_policy_impl.h
index 2f2b8100b8c..271e69c0acd 100644
--- a/chromium/content/browser/child_process_security_policy_impl.h
+++ b/chromium/content/browser/child_process_security_policy_impl.h
@@ -8,6 +8,7 @@
#include <map>
#include <set>
#include <string>
+#include <vector>
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
@@ -77,6 +78,9 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
void GrantSendMidiSysExMessage(int child_id) override;
bool CanAccessDataForOrigin(int child_id, const GURL& url) override;
+ // Returns if |child_id| can read all of the |files|.
+ bool CanReadAllFiles(int child_id, const std::vector<base::FilePath>& files);
+
// Pseudo schemes are treated differently than other schemes because they
// cannot be requested like normal URLs. There is no mechanism for revoking
// pseudo schemes.
diff --git a/chromium/content/browser/child_process_security_policy_unittest.cc b/chromium/content/browser/child_process_security_policy_unittest.cc
index 455da447dd3..24aa45bc21f 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -169,21 +169,19 @@ TEST_F(ChildProcessSecurityPolicyTest, StandardSchemesTest) {
EXPECT_TRUE(p->CanCommitURL(
kRendererID, GURL("filesystem:http://localhost/temporary/a.gif")));
- // Safe to request but not commit.
- EXPECT_TRUE(p->CanRequestURL(kRendererID,
- GURL("view-source:http://www.google.com/")));
- EXPECT_FALSE(p->CanCommitURL(kRendererID,
- GURL("view-source:http://www.google.com/")));
-
// Dangerous to request or commit.
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("chrome://foo/bar")));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID,
+ GURL("view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanCommitURL(kRendererID,
GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanCommitURL(kRendererID,
GURL("chrome://foo/bar")));
+ EXPECT_FALSE(
+ p->CanCommitURL(kRendererID, GURL("view-source:http://www.google.com/")));
p->Remove(kRendererID);
}
@@ -300,9 +298,9 @@ TEST_F(ChildProcessSecurityPolicyTest, ViewSource) {
p->Add(kRendererID);
- // View source is determined by the embedded scheme.
- EXPECT_TRUE(p->CanRequestURL(kRendererID,
- GURL("view-source:http://www.google.com/")));
+ // Child processes cannot request view source URLs.
+ EXPECT_FALSE(p->CanRequestURL(kRendererID,
+ GURL("view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("view-source:file:///etc/passwd")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
@@ -319,16 +317,13 @@ TEST_F(ChildProcessSecurityPolicyTest, ViewSource) {
EXPECT_FALSE(p->CanCommitURL(
kRendererID, GURL("view-source:view-source:http://www.google.com/")));
-
p->GrantRequestURL(kRendererID, GURL("view-source:file:///etc/passwd"));
- // View source needs to be able to request the embedded scheme.
- EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
- EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
- EXPECT_TRUE(p->CanRequestURL(kRendererID,
- GURL("view-source:file:///etc/passwd")));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
+ EXPECT_FALSE(
+ p->CanRequestURL(kRendererID, GURL("view-source:file:///etc/passwd")));
EXPECT_FALSE(p->CanCommitURL(kRendererID,
GURL("view-source:file:///etc/passwd")));
-
p->Remove(kRendererID);
}
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.cc b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
index eb2a98cfa3a..b5fbbcf6eb6 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
@@ -9,9 +9,11 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "cc/base/switches.h"
#include "cc/output/output_surface_client.h"
+#include "cc/scheduler/begin_frame_source.h"
#include "components/display_compositor/compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
@@ -21,14 +23,12 @@ namespace content {
BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
scoped_refptr<cc::ContextProvider> context_provider,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
- base::SingleThreadTaskRunner* task_runner,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
overlay_candidate_validator)
- : OutputSurface(std::move(context_provider)),
+ : OutputSurface(std::move(context_provider), nullptr, nullptr),
vsync_manager_(std::move(vsync_manager)),
- synthetic_begin_frame_source_(new cc::SyntheticBeginFrameSource(
- task_runner,
- cc::BeginFrameArgs::DefaultInterval())),
+ synthetic_begin_frame_source_(begin_frame_source),
reflector_(nullptr),
use_begin_frame_scheduling_(
base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -40,12 +40,10 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
std::unique_ptr<cc::SoftwareOutputDevice> software_device,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- base::SingleThreadTaskRunner* task_runner)
- : OutputSurface(std::move(software_device)),
+ cc::SyntheticBeginFrameSource* begin_frame_source)
+ : OutputSurface(nullptr, nullptr, std::move(software_device)),
vsync_manager_(vsync_manager),
- synthetic_begin_frame_source_(new cc::SyntheticBeginFrameSource(
- task_runner,
- cc::BeginFrameArgs::DefaultInterval())),
+ synthetic_begin_frame_source_(begin_frame_source),
reflector_(nullptr),
use_begin_frame_scheduling_(
base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -56,12 +54,10 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- base::SingleThreadTaskRunner* task_runner)
- : OutputSurface(nullptr, nullptr, vulkan_context_provider, nullptr),
+ cc::SyntheticBeginFrameSource* begin_frame_source)
+ : OutputSurface(std::move(vulkan_context_provider)),
vsync_manager_(vsync_manager),
- synthetic_begin_frame_source_(new cc::SyntheticBeginFrameSource(
- task_runner,
- cc::BeginFrameArgs::DefaultInterval())),
+ synthetic_begin_frame_source_(begin_frame_source),
reflector_(nullptr) {
Initialize();
}
@@ -88,9 +84,6 @@ bool BrowserCompositorOutputSurface::BindToClient(
if (!OutputSurface::BindToClient(client))
return false;
- // Pass begin frame source up to Display to use for DisplayScheduler.
- client->SetBeginFrameSource(synthetic_begin_frame_source_.get());
-
// Don't want vsync notifications until there is a client.
if (!use_begin_frame_scheduling_)
vsync_manager_->AddObserver(this);
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.h b/chromium/content/browser/compositor/browser_compositor_output_surface.h
index e2dbb9b2f0c..f0e8fd31e65 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.h
@@ -9,12 +9,12 @@
#include "base/threading/non_thread_safe.h"
#include "build/build_config.h"
#include "cc/output/output_surface.h"
-#include "cc/scheduler/begin_frame_source.h"
#include "content/common/content_export.h"
#include "ui/compositor/compositor_vsync_manager.h"
namespace cc {
class SoftwareOutputDevice;
+class SyntheticBeginFrameSource;
}
namespace display_compositor {
@@ -74,16 +74,12 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
virtual void SetSurfaceSuspendedForRecycle(bool suspended) = 0;
#endif
- cc::SyntheticBeginFrameSource* begin_frame_source() {
- return synthetic_begin_frame_source_.get();
- }
-
protected:
// Constructor used by the accelerated implementation.
BrowserCompositorOutputSurface(
scoped_refptr<cc::ContextProvider> context,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
- base::SingleThreadTaskRunner* task_runner,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
overlay_candidate_validator);
@@ -91,16 +87,16 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
BrowserCompositorOutputSurface(
std::unique_ptr<cc::SoftwareOutputDevice> software_device,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- base::SingleThreadTaskRunner* task_runner);
+ cc::SyntheticBeginFrameSource* begin_frame_source);
// Constructor used by the Vulkan implementation.
BrowserCompositorOutputSurface(
const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- base::SingleThreadTaskRunner* task_runner);
+ cc::SyntheticBeginFrameSource* begin_frame_source);
scoped_refptr<ui::CompositorVSyncManager> vsync_manager_;
- std::unique_ptr<cc::SyntheticBeginFrameSource> synthetic_begin_frame_source_;
+ cc::SyntheticBeginFrameSource* synthetic_begin_frame_source_;
ReflectorImpl* reflector_;
// True when BeginFrame scheduling is enabled.
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 c3ab12dde70..84cee90f3ea 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -17,34 +17,24 @@
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
-#if defined(OS_MACOSX)
-#include "content/browser/gpu/gpu_surface_tracker.h"
-#include "gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.h"
-#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
-#endif
-
namespace content {
GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
scoped_refptr<ContextProviderCommandBuffer> context,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
- base::SingleThreadTaskRunner* task_runner,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
overlay_candidate_validator)
: BrowserCompositorOutputSurface(std::move(context),
std::move(vsync_manager),
- task_runner,
+ begin_frame_source,
std::move(overlay_candidate_validator)),
-#if defined(OS_MACOSX)
- should_show_frames_state_(SHOULD_SHOW_FRAMES),
-#endif
swap_buffers_completion_callback_(base::Bind(
&GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted,
base::Unretained(this))),
update_vsync_parameters_callback_(base::Bind(
&BrowserCompositorOutputSurface::OnUpdateVSyncParametersFromGpu,
- base::Unretained(this))) {
-}
+ base::Unretained(this))) {}
GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() {}
@@ -75,6 +65,11 @@ bool GpuBrowserCompositorOutputSurface::BindToClient(
return true;
}
+uint32_t GpuBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
+ auto* gl = static_cast<ContextProviderCommandBuffer*>(context_provider());
+ return gl->GetCopyTextureInternalFormat();
+}
+
void GpuBrowserCompositorOutputSurface::OnReflectorChanged() {
if (!reflector_) {
reflector_texture_.reset();
@@ -84,95 +79,45 @@ void GpuBrowserCompositorOutputSurface::OnReflectorChanged() {
}
}
-void GpuBrowserCompositorOutputSurface::SwapBuffers(
- cc::CompositorFrame* frame) {
- DCHECK(frame->gl_frame_data);
+void GpuBrowserCompositorOutputSurface::SwapBuffers(cc::CompositorFrame frame) {
+ DCHECK(frame.gl_frame_data);
- GetCommandBufferProxy()->SetLatencyInfo(frame->metadata.latency_info);
+ GetCommandBufferProxy()->SetLatencyInfo(frame.metadata.latency_info);
if (reflector_) {
- if (frame->gl_frame_data->sub_buffer_rect ==
- gfx::Rect(frame->gl_frame_data->size)) {
+ if (frame.gl_frame_data->sub_buffer_rect ==
+ gfx::Rect(frame.gl_frame_data->size)) {
reflector_texture_->CopyTextureFullImage(SurfaceSize());
reflector_->OnSourceSwapBuffers();
} else {
- const gfx::Rect& rect = frame->gl_frame_data->sub_buffer_rect;
+ const gfx::Rect& rect = frame.gl_frame_data->sub_buffer_rect;
reflector_texture_->CopyTextureSubImage(rect);
reflector_->OnSourcePostSubBuffer(rect);
}
}
- if (frame->gl_frame_data->sub_buffer_rect ==
- gfx::Rect(frame->gl_frame_data->size)) {
+ if (frame.gl_frame_data->sub_buffer_rect ==
+ gfx::Rect(frame.gl_frame_data->size)) {
context_provider_->ContextSupport()->Swap();
} else {
context_provider_->ContextSupport()->PartialSwapBuffers(
- frame->gl_frame_data->sub_buffer_rect);
+ frame.gl_frame_data->sub_buffer_rect);
}
client_->DidSwapBuffers();
-
-#if defined(OS_MACOSX)
- if (should_show_frames_state_ ==
- SHOULD_NOT_SHOW_FRAMES_NO_SWAP_AFTER_SUSPENDED) {
- should_show_frames_state_ = SHOULD_SHOW_FRAMES;
- }
-#endif
}
void GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
const std::vector<ui::LatencyInfo>& latency_info,
gfx::SwapResult result,
const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) {
-#if defined(OS_MACOSX)
- if (should_show_frames_state_ == SHOULD_SHOW_FRAMES) {
- gfx::AcceleratedWidget native_widget =
- content::GpuSurfaceTracker::Get()->AcquireNativeWidget(
- params_mac->surface_handle);
- ui::AcceleratedWidgetMacGotFrame(
- native_widget, params_mac->ca_context_id,
- params_mac->fullscreen_low_power_ca_context_valid,
- params_mac->fullscreen_low_power_ca_context_id, params_mac->io_surface,
- params_mac->pixel_size, params_mac->scale_factor, nullptr, nullptr);
- }
-#endif
RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
OnSwapBuffersComplete();
}
#if defined(OS_MACOSX)
void GpuBrowserCompositorOutputSurface::SetSurfaceSuspendedForRecycle(
- bool suspended) {
- if (suspended) {
- // It may be that there are frames in-flight from the GPU process back to
- // the browser. Make sure that these frames are not displayed by ignoring
- // them in GpuProcessHostUIShim, until the browser issues a SwapBuffers for
- // the new content.
- should_show_frames_state_ = SHOULD_NOT_SHOW_FRAMES_SUSPENDED;
- } else {
- // Discard the backbuffer before drawing the new frame. This is necessary
- // only when using a ImageTransportSurfaceFBO with a
- // CALayerStorageProvider. Discarding the backbuffer results in the next
- // frame using a new CALayer and CAContext, which guarantees that the
- // browser will not flash stale content when adding the remote CALayer to
- // the NSView hierarchy (it could flash stale content because the system
- // window server is not synchronized with any signals we control or
- // observe).
- if (should_show_frames_state_ == SHOULD_NOT_SHOW_FRAMES_SUSPENDED) {
- DiscardBackbuffer();
- should_show_frames_state_ =
- SHOULD_NOT_SHOW_FRAMES_NO_SWAP_AFTER_SUSPENDED;
- }
- }
-}
+ bool suspended) {}
#endif
-bool GpuBrowserCompositorOutputSurface::SurfaceIsSuspendForRecycle() const {
-#if defined(OS_MACOSX)
- return should_show_frames_state_ == SHOULD_NOT_SHOW_FRAMES_SUSPENDED;
-#else
- return false;
-#endif
-}
-
} // 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 542f294c2dd..5d2c7ed66e1 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -37,7 +37,7 @@ class GpuBrowserCompositorOutputSurface
GpuBrowserCompositorOutputSurface(
scoped_refptr<ContextProviderCommandBuffer> context,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
- base::SingleThreadTaskRunner* task_runner,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
overlay_candidate_validator);
@@ -50,28 +50,15 @@ class GpuBrowserCompositorOutputSurface
const std::vector<ui::LatencyInfo>& latency_info,
gfx::SwapResult result,
const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) override;
-
- // cc::OutputSurface implementation.
- void SwapBuffers(cc::CompositorFrame* frame) override;
- bool BindToClient(cc::OutputSurfaceClient* client) override;
- bool SurfaceIsSuspendForRecycle() const override;
-
#if defined(OS_MACOSX)
void SetSurfaceSuspendedForRecycle(bool suspended) override;
- enum ShouldShowFramesState {
- // Frames that come from the GPU process should appear on-screen.
- SHOULD_SHOW_FRAMES,
- // The compositor has been suspended. Any frames that come from the GPU
- // process are for the pre-suspend content and should not be displayed.
- SHOULD_NOT_SHOW_FRAMES_SUSPENDED,
- // The compositor has been un-suspended, but has not yet issued a swap
- // since being un-suspended, so any frames that come from the GPU process
- // are for pre-suspend content and should not be displayed.
- SHOULD_NOT_SHOW_FRAMES_NO_SWAP_AFTER_SUSPENDED,
- };
- ShouldShowFramesState should_show_frames_state_;
#endif
+ // cc::OutputSurface implementation.
+ void SwapBuffers(cc::CompositorFrame frame) override;
+ bool BindToClient(cc::OutputSurfaceClient* client) override;
+ uint32_t GetFramebufferCopyTextureFormat() override;
+
gpu::CommandBufferProxyImpl* GetCommandBufferProxy();
base::CancelableCallback<void(
diff --git a/chromium/content/browser/compositor/gpu_output_surface_mac.h b/chromium/content/browser/compositor/gpu_output_surface_mac.h
new file mode 100644
index 00000000000..74076cc6c65
--- /dev/null
+++ b/chromium/content/browser/compositor/gpu_output_surface_mac.h
@@ -0,0 +1,60 @@
+// 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_COMPOSITOR_GPU_OUTPUT_SURFACE_MAC_H_
+#define CONTENT_BROWSER_COMPOSITOR_GPU_OUTPUT_SURFACE_MAC_H_
+
+#include "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h"
+
+namespace content {
+
+class GpuOutputSurfaceMac
+ : public GpuSurfacelessBrowserCompositorOutputSurface {
+ public:
+ GpuOutputSurfaceMac(
+ scoped_refptr<ContextProviderCommandBuffer> context,
+ gpu::SurfaceHandle surface_handle,
+ scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
+ std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
+ overlay_candidate_validator,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
+ ~GpuOutputSurfaceMac() override;
+
+ // cc::OutputSurface implementation.
+ void SwapBuffers(cc::CompositorFrame frame) override;
+ bool SurfaceIsSuspendForRecycle() const override;
+
+ // BrowserCompositorOutputSurface implementation.
+ void OnGpuSwapBuffersCompleted(
+ const std::vector<ui::LatencyInfo>& latency_info,
+ gfx::SwapResult result,
+ const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) override;
+ void SetSurfaceSuspendedForRecycle(bool suspended) override;
+
+ private:
+ // Store remote layers in a separate structure, so that non-Objective-C files
+ // may include this header.
+ struct RemoteLayers;
+ std::unique_ptr<RemoteLayers> remote_layers_;
+
+ enum ShouldShowFramesState {
+ // Frames that come from the GPU process should appear on-screen.
+ SHOULD_SHOW_FRAMES,
+ // The compositor has been suspended. Any frames that come from the GPU
+ // process are for the pre-suspend content and should not be displayed.
+ SHOULD_NOT_SHOW_FRAMES_SUSPENDED,
+ // The compositor has been un-suspended, but has not yet issued a swap
+ // since being un-suspended, so any frames that come from the GPU process
+ // are for pre-suspend content and should not be displayed.
+ SHOULD_NOT_SHOW_FRAMES_NO_SWAP_AFTER_SUSPENDED,
+ };
+ ShouldShowFramesState should_show_frames_state_ = SHOULD_SHOW_FRAMES;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuOutputSurfaceMac);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COMPOSITOR_GPU_OUTPUT_SURFACE_MAC_H_
diff --git a/chromium/content/browser/compositor/gpu_output_surface_mac.mm b/chromium/content/browser/compositor/gpu_output_surface_mac.mm
new file mode 100644
index 00000000000..e7289062836
--- /dev/null
+++ b/chromium/content/browser/compositor/gpu_output_surface_mac.mm
@@ -0,0 +1,139 @@
+// 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/compositor/gpu_output_surface_mac.h"
+
+#include "cc/output/compositor_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"
+#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
+#include "ui/base/cocoa/remote_layer_api.h"
+#include "ui/gfx/mac/io_surface.h"
+
+namespace content {
+
+struct GpuOutputSurfaceMac::RemoteLayers {
+ void UpdateLayers(CAContextID content_ca_context_id,
+ CAContextID fullscreen_low_power_ca_context_id) {
+ if (content_ca_context_id) {
+ if ([content_layer contextId] != content_ca_context_id) {
+ content_layer.reset([[CALayerHost alloc] init]);
+ [content_layer setContextId:content_ca_context_id];
+ [content_layer
+ setAutoresizingMask:kCALayerMaxXMargin | kCALayerMaxYMargin];
+ }
+ } else {
+ content_layer.reset();
+ }
+
+ if (fullscreen_low_power_ca_context_id) {
+ if ([fullscreen_low_power_layer contextId] !=
+ fullscreen_low_power_ca_context_id) {
+ fullscreen_low_power_layer.reset([[CALayerHost alloc] init]);
+ [fullscreen_low_power_layer
+ setContextId:fullscreen_low_power_ca_context_id];
+ }
+ } else {
+ fullscreen_low_power_layer.reset();
+ }
+ }
+
+ base::scoped_nsobject<CALayerHost> content_layer;
+ base::scoped_nsobject<CALayerHost> fullscreen_low_power_layer;
+};
+
+GpuOutputSurfaceMac::GpuOutputSurfaceMac(
+ scoped_refptr<ContextProviderCommandBuffer> context,
+ gpu::SurfaceHandle surface_handle,
+ scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
+ std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
+ overlay_candidate_validator,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
+ : GpuSurfacelessBrowserCompositorOutputSurface(
+ std::move(context),
+ surface_handle,
+ std::move(vsync_manager),
+ begin_frame_source,
+ std::move(overlay_candidate_validator),
+ GL_TEXTURE_RECTANGLE_ARB,
+ GL_RGBA,
+ gpu_memory_buffer_manager),
+ remote_layers_(new RemoteLayers) {}
+
+GpuOutputSurfaceMac::~GpuOutputSurfaceMac() {}
+
+void GpuOutputSurfaceMac::SwapBuffers(cc::CompositorFrame frame) {
+ GpuSurfacelessBrowserCompositorOutputSurface::SwapBuffers(std::move(frame));
+
+ if (should_show_frames_state_ ==
+ SHOULD_NOT_SHOW_FRAMES_NO_SWAP_AFTER_SUSPENDED) {
+ should_show_frames_state_ = SHOULD_SHOW_FRAMES;
+ }
+}
+
+void GpuOutputSurfaceMac::OnGpuSwapBuffersCompleted(
+ const std::vector<ui::LatencyInfo>& latency_info,
+ gfx::SwapResult result,
+ const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) {
+ remote_layers_->UpdateLayers(params_mac->ca_context_id,
+ params_mac->fullscreen_low_power_ca_context_id);
+ if (should_show_frames_state_ == SHOULD_SHOW_FRAMES) {
+ ui::AcceleratedWidgetMac* widget = ui::AcceleratedWidgetMac::Get(
+ content::GpuSurfaceTracker::Get()->AcquireNativeWidget(
+ params_mac->surface_handle));
+ if (widget) {
+ if (remote_layers_->content_layer) {
+ widget->GotCALayerFrame(
+ base::scoped_nsobject<CALayer>(remote_layers_->content_layer.get(),
+ base::scoped_policy::RETAIN),
+ params_mac->fullscreen_low_power_ca_context_valid,
+ base::scoped_nsobject<CALayer>(
+ remote_layers_->fullscreen_low_power_layer.get(),
+ base::scoped_policy::RETAIN),
+ params_mac->pixel_size, params_mac->scale_factor);
+ } else {
+ widget->GotIOSurfaceFrame(params_mac->io_surface,
+ params_mac->pixel_size,
+ params_mac->scale_factor);
+ }
+ }
+ }
+ DidReceiveTextureInUseResponses(params_mac->responses);
+ GpuSurfacelessBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
+ latency_info, result, params_mac);
+}
+
+void GpuOutputSurfaceMac::SetSurfaceSuspendedForRecycle(bool suspended) {
+ if (suspended) {
+ // It may be that there are frames in-flight from the GPU process back to
+ // the browser. Make sure that these frames are not displayed by ignoring
+ // them in GpuProcessHostUIShim, until the browser issues a SwapBuffers for
+ // the new content.
+ should_show_frames_state_ = SHOULD_NOT_SHOW_FRAMES_SUSPENDED;
+ } else {
+ // Discard the backbuffer before drawing the new frame. This is necessary
+ // only when using a ImageTransportSurfaceFBO with a
+ // CALayerStorageProvider. Discarding the backbuffer results in the next
+ // frame using a new CALayer and CAContext, which guarantees that the
+ // browser will not flash stale content when adding the remote CALayer to
+ // the NSView hierarchy (it could flash stale content because the system
+ // window server is not synchronized with any signals we control or
+ // observe).
+ if (should_show_frames_state_ == SHOULD_NOT_SHOW_FRAMES_SUSPENDED) {
+ DiscardBackbuffer();
+ should_show_frames_state_ =
+ SHOULD_NOT_SHOW_FRAMES_NO_SWAP_AFTER_SUSPENDED;
+ }
+ }
+}
+
+bool GpuOutputSurfaceMac::SurfaceIsSuspendForRecycle() const {
+ return should_show_frames_state_ == SHOULD_NOT_SHOW_FRAMES_SUSPENDED;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index ea713fd1a5b..841fea0e2f6 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -20,10 +20,14 @@
#include "cc/base/histograms.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/output_surface.h"
+#include "cc/output/texture_mailbox_deleter.h"
#include "cc/output/vulkan_in_process_context_provider.h"
#include "cc/raster/single_thread_task_graph_runner.h"
#include "cc/raster/task_graph_runner.h"
-#include "cc/surfaces/onscreen_display_client.h"
+#include "cc/scheduler/begin_frame_source.h"
+#include "cc/scheduler/delay_based_time_source.h"
+#include "cc/surfaces/display.h"
+#include "cc/surfaces/display_scheduler.h"
#include "cc/surfaces/surface_display_output_surface.h"
#include "cc/surfaces/surface_manager.h"
#include "components/display_compositor/compositor_overlay_candidate_validator.h"
@@ -56,7 +60,7 @@
#include "ui/gfx/geometry/size.h"
#if defined(MOJO_RUNNER_CLIENT)
-#include "content/common/mojo/mojo_shell_connection_impl.h"
+#include "services/shell/runner/common/client_util.h"
#endif
#if defined(OS_WIN)
@@ -73,6 +77,7 @@
#include "content/browser/compositor/software_output_device_x11.h"
#elif defined(OS_MACOSX)
#include "components/display_compositor/compositor_overlay_candidate_validator_mac.h"
+#include "content/browser/compositor/gpu_output_surface_mac.h"
#include "content/browser/compositor/software_output_device_mac.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
@@ -132,9 +137,9 @@ scoped_refptr<content::ContextProviderCommandBuffer> CreateContextCommon(
GURL url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon");
return make_scoped_refptr(new content::ContextProviderCommandBuffer(
std::move(gpu_channel_host), gpu::GPU_STREAM_DEFAULT,
- gpu::GpuStreamPriority::NORMAL, surface_handle, url,
- gfx::PreferIntegratedGpu, automatic_flushes, support_locking,
- gpu::SharedMemoryLimits(), attributes, shared_context_provider, type));
+ gpu::GpuStreamPriority::NORMAL, surface_handle, url, automatic_flushes,
+ support_locking, gpu::SharedMemoryLimits(), attributes,
+ shared_context_provider, type));
}
#if defined(OS_MACOSX)
@@ -149,16 +154,12 @@ bool IsCALayersDisabledFromCommandLine() {
namespace content {
struct GpuProcessTransportFactory::PerCompositorData {
- gpu::SurfaceHandle surface_handle;
- BrowserCompositorOutputSurface* surface;
- ReflectorImpl* reflector;
- std::unique_ptr<cc::OnscreenDisplayClient> display_client;
+ gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
+ BrowserCompositorOutputSurface* display_output_surface = nullptr;
+ cc::SyntheticBeginFrameSource* begin_frame_source = nullptr;
+ ReflectorImpl* reflector = nullptr;
+ std::unique_ptr<cc::Display> display;
bool output_is_secure = false;
-
- PerCompositorData()
- : surface_handle(gpu::kNullSurfaceHandle),
- surface(nullptr),
- reflector(nullptr) {}
};
GpuProcessTransportFactory::GpuProcessTransportFactory()
@@ -189,7 +190,7 @@ std::unique_ptr<cc::SoftwareOutputDevice>
GpuProcessTransportFactory::CreateSoftwareOutputDevice(
ui::Compositor* compositor) {
#if defined(MOJO_RUNNER_CLIENT)
- if (IsRunningInMojoShell()) {
+ if (shell::ShellIsRemote()) {
return std::unique_ptr<cc::SoftwareOutputDevice>(
new SoftwareOutputDeviceMus(compositor));
}
@@ -254,7 +255,7 @@ static bool ShouldCreateGpuOutputSurface(ui::Compositor* compositor) {
#if defined(MOJO_RUNNER_CLIENT)
// Chrome running as a mojo app currently can only use software compositing.
// TODO(rjkroege): http://crbug.com/548451
- if (IsRunningInMojoShell()) {
+ if (shell::ShellIsRemote()) {
return false;
}
#endif
@@ -280,7 +281,10 @@ void GpuProcessTransportFactory::CreateOutputSurface(
if (!data) {
data = CreatePerCompositorData(compositor.get());
} else {
- data->surface = nullptr;
+ // TODO(danakj): We can destroy the |data->display| here when the compositor
+ // destroys its OutputSurface before calling back here.
+ data->display_output_surface = nullptr;
+ data->begin_frame_source = nullptr;
}
#if defined(OS_WIN)
@@ -422,7 +426,18 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
}
}
- std::unique_ptr<BrowserCompositorOutputSurface> surface;
+ std::unique_ptr<cc::SyntheticBeginFrameSource> begin_frame_source;
+ if (!compositor->GetRendererSettings().disable_display_vsync) {
+ begin_frame_source.reset(new cc::DelayBasedBeginFrameSource(
+ base::MakeUnique<cc::DelayBasedTimeSource>(
+ compositor->task_runner().get())));
+ } else {
+ begin_frame_source.reset(new cc::BackToBackBeginFrameSource(
+ base::MakeUnique<cc::DelayBasedTimeSource>(
+ compositor->task_runner().get())));
+ }
+
+ std::unique_ptr<BrowserCompositorOutputSurface> display_output_surface;
#if defined(ENABLE_VULKAN)
std::unique_ptr<VulkanBrowserCompositorOutputSurface> vulkan_surface;
if (vulkan_context_provider) {
@@ -433,38 +448,43 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
vulkan_surface->Destroy();
vulkan_surface.reset();
} else {
- surface = std::move(vulkan_surface);
+ display_output_surface = std::move(vulkan_surface);
}
}
#endif
- if (!surface) {
+ if (!display_output_surface) {
if (!create_gpu_output_surface) {
- surface = base::WrapUnique(new SoftwareBrowserCompositorOutputSurface(
- CreateSoftwareOutputDevice(compositor.get()),
- compositor->vsync_manager(), compositor->task_runner().get()));
+ display_output_surface =
+ base::WrapUnique(new SoftwareBrowserCompositorOutputSurface(
+ CreateSoftwareOutputDevice(compositor.get()),
+ compositor->vsync_manager(), begin_frame_source.get()));
} else {
DCHECK(context_provider);
const auto& capabilities = context_provider->ContextCapabilities();
if (data->surface_handle == gpu::kNullSurfaceHandle) {
- surface = base::WrapUnique(new OffscreenBrowserCompositorOutputSurface(
- context_provider, compositor->vsync_manager(),
- compositor->task_runner().get(),
- std::unique_ptr<
- display_compositor::CompositorOverlayCandidateValidator>()));
+ display_output_surface =
+ base::WrapUnique(new OffscreenBrowserCompositorOutputSurface(
+ context_provider, compositor->vsync_manager(),
+ begin_frame_source.get(),
+ std::unique_ptr<display_compositor::
+ CompositorOverlayCandidateValidator>()));
} else if (capabilities.surfaceless) {
- GLenum target = GL_TEXTURE_2D;
- GLenum format = GL_RGB;
#if defined(OS_MACOSX)
- target = GL_TEXTURE_RECTANGLE_ARB;
- format = GL_RGBA;
-#endif
- surface =
+ display_output_surface = base::WrapUnique(new GpuOutputSurfaceMac(
+ context_provider, data->surface_handle, compositor->vsync_manager(),
+ begin_frame_source.get(),
+ CreateOverlayCandidateValidator(compositor->widget()),
+ BrowserGpuMemoryBufferManager::current()));
+#else
+ display_output_surface =
base::WrapUnique(new GpuSurfacelessBrowserCompositorOutputSurface(
context_provider, data->surface_handle,
- compositor->vsync_manager(), compositor->task_runner().get(),
- CreateOverlayCandidateValidator(compositor->widget()), target,
- format, BrowserGpuMemoryBufferManager::current()));
+ compositor->vsync_manager(), begin_frame_source.get(),
+ CreateOverlayCandidateValidator(compositor->widget()),
+ GL_TEXTURE_2D, GL_RGB,
+ BrowserGpuMemoryBufferManager::current()));
+#endif
} else {
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
validator;
@@ -472,49 +492,55 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
// Overlays are only supported on surfaceless output surfaces on Mac.
validator = CreateOverlayCandidateValidator(compositor->widget());
#endif
- surface = base::WrapUnique(new GpuBrowserCompositorOutputSurface(
- context_provider, compositor->vsync_manager(),
- compositor->task_runner().get(), std::move(validator)));
+ display_output_surface =
+ base::WrapUnique(new GpuBrowserCompositorOutputSurface(
+ context_provider, compositor->vsync_manager(),
+ begin_frame_source.get(), std::move(validator)));
}
}
}
- data->surface = surface.get();
+ data->display_output_surface = display_output_surface.get();
+ data->begin_frame_source = begin_frame_source.get();
if (data->reflector)
- data->reflector->OnSourceSurfaceReady(data->surface);
+ data->reflector->OnSourceSurfaceReady(data->display_output_surface);
#if defined(OS_WIN)
gfx::RenderingWindowManager::GetInstance()->DoSetParentOnChild(
compositor->widget());
#endif
- // This gets a bit confusing. Here we have a ContextProvider in the |surface|
- // configured to render directly to this widget. We need to make an
- // OnscreenDisplayClient associated with that context, then return a
- // SurfaceDisplayOutputSurface set up to draw to the display's surface.
- cc::SurfaceManager* manager = surface_manager_.get();
- std::unique_ptr<cc::OnscreenDisplayClient> display_client(
- new cc::OnscreenDisplayClient(
- std::move(surface), manager, HostSharedBitmapManager::current(),
- BrowserGpuMemoryBufferManager::current(),
- compositor->GetRendererSettings(), compositor->task_runner(),
- compositor->surface_id_allocator()->id_namespace()));
-
- std::unique_ptr<cc::SurfaceDisplayOutputSurface> output_surface(
+ std::unique_ptr<cc::DisplayScheduler> scheduler(new cc::DisplayScheduler(
+ begin_frame_source.get(), compositor->task_runner().get(),
+ display_output_surface->capabilities().max_frames_pending));
+
+ // The Display owns and uses the |display_output_surface| created above.
+ data->display = base::MakeUnique<cc::Display>(
+ surface_manager_.get(), HostSharedBitmapManager::current(),
+ BrowserGpuMemoryBufferManager::current(),
+ compositor->GetRendererSettings(),
+ compositor->surface_id_allocator()->id_namespace(),
+ 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
+ // same ContextProvider as the Display's output surface.
+ std::unique_ptr<cc::SurfaceDisplayOutputSurface> delegated_output_surface(
vulkan_context_provider
? new cc::SurfaceDisplayOutputSurface(
- manager, compositor->surface_id_allocator(),
+ surface_manager_.get(), compositor->surface_id_allocator(),
+ data->display.get(),
static_cast<scoped_refptr<cc::VulkanContextProvider>>(
vulkan_context_provider))
: new cc::SurfaceDisplayOutputSurface(
- manager, compositor->surface_id_allocator(), context_provider,
+ surface_manager_.get(), compositor->surface_id_allocator(),
+ data->display.get(), context_provider,
shared_worker_context_provider_));
- display_client->set_surface_output_surface(output_surface.get());
- output_surface->set_display_client(display_client.get());
- display_client->display()->Resize(compositor->size());
- display_client->display()->SetOutputIsSecure(data->output_is_secure);
- data->display_client = std::move(display_client);
- compositor->SetOutputSurface(std::move(output_surface));
+ data->display->Resize(compositor->size());
+ data->display->SetOutputIsSecure(data->output_is_secure);
+ compositor->SetOutputSurface(std::move(delegated_output_surface));
}
std::unique_ptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector(
@@ -526,7 +552,7 @@ std::unique_ptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector(
std::unique_ptr<ReflectorImpl> reflector(
new ReflectorImpl(source_compositor, target_layer));
source_data->reflector = reflector.get();
- if (BrowserCompositorOutputSurface* source_surface = source_data->surface)
+ if (auto* source_surface = source_data->display_output_surface)
reflector->OnSourceSurfaceReady(source_surface);
return std::move(reflector);
}
@@ -563,8 +589,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(
- ImageTransportFactoryObserver, observer_list_, OnLostResources());
+ FOR_EACH_OBSERVER(ui::ContextFactoryObserver, observer_list_,
+ OnLostResources());
helper.reset();
DCHECK(!gl_helper_) << "Destroying the GLHelper should not cause a new "
@@ -617,8 +643,20 @@ void GpuProcessTransportFactory::ResizeDisplay(ui::Compositor* compositor,
return;
PerCompositorData* data = it->second;
DCHECK(data);
- if (data->display_client)
- data->display_client->display()->Resize(size);
+ if (data->display)
+ data->display->Resize(size);
+}
+
+void GpuProcessTransportFactory::SetDisplayColorSpace(
+ ui::Compositor* compositor,
+ const gfx::ColorSpace& color_space) {
+ PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ if (it == per_compositor_data_.end())
+ return;
+ PerCompositorData* data = it->second;
+ DCHECK(data);
+ if (data->display)
+ data->display->SetColorSpace(color_space);
}
void GpuProcessTransportFactory::SetAuthoritativeVSyncInterval(
@@ -629,10 +667,8 @@ void GpuProcessTransportFactory::SetAuthoritativeVSyncInterval(
return;
PerCompositorData* data = it->second;
DCHECK(data);
- if (data->surface) {
- data->surface->begin_frame_source()->SetAuthoritativeVSyncInterval(
- interval);
- }
+ if (data->begin_frame_source)
+ data->begin_frame_source->SetAuthoritativeVSyncInterval(interval);
}
void GpuProcessTransportFactory::SetOutputIsSecure(ui::Compositor* compositor,
@@ -643,8 +679,18 @@ void GpuProcessTransportFactory::SetOutputIsSecure(ui::Compositor* compositor,
PerCompositorData* data = it->second;
DCHECK(data);
data->output_is_secure = secure;
- if (data->display_client)
- data->display_client->display()->SetOutputIsSecure(secure);
+ if (data->display)
+ data->display->SetOutputIsSecure(secure);
+}
+
+void GpuProcessTransportFactory::AddObserver(
+ ui::ContextFactoryObserver* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void GpuProcessTransportFactory::RemoveObserver(
+ ui::ContextFactoryObserver* observer) {
+ observer_list_.RemoveObserver(observer);
}
cc::SurfaceManager* GpuProcessTransportFactory::GetSurfaceManager() {
@@ -662,16 +708,6 @@ display_compositor::GLHelper* GpuProcessTransportFactory::GetGLHelper() {
return gl_helper_.get();
}
-void GpuProcessTransportFactory::AddObserver(
- ImageTransportFactoryObserver* observer) {
- observer_list_.AddObserver(observer);
-}
-
-void GpuProcessTransportFactory::RemoveObserver(
- ImageTransportFactoryObserver* observer) {
- observer_list_.RemoveObserver(observer);
-}
-
#if defined(OS_MACOSX)
void GpuProcessTransportFactory::SetCompositorSuspendedForRecycle(
ui::Compositor* compositor,
@@ -681,8 +717,8 @@ void GpuProcessTransportFactory::SetCompositorSuspendedForRecycle(
return;
PerCompositorData* data = it->second;
DCHECK(data);
- if (data->surface)
- data->surface->SetSurfaceSuspendedForRecycle(suspended);
+ if (data->display_output_surface)
+ data->display_output_surface->SetSurfaceSuspendedForRecycle(suspended);
}
#endif
@@ -764,8 +800,7 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
std::unique_ptr<display_compositor::GLHelper> lost_gl_helper =
std::move(gl_helper_);
- FOR_EACH_OBSERVER(ImageTransportFactoryObserver,
- observer_list_,
+ FOR_EACH_OBSERVER(ui::ContextFactoryObserver, observer_list_,
OnLostResources());
// Kill things that use the shared context before killing the shared context.
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.h b/chromium/content/browser/compositor/gpu_process_transport_factory.h
index b465fa7673b..0cad2115420 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -64,16 +64,18 @@ class GpuProcessTransportFactory
std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() override;
void ResizeDisplay(ui::Compositor* compositor,
const gfx::Size& size) override;
+ void SetDisplayColorSpace(ui::Compositor* compositor,
+ const gfx::ColorSpace& color_space) override;
void SetAuthoritativeVSyncInterval(ui::Compositor* compositor,
base::TimeDelta interval) override;
void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override;
+ void AddObserver(ui::ContextFactoryObserver* observer) override;
+ void RemoveObserver(ui::ContextFactoryObserver* observer) override;
// ImageTransportFactory implementation.
ui::ContextFactory* GetContextFactory() override;
cc::SurfaceManager* GetSurfaceManager() override;
display_compositor::GLHelper* GetGLHelper() override;
- void AddObserver(ImageTransportFactoryObserver* observer) override;
- void RemoveObserver(ImageTransportFactoryObserver* observer) override;
#if defined(OS_MACOSX)
void SetCompositorSuspendedForRecycle(ui::Compositor* compositor,
bool suspended) override;
@@ -99,7 +101,7 @@ class GpuProcessTransportFactory
PerCompositorDataMap per_compositor_data_;
scoped_refptr<ContextProviderCommandBuffer> shared_main_thread_contexts_;
std::unique_ptr<display_compositor::GLHelper> gl_helper_;
- base::ObserverList<ImageTransportFactoryObserver> observer_list_;
+ base::ObserverList<ui::ContextFactoryObserver> observer_list_;
std::unique_ptr<cc::SurfaceManager> surface_manager_;
uint32_t next_surface_id_namespace_;
std::unique_ptr<cc::SingleThreadTaskGraphRunner> task_graph_runner_;
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 26db5a78d58..7ba712c4970 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
@@ -23,7 +23,7 @@ GpuSurfacelessBrowserCompositorOutputSurface::
scoped_refptr<ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
- base::SingleThreadTaskRunner* task_runner,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
overlay_candidate_validator,
unsigned int target,
@@ -31,7 +31,7 @@ GpuSurfacelessBrowserCompositorOutputSurface::
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
: GpuBrowserCompositorOutputSurface(std::move(context),
std::move(vsync_manager),
- task_runner,
+ begin_frame_source,
std::move(overlay_candidate_validator)),
internalformat_(internalformat),
gpu_memory_buffer_manager_(gpu_memory_buffer_manager) {
@@ -48,10 +48,10 @@ GpuSurfacelessBrowserCompositorOutputSurface::
gl_helper_.reset(new display_compositor::GLHelper(
context_provider_->ContextGL(), context_provider_->ContextSupport()));
- output_surface_.reset(new display_compositor::BufferQueue(
- context_provider_, target, internalformat_, gl_helper_.get(),
+ buffer_queue_.reset(new display_compositor::BufferQueue(
+ context_provider_->ContextGL(), target, internalformat_, gl_helper_.get(),
gpu_memory_buffer_manager_, surface_handle));
- output_surface_->Initialize();
+ buffer_queue_->Initialize();
}
GpuSurfacelessBrowserCompositorOutputSurface::
@@ -65,34 +65,43 @@ bool GpuSurfacelessBrowserCompositorOutputSurface::IsDisplayedAsOverlayPlane()
unsigned GpuSurfacelessBrowserCompositorOutputSurface::GetOverlayTextureId()
const {
- return output_surface_->current_texture_id();
+ return buffer_queue_->current_texture_id();
}
void GpuSurfacelessBrowserCompositorOutputSurface::SwapBuffers(
- cc::CompositorFrame* frame) {
- DCHECK(output_surface_);
- output_surface_->SwapBuffers(frame->gl_frame_data->sub_buffer_rect);
- GpuBrowserCompositorOutputSurface::SwapBuffers(frame);
+ cc::CompositorFrame frame) {
+ DCHECK(buffer_queue_);
+ buffer_queue_->SwapBuffers(frame.gl_frame_data->sub_buffer_rect);
+ GpuBrowserCompositorOutputSurface::SwapBuffers(std::move(frame));
}
void GpuSurfacelessBrowserCompositorOutputSurface::OnSwapBuffersComplete() {
- DCHECK(output_surface_);
- output_surface_->PageFlipComplete();
+ DCHECK(buffer_queue_);
+ buffer_queue_->PageFlipComplete();
GpuBrowserCompositorOutputSurface::OnSwapBuffersComplete();
}
void GpuSurfacelessBrowserCompositorOutputSurface::BindFramebuffer() {
- DCHECK(output_surface_);
- output_surface_->BindFramebuffer();
+ DCHECK(buffer_queue_);
+ buffer_queue_->BindFramebuffer();
+}
+
+GLenum GpuSurfacelessBrowserCompositorOutputSurface::
+ GetFramebufferCopyTextureFormat() {
+ return buffer_queue_->internal_format();
}
void GpuSurfacelessBrowserCompositorOutputSurface::Reshape(
const gfx::Size& size,
float scale_factor,
+ const gfx::ColorSpace& color_space,
bool alpha) {
- GpuBrowserCompositorOutputSurface::Reshape(size, scale_factor, alpha);
- DCHECK(output_surface_);
- output_surface_->Reshape(SurfaceSize(), scale_factor);
+ GpuBrowserCompositorOutputSurface::Reshape(size, scale_factor, color_space,
+ alpha);
+ DCHECK(buffer_queue_);
+ // TODO(ccameron): Plumb the color profile to the output GpuMemoryBuffer.
+ // https://crbug.com/622133
+ buffer_queue_->Reshape(SurfaceSize(), scale_factor);
}
void GpuSurfacelessBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
@@ -104,7 +113,7 @@ void GpuSurfacelessBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
// Even through the swap failed, this is a fixable error so we can pretend
// it succeeded to the rest of the system.
result = gfx::SwapResult::SWAP_ACK;
- output_surface_->RecreateBuffers();
+ buffer_queue_->RecreateBuffers();
force_swap = true;
}
GpuBrowserCompositorOutputSurface::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 a5233033c9e..d94b12695db 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
@@ -28,7 +28,7 @@ class GpuSurfacelessBrowserCompositorOutputSurface
scoped_refptr<ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
- base::SingleThreadTaskRunner* task_runner,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
overlay_candidate_validator,
unsigned int target,
@@ -36,12 +36,15 @@ class GpuSurfacelessBrowserCompositorOutputSurface
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
~GpuSurfacelessBrowserCompositorOutputSurface() override;
- private:
// cc::OutputSurface implementation.
- void SwapBuffers(cc::CompositorFrame* frame) override;
+ void SwapBuffers(cc::CompositorFrame frame) override;
void OnSwapBuffersComplete() override;
void BindFramebuffer() override;
- void Reshape(const gfx::Size& size, float scale_factor, bool alpha) override;
+ uint32_t GetFramebufferCopyTextureFormat() override;
+ void Reshape(const gfx::Size& size,
+ float scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool alpha) override;
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
@@ -51,9 +54,10 @@ class GpuSurfacelessBrowserCompositorOutputSurface
gfx::SwapResult result,
const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac) override;
- unsigned int internalformat_;
+ private:
+ const unsigned int internalformat_;
std::unique_ptr<display_compositor::GLHelper> gl_helper_;
- std::unique_ptr<display_compositor::BufferQueue> output_surface_;
+ std::unique_ptr<display_compositor::BufferQueue> buffer_queue_;
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
};
diff --git a/chromium/content/browser/compositor/image_transport_factory.cc b/chromium/content/browser/compositor/image_transport_factory.cc
index de8f0750d50..835748d63c5 100644
--- a/chromium/content/browser/compositor/image_transport_factory.cc
+++ b/chromium/content/browser/compositor/image_transport_factory.cc
@@ -15,7 +15,7 @@ namespace content {
namespace {
ImageTransportFactory* g_factory = NULL;
bool g_initialized_for_unit_tests = false;
-static gfx::DisableNullDrawGLBindings* g_disable_null_draw = NULL;
+static gl::DisableNullDrawGLBindings* g_disable_null_draw = NULL;
void SetFactory(ImageTransportFactory* factory) {
g_factory = factory;
@@ -40,7 +40,7 @@ void ImageTransportFactory::InitializeForUnitTests(
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnablePixelOutputInTests))
- g_disable_null_draw = new gfx::DisableNullDrawGLBindings;
+ g_disable_null_draw = new gl::DisableNullDrawGLBindings;
SetFactory(factory.release());
}
diff --git a/chromium/content/browser/compositor/image_transport_factory.h b/chromium/content/browser/compositor/image_transport_factory.h
index 984d6528847..376e2408775 100644
--- a/chromium/content/browser/compositor/image_transport_factory.h
+++ b/chromium/content/browser/compositor/image_transport_factory.h
@@ -28,6 +28,7 @@ enum class SwapResult;
namespace ui {
class Compositor;
class ContextFactory;
+class ContextFactoryObserver;
class Texture;
}
@@ -37,20 +38,6 @@ class GLHelper;
namespace content {
-// This class provides a way to get notified when surface handles get lost.
-class CONTENT_EXPORT ImageTransportFactoryObserver {
- public:
- virtual ~ImageTransportFactoryObserver() {}
-
- // Notifies that the surface handles generated by ImageTransportFactory were
- // lost.
- // When this is called, the old resources (e.g. shared context, GL helper)
- // still exist, but are about to be destroyed. Getting a reference to those
- // resources from the ImageTransportFactory (e.g. through GetGLHelper) will
- // return newly recreated, valid resources.
- virtual void OnLostResources() = 0;
-};
-
// This class provides the interface for creating the support for the
// cross-process image transport, both for creating the shared surface handle
// (destination surface for the GPU process) and the transport client (logic for
@@ -83,9 +70,6 @@ class CONTENT_EXPORT ImageTransportFactory {
// (ImageTransportFactoryObserver::OnLostResources is called).
virtual display_compositor::GLHelper* GetGLHelper() = 0;
- virtual void AddObserver(ImageTransportFactoryObserver* observer) = 0;
- virtual void RemoveObserver(ImageTransportFactoryObserver* observer) = 0;
-
#if defined(OS_MACOSX)
// Called with |suspended| as true when the ui::Compositor has been
// disconnected from an NSView and may be attached to another one. Called
diff --git a/chromium/content/browser/compositor/image_transport_factory_browsertest.cc b/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
index d92e172ec67..7d94b92cf40 100644
--- a/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
+++ b/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
@@ -20,7 +20,7 @@ namespace {
typedef ContentBrowserTest ImageTransportFactoryBrowserTest;
-class MockImageTransportFactoryObserver : public ImageTransportFactoryObserver {
+class MockContextFactoryObserver : public ui::ContextFactoryObserver {
public:
MOCK_METHOD0(OnLostResources, void());
};
@@ -46,8 +46,8 @@ IN_PROC_BROWSER_TEST_F(ImageTransportFactoryBrowserTest,
new OwnedMailbox(factory->GetGLHelper());
EXPECT_FALSE(mailbox->mailbox().IsZero());
- MockImageTransportFactoryObserver observer;
- factory->AddObserver(&observer);
+ MockContextFactoryObserver observer;
+ factory->GetContextFactory()->AddObserver(&observer);
base::RunLoop run_loop;
EXPECT_CALL(observer, OnLostResources())
@@ -66,7 +66,7 @@ IN_PROC_BROWSER_TEST_F(ImageTransportFactoryBrowserTest,
run_loop.Run();
EXPECT_TRUE(mailbox->mailbox().IsZero());
- factory->RemoveObserver(&observer);
+ factory->GetContextFactory()->RemoveObserver(&observer);
}
class ImageTransportFactoryTearDownBrowserTest : public ContentBrowserTest {
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 2e4fe4c7624..3b06fb0137d 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -30,16 +30,18 @@ using gpu::gles2::GLES2Interface;
namespace content {
+static cc::ResourceFormat kFboTextureFormat = cc::RGBA_8888;
+
OffscreenBrowserCompositorOutputSurface::
OffscreenBrowserCompositorOutputSurface(
scoped_refptr<ContextProviderCommandBuffer> context,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
- base::SingleThreadTaskRunner* task_runner,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
overlay_candidate_validator)
: BrowserCompositorOutputSurface(std::move(context),
std::move(vsync_manager),
- task_runner,
+ begin_frame_source,
std::move(overlay_candidate_validator)),
fbo_(0),
is_backbuffer_discarded_(false),
@@ -55,7 +57,7 @@ OffscreenBrowserCompositorOutputSurface::
void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() {
is_backbuffer_discarded_ = false;
- if (!reflector_texture_.get()) {
+ if (!reflector_texture_) {
reflector_texture_.reset(new ReflectorTexture(context_provider()));
GLES2Interface* gl = context_provider_->ContextGL();
@@ -65,15 +67,15 @@ void OffscreenBrowserCompositorOutputSurface::EnsureBackbuffer() {
int texture_width = std::min(max_texture_size, surface_size_.width());
int texture_height = std::min(max_texture_size, surface_size_.height());
- cc::ResourceFormat format = cc::RGBA_8888;
gl->BindTexture(GL_TEXTURE_2D, reflector_texture_->texture_id());
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format),
+ gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(kFboTextureFormat),
texture_width, texture_height, 0,
- GLDataFormat(format), GLDataType(format), nullptr);
+ GLDataFormat(kFboTextureFormat),
+ GLDataType(kFboTextureFormat), nullptr);
if (!fbo_)
gl->GenFramebuffers(1, &fbo_);
@@ -104,9 +106,11 @@ void OffscreenBrowserCompositorOutputSurface::DiscardBackbuffer() {
}
}
-void OffscreenBrowserCompositorOutputSurface::Reshape(const gfx::Size& size,
- float scale_factor,
- bool alpha) {
+void OffscreenBrowserCompositorOutputSurface::Reshape(
+ const gfx::Size& size,
+ float scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool alpha) {
if (size == surface_size_)
return;
@@ -127,14 +131,19 @@ void OffscreenBrowserCompositorOutputSurface::BindFramebuffer() {
}
}
+GLenum
+OffscreenBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
+ return GLCopyTextureInternalFormat(kFboTextureFormat);
+}
+
void OffscreenBrowserCompositorOutputSurface::SwapBuffers(
- cc::CompositorFrame* frame) {
+ cc::CompositorFrame frame) {
if (reflector_) {
- if (frame->gl_frame_data->sub_buffer_rect ==
- gfx::Rect(frame->gl_frame_data->size))
+ if (frame.gl_frame_data->sub_buffer_rect ==
+ gfx::Rect(frame.gl_frame_data->size))
reflector_->OnSourceSwapBuffers();
else
- reflector_->OnSourcePostSubBuffer(frame->gl_frame_data->sub_buffer_rect);
+ reflector_->OnSourcePostSubBuffer(frame.gl_frame_data->sub_buffer_rect);
}
client_->DidSwapBuffers();
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 3f753a86925..c5113228175 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
@@ -29,7 +29,7 @@ class OffscreenBrowserCompositorOutputSurface
OffscreenBrowserCompositorOutputSurface(
scoped_refptr<ContextProviderCommandBuffer> context,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
- base::SingleThreadTaskRunner* task_runner,
+ cc::SyntheticBeginFrameSource* begin_frame_source,
std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
overlay_candidate_validator);
@@ -39,9 +39,13 @@ class OffscreenBrowserCompositorOutputSurface
// cc::OutputSurface:
void EnsureBackbuffer() override;
void DiscardBackbuffer() override;
- void Reshape(const gfx::Size& size, float scale_factor, bool alpha) override;
+ void Reshape(const gfx::Size& size,
+ float scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool alpha) override;
void BindFramebuffer() override;
- void SwapBuffers(cc::CompositorFrame* frame) override;
+ uint32_t GetFramebufferCopyTextureFormat() override;
+ void SwapBuffers(cc::CompositorFrame frame) override;
// BrowserCompositorOutputSurface
void OnReflectorChanged() override;
diff --git a/chromium/content/browser/compositor/owned_mailbox.cc b/chromium/content/browser/compositor/owned_mailbox.cc
index b23d3c8d3f8..1729c38673c 100644
--- a/chromium/content/browser/compositor/owned_mailbox.cc
+++ b/chromium/content/browser/compositor/owned_mailbox.cc
@@ -14,7 +14,7 @@ OwnedMailbox::OwnedMailbox(display_compositor::GLHelper* gl_helper)
: texture_id_(0), gl_helper_(gl_helper) {
texture_id_ = gl_helper_->CreateTexture();
mailbox_holder_ = gl_helper_->ProduceMailboxHolderFromTexture(texture_id_);
- ImageTransportFactory::GetInstance()->AddObserver(this);
+ ImageTransportFactory::GetInstance()->GetContextFactory()->AddObserver(this);
}
OwnedMailbox::~OwnedMailbox() {
@@ -28,7 +28,8 @@ void OwnedMailbox::UpdateSyncToken(const gpu::SyncToken& sync_token) {
}
void OwnedMailbox::Destroy() {
- ImageTransportFactory::GetInstance()->RemoveObserver(this);
+ ImageTransportFactory::GetInstance()->GetContextFactory()->RemoveObserver(
+ this);
gl_helper_->WaitSyncToken(mailbox_holder_.sync_token);
gl_helper_->DeleteTexture(texture_id_);
texture_id_ = 0;
diff --git a/chromium/content/browser/compositor/owned_mailbox.h b/chromium/content/browser/compositor/owned_mailbox.h
index cbf1593111e..d0bd7b5d47c 100644
--- a/chromium/content/browser/compositor/owned_mailbox.h
+++ b/chromium/content/browser/compositor/owned_mailbox.h
@@ -11,6 +11,7 @@
#include "content/browser/compositor/image_transport_factory.h"
#include "content/common/content_export.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
+#include "ui/compositor/compositor.h"
namespace display_compositor {
class GLHelper;
@@ -23,7 +24,7 @@ namespace content {
// id when the object itself is destroyed. Should only be created if a GLHelper
// exists on the ImageTransportFactory.
class CONTENT_EXPORT OwnedMailbox : public base::RefCounted<OwnedMailbox>,
- public ImageTransportFactoryObserver {
+ public ui::ContextFactoryObserver {
public:
explicit OwnedMailbox(display_compositor::GLHelper* gl_helper);
diff --git a/chromium/content/browser/compositor/reflector_impl_unittest.cc b/chromium/content/browser/compositor/reflector_impl_unittest.cc
index 69557e1a0b5..0b7e22342ca 100644
--- a/chromium/content/browser/compositor/reflector_impl_unittest.cc
+++ b/chromium/content/browser/compositor/reflector_impl_unittest.cc
@@ -2,9 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
+#include "cc/output/compositor_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"
@@ -74,10 +78,10 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
public:
TestOutputSurface(scoped_refptr<cc::ContextProvider> context_provider,
scoped_refptr<ui::CompositorVSyncManager> vsync_manager,
- base::SingleThreadTaskRunner* task_runner)
+ cc::SyntheticBeginFrameSource* begin_frame_source)
: BrowserCompositorOutputSurface(std::move(context_provider),
std::move(vsync_manager),
- task_runner,
+ begin_frame_source,
CreateTestValidatorOzone()) {
surface_size_ = gfx::Size(256, 256);
device_scale_factor_ = 1.f;
@@ -85,7 +89,8 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
void SetFlip(bool flip) { capabilities_.flipped_output_surface = flip; }
- void SwapBuffers(cc::CompositorFrame* frame) override {}
+ void SwapBuffers(cc::CompositorFrame frame) override {}
+ uint32_t GetFramebufferCopyTextureFormat() override { return GL_RGB; }
void OnReflectorChanged() override {
if (!reflector_) {
@@ -127,12 +132,15 @@ class ReflectorImplTest : public testing::Test {
message_loop_.reset(new base::MessageLoop());
task_runner_ = message_loop_->task_runner();
compositor_task_runner_ = new FakeTaskRunner();
+ begin_frame_source_.reset(new cc::DelayBasedBeginFrameSource(
+ base::MakeUnique<cc::DelayBasedTimeSource>(
+ compositor_task_runner_.get())));
compositor_.reset(
new ui::Compositor(context_factory, compositor_task_runner_.get()));
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
- output_surface_ = std::unique_ptr<TestOutputSurface>(new TestOutputSurface(
+ output_surface_ = base::MakeUnique<TestOutputSurface>(
cc::TestContextProvider::Create(cc::TestWebGraphicsContext3D::Create()),
- compositor_->vsync_manager(), compositor_task_runner_.get()));
+ compositor_->vsync_manager(), begin_frame_source_.get());
CHECK(output_surface_->BindToClient(&output_surface_client_));
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
@@ -166,6 +174,7 @@ 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_;
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 23a7f7604f2..250a9ce4708 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -8,7 +8,6 @@
#include "base/location.h"
#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -24,10 +23,10 @@ namespace content {
SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface(
std::unique_ptr<cc::SoftwareOutputDevice> software_device,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- base::SingleThreadTaskRunner* task_runner)
+ cc::SyntheticBeginFrameSource* begin_frame_source)
: BrowserCompositorOutputSurface(std::move(software_device),
vsync_manager,
- task_runner),
+ begin_frame_source),
weak_factory_(this) {}
SoftwareBrowserCompositorOutputSurface::
@@ -35,9 +34,9 @@ SoftwareBrowserCompositorOutputSurface::
}
void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
- cc::CompositorFrame* frame) {
+ cc::CompositorFrame frame) {
base::TimeTicks swap_time = base::TimeTicks::Now();
- for (auto& latency : frame->metadata.latency_info) {
+ for (auto& latency : frame.metadata.latency_info) {
latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
latency.AddLatencyNumberWithTimestamp(
@@ -46,7 +45,7 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&RenderWidgetHostImpl::CompositorFrameDrawn,
- frame->metadata.latency_info));
+ frame.metadata.latency_info));
gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
if (vsync_provider) {
@@ -58,6 +57,18 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
client_->DidSwapBuffers();
}
+void SoftwareBrowserCompositorOutputSurface::BindFramebuffer() {
+ // Not used for software surfaces.
+ NOTREACHED();
+}
+
+GLenum
+SoftwareBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
+ // Not used for software surfaces.
+ NOTREACHED();
+ return 0;
+}
+
void SoftwareBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
const std::vector<ui::LatencyInfo>& latency_info,
gfx::SwapResult result,
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 44a508de0a8..4258afac08e 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
@@ -27,12 +27,17 @@ class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
SoftwareBrowserCompositorOutputSurface(
std::unique_ptr<cc::SoftwareOutputDevice> software_device,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- base::SingleThreadTaskRunner* task_runner);
+ cc::SyntheticBeginFrameSource* begin_frame_source);
~SoftwareBrowserCompositorOutputSurface() override;
+ // OutputSurface implementation.
+ void SwapBuffers(cc::CompositorFrame frame) override;
+ void BindFramebuffer() override;
+ uint32_t GetFramebufferCopyTextureFormat() override;
+
private:
- void SwapBuffers(cc::CompositorFrame* frame) override;
+ // BrowserCompositorOutputSurface implementation.
void OnGpuSwapBuffersCompleted(
const std::vector<ui::LatencyInfo>& latency_info,
gfx::SwapResult result,
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 d5b5276cec2..8a6fd7dcebd 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
@@ -7,8 +7,12 @@
#include <utility>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/test/test_message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cc/output/compositor_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 "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
@@ -60,8 +64,10 @@ class FakeSoftwareOutputDevice : public cc::SoftwareOutputDevice {
class SoftwareBrowserCompositorOutputSurfaceTest : public testing::Test {
public:
- SoftwareBrowserCompositorOutputSurfaceTest();
- ~SoftwareBrowserCompositorOutputSurfaceTest() override;
+ SoftwareBrowserCompositorOutputSurfaceTest()
+ : begin_frame_source_(base::MakeUnique<cc::DelayBasedTimeSource>(
+ message_loop_.task_runner().get())) {}
+ ~SoftwareBrowserCompositorOutputSurfaceTest() override = default;
void SetUp() override;
void TearDown() override;
@@ -72,29 +78,23 @@ class SoftwareBrowserCompositorOutputSurfaceTest : public testing::Test {
protected:
std::unique_ptr<content::BrowserCompositorOutputSurface> output_surface_;
- std::unique_ptr<base::MessageLoop> message_loop_;
+ // TODO(crbug.com/616973): We shouldn't be using ThreadTaskRunnerHandle::Get()
+ // inside the OutputSurface, so we shouldn't need a MessageLoop. The
+ // OutputSurface should be using the TaskRunner given to the compositor.
+ base::TestMessageLoop message_loop_;
+ cc::DelayBasedBeginFrameSource begin_frame_source_;
std::unique_ptr<ui::Compositor> compositor_;
DISALLOW_COPY_AND_ASSIGN(SoftwareBrowserCompositorOutputSurfaceTest);
};
-SoftwareBrowserCompositorOutputSurfaceTest::
- SoftwareBrowserCompositorOutputSurfaceTest() {
- // |message_loop_| is not used, but the main thread still has to exist for the
- // compositor to use.
- message_loop_.reset(new base::MessageLoopForUI);
-}
-
-SoftwareBrowserCompositorOutputSurfaceTest::
- ~SoftwareBrowserCompositorOutputSurfaceTest() {}
-
void SoftwareBrowserCompositorOutputSurfaceTest::SetUp() {
bool enable_pixel_output = false;
ui::ContextFactory* context_factory =
ui::InitializeContextFactoryForTests(enable_pixel_output);
compositor_.reset(
- new ui::Compositor(context_factory, base::ThreadTaskRunnerHandle::Get()));
+ new ui::Compositor(context_factory, message_loop_.task_runner().get()));
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
}
@@ -107,10 +107,8 @@ void SoftwareBrowserCompositorOutputSurfaceTest::TearDown() {
std::unique_ptr<content::BrowserCompositorOutputSurface>
SoftwareBrowserCompositorOutputSurfaceTest::CreateSurface(
std::unique_ptr<cc::SoftwareOutputDevice> device) {
- return std::unique_ptr<content::BrowserCompositorOutputSurface>(
- new content::SoftwareBrowserCompositorOutputSurface(
- std::move(device), compositor_->vsync_manager(),
- message_loop_->task_runner().get()));
+ return base::MakeUnique<content::SoftwareBrowserCompositorOutputSurface>(
+ std::move(device), compositor_->vsync_manager(), &begin_frame_source_);
}
TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) {
@@ -121,7 +119,7 @@ TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) {
CHECK(output_surface_->BindToClient(&output_surface_client));
cc::CompositorFrame frame;
- output_surface_->SwapBuffers(&frame);
+ output_surface_->SwapBuffers(std::move(frame));
EXPECT_EQ(1, output_surface_client.swap_count());
EXPECT_EQ(NULL, output_surface_->software_device()->GetVSyncProvider());
@@ -139,7 +137,7 @@ TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, VSyncProviderUpdates) {
EXPECT_EQ(0, vsync_provider->call_count());
cc::CompositorFrame frame;
- output_surface_->SwapBuffers(&frame);
+ output_surface_->SwapBuffers(std::move(frame));
EXPECT_EQ(1, output_surface_client.swap_count());
EXPECT_EQ(1, vsync_provider->call_count());
diff --git a/chromium/content/browser/compositor/software_output_device_mac.h b/chromium/content/browser/compositor/software_output_device_mac.h
index 84e09873597..e0a1b1f0c49 100644
--- a/chromium/content/browser/compositor/software_output_device_mac.h
+++ b/chromium/content/browser/compositor/software_output_device_mac.h
@@ -10,11 +10,12 @@
#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
#include "cc/output/software_output_device.h"
-#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/gfx/vsync_provider.h"
+class SkCanvas;
+
namespace gfx {
class Canvas;
}
diff --git a/chromium/content/browser/compositor/software_output_device_mac.mm b/chromium/content/browser/compositor/software_output_device_mac.mm
index da190699d03..099fd04d69a 100644
--- a/chromium/content/browser/compositor/software_output_device_mac.mm
+++ b/chromium/content/browser/compositor/software_output_device_mac.mm
@@ -4,14 +4,11 @@
#include "content/browser/compositor/software_output_device_mac.h"
-#import <Cocoa/Cocoa.h>
-#include <stddef.h>
-#include <stdint.h>
-
#include "base/mac/foundation_util.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/compositor/compositor.h"
+#include "ui/gfx/mac/io_surface.h"
#include "ui/gfx/skia_util.h"
namespace content {
@@ -86,15 +83,8 @@ bool SoftwareOutputDeviceMac::EnsureBuffersExist() {
for (int i = 0; i < 2; ++i) {
if (!io_surfaces_[i]) {
TRACE_EVENT0("browser", "IOSurfaceCreate");
- unsigned pixel_format = 'BGRA';
- unsigned bytes_per_element = 4;
- NSDictionary* options = @{
- static_cast<id>(kIOSurfaceWidth) : @(pixel_size_.width()),
- static_cast<id>(kIOSurfaceHeight) : @(pixel_size_.height()),
- static_cast<id>(kIOSurfacePixelFormat) : @(pixel_format),
- static_cast<id>(kIOSurfaceBytesPerElement) : @(bytes_per_element),
- };
- io_surfaces_[i].reset(IOSurfaceCreate(base::mac::NSToCFCast(options)));
+ io_surfaces_[i].reset(
+ gfx::CreateIOSurface(pixel_size_, gfx::BufferFormat::BGRA_8888));
}
if (!io_surfaces_[i]) {
DLOG(ERROR) << "Failed to allocate IOSurface";
@@ -140,15 +130,19 @@ void SoftwareOutputDeviceMac::EndPaint() {
if (io_result)
DLOG(ERROR) << "Failed to unlock IOSurface " << io_result;
}
-
canvas_.reset();
- base::TimeTicks vsync_timebase;
- base::TimeDelta vsync_interval;
- ui::AcceleratedWidgetMacGotFrame(
- compositor_->widget(), 0, false, 0, io_surfaces_[current_index_],
- pixel_size_, scale_factor_, &vsync_timebase, &vsync_interval);
- if (!update_vsync_callback_.is_null())
- update_vsync_callback_.Run(vsync_timebase, vsync_interval);
+
+ ui::AcceleratedWidgetMac* widget =
+ ui::AcceleratedWidgetMac::Get(compositor_->widget());
+ if (widget) {
+ widget->GotIOSurfaceFrame(io_surfaces_[current_index_], pixel_size_,
+ scale_factor_);
+ base::TimeTicks vsync_timebase;
+ base::TimeDelta vsync_interval;
+ widget->GetVSyncParameters(&vsync_timebase, &vsync_interval);
+ if (!update_vsync_callback_.is_null())
+ update_vsync_callback_.Run(vsync_timebase, vsync_interval);
+ }
current_index_ = !current_index_;
}
diff --git a/chromium/content/browser/compositor/surface_utils.cc b/chromium/content/browser/compositor/surface_utils.cc
index 9f79cb74b55..e0e49162781 100644
--- a/chromium/content/browser/compositor/surface_utils.cc
+++ b/chromium/content/browser/compositor/surface_utils.cc
@@ -172,6 +172,8 @@ cc::SurfaceManager* GetSurfaceManager() {
return CompositorImpl::GetSurfaceManager();
#else
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ if (factory == NULL)
+ return nullptr;
return factory->GetSurfaceManager();
#endif
}
diff --git a/chromium/content/browser/compositor/surface_utils.h b/chromium/content/browser/compositor/surface_utils.h
index 54f7a32fd33..92bfe5786d5 100644
--- a/chromium/content/browser/compositor/surface_utils.h
+++ b/chromium/content/browser/compositor/surface_utils.h
@@ -20,6 +20,7 @@ class SurfaceManager;
namespace content {
+CONTENT_EXPORT
std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator();
CONTENT_EXPORT
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 d933aad0d13..de0edfdf65f 100644
--- a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
@@ -13,8 +13,10 @@ namespace content {
VulkanBrowserCompositorOutputSurface::VulkanBrowserCompositorOutputSurface(
const scoped_refptr<cc::VulkanContextProvider>& context,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- base::SingleThreadTaskRunner* task_runner)
- : BrowserCompositorOutputSurface(context, vsync_manager, task_runner) {}
+ cc::SyntheticBeginFrameSource* begin_frame_source)
+ : BrowserCompositorOutputSurface(context,
+ vsync_manager,
+ begin_frame_source) {}
VulkanBrowserCompositorOutputSurface::~VulkanBrowserCompositorOutputSurface() {
Destroy();
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 8aaf97a0a51..ed53ac0b1b2 100644
--- a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
@@ -23,7 +23,7 @@ class VulkanBrowserCompositorOutputSurface
VulkanBrowserCompositorOutputSurface(
const scoped_refptr<cc::VulkanContextProvider>& context,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
- base::SingleThreadTaskRunner* task_runner);
+ cc::SyntheticBeginFrameSource* begin_frame_source);
~VulkanBrowserCompositorOutputSurface() override;
diff --git a/chromium/content/browser/cross_site_transfer_browsertest.cc b/chromium/content/browser/cross_site_transfer_browsertest.cc
index 658519c3451..38327b788ba 100644
--- a/chromium/content/browser/cross_site_transfer_browsertest.cc
+++ b/chromium/content/browser/cross_site_transfer_browsertest.cc
@@ -2,11 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
+
#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/browser/web_contents.h"
@@ -17,11 +24,13 @@
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "net/base/escape.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_status.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "url/gurl.h"
namespace content {
@@ -188,7 +197,7 @@ class CrossSiteTransferTest : public ContentBrowserTest {
else
script = base::StringPrintf("location.href = '%s'", url.spec().c_str());
TestNavigationObserver load_observer(shell()->web_contents(), 1);
- bool result = ExecuteScript(window->web_contents(), script);
+ bool result = ExecuteScript(window, script);
EXPECT_TRUE(result);
if (should_wait_for_navigation)
load_observer.Wait();
@@ -418,4 +427,71 @@ IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, NoLeakOnCrossSiteCancel) {
shell()->web_contents()->SetDelegate(old_delegate);
}
+// Test that verifies that a cross-process transfer retains ability to read
+// files encapsulated by HTTP POST body that is forwarded to the new renderer.
+// Invalid handling of this scenario has been suspected as the cause of at least
+// some of the renderer kills tracked in https://crbug.com/613260.
+IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, PostWithFileData) {
+ // Navigate to the page with form that posts via 307 redirection to
+ // |redirect_target_url| (cross-site from |form_url|). Using 307 (rather than
+ // 302) redirection is important to preserve the HTTP method and POST body.
+ GURL form_url(embedded_test_server()->GetURL(
+ "a.com", "/form_that_posts_cross_site.html"));
+ GURL redirect_target_url(embedded_test_server()->GetURL("x.com", "/echoall"));
+ EXPECT_TRUE(NavigateToURL(shell(), form_url));
+
+ // Prepare a file to upload.
+ base::ScopedTempDir temp_dir;
+ base::FilePath file_path;
+ std::string file_content("test-file-content");
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &file_path));
+ ASSERT_LT(
+ 0, base::WriteFile(file_path, file_content.data(), file_content.size()));
+
+ // Fill out the form to refer to the test file.
+ std::unique_ptr<FileChooserDelegate> delegate(
+ new FileChooserDelegate(file_path));
+ shell()->web_contents()->SetDelegate(delegate.get());
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "document.getElementById('file').click();"));
+ EXPECT_TRUE(delegate->file_chosen());
+
+ // Remember the old process id for a sanity check below.
+ int old_process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
+
+ // Submit the form.
+ TestNavigationObserver form_post_observer(shell()->web_contents(), 1);
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "document.getElementById('file-form').submit();"));
+ form_post_observer.Wait();
+
+ // Verify that we arrived at the expected, redirected location.
+ EXPECT_EQ(redirect_target_url,
+ shell()->web_contents()->GetLastCommittedURL());
+
+ // Verify that the test really verifies access of a *new* renderer process.
+ int new_process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
+ ASSERT_NE(new_process_id, old_process_id);
+
+ // MAIN VERIFICATION: Check if the new renderer process is able to read the
+ // file.
+ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
+ new_process_id, file_path));
+
+ // Verify that POST body got preserved by 307 redirect. This expectation
+ // comes from: https://tools.ietf.org/html/rfc7231#section-6.4.7
+ std::string actual_page_body;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell()->web_contents(),
+ "window.domAutomationController.send("
+ "document.getElementsByTagName('pre')[0].innerText);",
+ &actual_page_body));
+ EXPECT_THAT(actual_page_body, ::testing::HasSubstr(file_content));
+ EXPECT_THAT(actual_page_body,
+ ::testing::HasSubstr(file_path.BaseName().AsUTF8Unsafe()));
+ EXPECT_THAT(actual_page_body,
+ ::testing::HasSubstr("form-data; name=\"file\""));
+}
+
} // namespace content
diff --git a/chromium/content/browser/database_browsertest.cc b/chromium/content/browser/database_browsertest.cc
index e38e4173744..35160299b62 100644
--- a/chromium/content/browser/database_browsertest.cc
+++ b/chromium/content/browser/database_browsertest.cc
@@ -26,10 +26,7 @@ class DatabaseTest : public ContentBrowserTest {
const std::string& script,
const std::string& result) {
std::string data;
- ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell->web_contents(),
- script,
- &data));
+ ASSERT_TRUE(ExecuteScriptAndExtractString(shell, script, &data));
ASSERT_EQ(data, result);
}
@@ -63,10 +60,7 @@ class DatabaseTest : public ContentBrowserTest {
bool HasTable(Shell* shell) {
std::string data;
- CHECK(ExecuteScriptAndExtractString(
- shell->web_contents(),
- "getRecords()",
- &data));
+ CHECK(ExecuteScriptAndExtractString(shell, "getRecords()", &data));
return data != "getRecords error: [object SQLError]";
}
};
diff --git a/chromium/content/browser/databases_table_unittest.cc b/chromium/content/browser/databases_table_unittest.cc
index 9353ad45557..2d6ba259f86 100644
--- a/chromium/content/browser/databases_table_unittest.cc
+++ b/chromium/content/browser/databases_table_unittest.cc
@@ -9,7 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "sql/connection.h"
#include "sql/statement.h"
-#include "sql/test/scoped_error_ignorer.h"
+#include "sql/test/scoped_error_expecter.h"
#include "storage/browser/database/databases_table.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/sqlite/sqlite3.h"
@@ -38,13 +38,13 @@ TEST(DatabasesTableTest, TestIt) {
// Initialize the 'Databases' table.
sql::Connection db;
- sql::ScopedErrorIgnorer ignore_errors;
+ sql::test::ScopedErrorExpecter expecter;
// TODO(shess): Suppressing SQLITE_CONSTRAINT because the code
// expects that and handles the resulting error. Consider revising
// the code to use INSERT OR IGNORE (which would not throw
// SQLITE_CONSTRAINT) and then check ChangeCount() to see if any
// changes were made.
- ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
+ expecter.ExpectError(SQLITE_CONSTRAINT);
// Initialize the temp dir and the 'Databases' table.
EXPECT_TRUE(db.OpenInMemory());
@@ -148,7 +148,7 @@ TEST(DatabasesTableTest, TestIt) {
EXPECT_FALSE(databases_table.DeleteDatabaseDetails(
"unknown_origin", ASCIIToUTF16("unknown_database")));
- ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ ASSERT_TRUE(expecter.SawExpectedErrors());
}
} // namespace content
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 1999bab80d6..85afac4b30d 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h
@@ -45,11 +45,13 @@ class CONTENT_EXPORT DataFetcherSharedMemory
bool Start(ConsumerType consumer_type, void* buffer) override;
bool Stop(ConsumerType consumer_type) override;
-#if !defined(OS_ANDROID)
- DeviceMotionHardwareBuffer* motion_buffer_;
- DeviceOrientationHardwareBuffer* orientation_buffer_;
- DeviceOrientationHardwareBuffer* orientation_absolute_buffer_;
- DeviceLightHardwareBuffer* light_buffer_;
+#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
+#if !defined(OS_CHROMEOS)
+ DeviceMotionHardwareBuffer* motion_buffer_ = nullptr;
+ DeviceOrientationHardwareBuffer* orientation_buffer_ = nullptr;
+ DeviceLightHardwareBuffer* light_buffer_ = nullptr;
+#endif
+ DeviceOrientationHardwareBuffer* orientation_absolute_buffer_ = nullptr;
#endif
#if defined(OS_CHROMEOS)
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 ab32df0b21e..73ce50242ad 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
@@ -21,18 +21,33 @@ namespace {
class FakeDataFetcher : public DataFetcherSharedMemoryBase {
public:
FakeDataFetcher()
- : start_light_(false, false),
- start_motion_(false, false),
- start_orientation_(false, false),
- start_orientation_absolute_(false, false),
- stop_light_(false, false),
- stop_motion_(false, false),
- stop_orientation_(false, false),
- stop_orientation_absolute_(false, false),
- updated_light_(false, false),
- updated_motion_(false, false),
- updated_orientation_(false, false),
- updated_orientation_absolute_(false, false),
+ : start_light_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ start_motion_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ start_orientation_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ start_orientation_absolute_(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ stop_light_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ stop_motion_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ stop_orientation_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ stop_orientation_absolute_(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ updated_light_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ updated_motion_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ updated_orientation_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ updated_orientation_absolute_(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
light_buffer_(nullptr),
motion_buffer_(nullptr),
orientation_buffer_(nullptr),
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc
index 7287b702d70..492e523da64 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc
@@ -43,12 +43,7 @@ bool SetLightBuffer(content::DeviceLightHardwareBuffer* buffer,
namespace content {
-DataFetcherSharedMemory::DataFetcherSharedMemory()
- : motion_buffer_(nullptr),
- orientation_buffer_(nullptr),
- orientation_absolute_buffer_(nullptr),
- light_buffer_(nullptr) {
-}
+DataFetcherSharedMemory::DataFetcherSharedMemory() {}
DataFetcherSharedMemory::~DataFetcherSharedMemory() {
}
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc
index ec49b89bdec..ca39ca3111f 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc
@@ -260,12 +260,7 @@ class DataFetcherSharedMemory::SensorEventSinkLight
DISALLOW_COPY_AND_ASSIGN(SensorEventSinkLight);
};
-DataFetcherSharedMemory::DataFetcherSharedMemory()
- : motion_buffer_(nullptr),
- orientation_buffer_(nullptr),
- orientation_absolute_buffer_(nullptr),
- light_buffer_(nullptr) {
-}
+DataFetcherSharedMemory::DataFetcherSharedMemory() {}
DataFetcherSharedMemory::~DataFetcherSharedMemory() {
}
diff --git a/chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc b/chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc
index b5d09c5739d..27c1a72fe76 100644
--- a/chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc
+++ b/chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc
@@ -28,12 +28,18 @@ namespace {
class FakeDataFetcher : public DataFetcherSharedMemory {
public:
FakeDataFetcher()
- : started_orientation_(false, false),
- stopped_orientation_(false, false),
- started_motion_(false, false),
- stopped_motion_(false, false),
- started_light_(false, false),
- stopped_light_(false, false),
+ : 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() override {}
@@ -179,7 +185,10 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
class DeviceInertialSensorBrowserTest : public ContentBrowserTest {
public:
DeviceInertialSensorBrowserTest()
- : fetcher_(nullptr), io_loop_finished_event_(false, false) {}
+ : fetcher_(nullptr),
+ io_loop_finished_event_(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED) {}
void SetUpOnMainThread() override {
BrowserThread::PostTask(
diff --git a/chromium/content/browser/devtools/BUILD.gn b/chromium/content/browser/devtools/BUILD.gn
index 595f94ffce3..da789a4a217 100644
--- a/chromium/content/browser/devtools/BUILD.gn
+++ b/chromium/content/browser/devtools/BUILD.gn
@@ -36,11 +36,13 @@ grit("devtools_resources") {
action("gen_devtools_protocol_handler") {
visibility = [ "//content/browser" ]
-
+ deps = [
+ "//third_party/WebKit/Source/core/inspector:protocol_version",
+ ]
script = "//content/browser/devtools/protocol/" +
"devtools_protocol_handler_generator.py"
- blink_protocol = "//third_party/WebKit/Source/devtools/protocol.json"
+ blink_protocol = "$root_gen_dir/blink/core/inspector/protocol.json"
browser_protocol = "browser_protocol.json"
inputs = [
blink_protocol,
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.cc b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
index dbc28a60092..0e2835072f6 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "content/browser/devtools/devtools_protocol_handler.h"
+#include "content/browser/devtools/protocol/browser_handler.h"
#include "content/browser/devtools/protocol/io_handler.h"
#include "content/browser/devtools/protocol/memory_handler.h"
#include "content/browser/devtools/protocol/system_info_handler.h"
@@ -24,7 +25,8 @@ scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::CreateForBrowser(
BrowserDevToolsAgentHost::BrowserDevToolsAgentHost(
scoped_refptr<base::SingleThreadTaskRunner> tethering_task_runner,
const CreateServerSocketCallback& socket_callback)
- : io_handler_(new devtools::io::IOHandler(GetIOContext())),
+ : browser_handler_(new devtools::browser::BrowserHandler()),
+ io_handler_(new devtools::io::IOHandler(GetIOContext())),
memory_handler_(new devtools::memory::MemoryHandler()),
system_info_handler_(new devtools::system_info::SystemInfoHandler()),
tethering_handler_(
@@ -36,6 +38,7 @@ BrowserDevToolsAgentHost::BrowserDevToolsAgentHost(
GetIOContext())),
protocol_handler_(new DevToolsProtocolHandler(this)) {
DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher();
+ dispatcher->SetBrowserHandler(browser_handler_.get());
dispatcher->SetIOHandler(io_handler_.get());
dispatcher->SetMemoryHandler(memory_handler_.get());
dispatcher->SetSystemInfoHandler(system_info_handler_.get());
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.h b/chromium/content/browser/devtools/browser_devtools_agent_host.h
index 8f9bf63a653..524322ef48e 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.h
@@ -12,6 +12,7 @@ namespace content {
class DevToolsProtocolHandler;
namespace devtools {
+namespace browser { class BrowserHandler; }
namespace io { class IOHandler; }
namespace memory { class MemoryHandler; }
namespace system_info { class SystemInfoHandler; }
@@ -39,6 +40,7 @@ class BrowserDevToolsAgentHost : public DevToolsAgentHostImpl {
bool Close() override;
bool DispatchProtocolMessage(const std::string& message) override;
+ std::unique_ptr<devtools::browser::BrowserHandler> browser_handler_;
std::unique_ptr<devtools::io::IOHandler> io_handler_;
std::unique_ptr<devtools::memory::MemoryHandler> memory_handler_;
std::unique_ptr<devtools::system_info::SystemInfoHandler>
diff --git a/chromium/content/browser/devtools/devtools.gyp b/chromium/content/browser/devtools/devtools.gyp
index 9aaaf25b9cd..33c99b1e0a8 100644
--- a/chromium/content/browser/devtools/devtools.gyp
+++ b/chromium/content/browser/devtools/devtools.gyp
@@ -7,11 +7,14 @@
{
'target_name': 'devtools_protocol_handler',
'type': 'none',
+ 'dependencies': [
+ '../../../third_party/WebKit/Source/core/inspector/inspector.gyp:protocol_version'
+ ],
'actions': [
{
'action_name': 'devtools_protocol_handler',
'variables': {
- 'blink_protocol': '../../../third_party/WebKit/Source/devtools/protocol.json',
+ 'blink_protocol': '<(SHARED_INTERMEDIATE_DIR)/blink/core/inspector/protocol.json',
'browser_protocol': 'browser_protocol.json',
'generator': 'protocol/devtools_protocol_handler_generator.py',
'output_cc': '<(SHARED_INTERMEDIATE_DIR)/content/browser/devtools/protocol/devtools_protocol_dispatcher.cc',
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index 033f2f18bd9..df95b806e24 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -102,7 +102,11 @@ scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::Create(
return new ForwardingAgentHost(delegate);
}
-void DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
+bool DevToolsAgentHostImpl::InnerAttach(DevToolsAgentHostClient* client,
+ bool force) {
+ if (client_ && !force)
+ return false;
+
scoped_refptr<DevToolsAgentHostImpl> protect(this);
++session_id_;
if (client_) {
@@ -111,15 +115,33 @@ void DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
}
client_ = client;
Attach();
+ return true;
}
-void DevToolsAgentHostImpl::DetachClient() {
- if (!client_)
- return;
+bool DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
+ return InnerAttach(client, false);
+}
+
+void DevToolsAgentHostImpl::ForceAttachClient(DevToolsAgentHostClient* client) {
+ InnerAttach(client, true);
+}
+
+bool DevToolsAgentHostImpl::DetachClient(DevToolsAgentHostClient* client) {
+ if (!client_ || client_ != client)
+ return false;
scoped_refptr<DevToolsAgentHostImpl> protect(this);
client_ = NULL;
InnerDetach();
+ return true;
+}
+
+bool DevToolsAgentHostImpl::DispatchProtocolMessage(
+ DevToolsAgentHostClient* client,
+ const std::string& message) {
+ if (!client_ || client_ != client)
+ return false;
+ return DispatchProtocolMessage(message);
}
void DevToolsAgentHostImpl::InnerDetach() {
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.h b/chromium/content/browser/devtools/devtools_agent_host_impl.h
index f70ebc5fc97..ddd2917e4b5 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.h
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.h
@@ -38,8 +38,12 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost,
bool Inspect(BrowserContext* browser_context);
// DevToolsAgentHost implementation.
- void AttachClient(DevToolsAgentHostClient* client) override;
- void DetachClient() override;
+ bool AttachClient(DevToolsAgentHostClient* client) override;
+ void ForceAttachClient(DevToolsAgentHostClient* client) override;
+ bool DetachClient(DevToolsAgentHostClient* client) override;
+ bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
+ const std::string& message) override;
+
bool IsAttached() override;
void InspectElement(int x, int y) override;
std::string GetId() override;
@@ -57,6 +61,8 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost,
DevToolsAgentHostImpl();
~DevToolsAgentHostImpl() override;
+ virtual bool DispatchProtocolMessage(const std::string& message) = 0;
+
void HostClosed();
void SendMessageToClient(int session_id, const std::string& message);
devtools::DevToolsIOContext* GetIOContext() { return &io_context_; }
@@ -67,6 +73,7 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost,
private:
friend class DevToolsAgentHost; // for static methods
+ bool InnerAttach(DevToolsAgentHostClient* client, bool force);
void InnerDetach();
const std::string id_;
diff --git a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
index 8d4696fcc53..67cb09c074c 100644
--- a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
+++ b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
@@ -142,7 +142,8 @@ void DevToolsFrameTraceRecorder::OnSynchronousSwapCompositorFrame(
TRACE_EVENT_IS_NEW_TRACE(&is_new_trace);
if (!is_new_trace && last_metadata_)
CaptureFrame(host, *last_metadata_);
- last_metadata_.reset(new cc::CompositorFrameMetadata(frame_metadata));
+ last_metadata_.reset(new cc::CompositorFrameMetadata);
+ *last_metadata_ = frame_metadata.Clone();
}
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_manager_unittest.cc b/chromium/content/browser/devtools/devtools_manager_unittest.cc
index 3aee809d927..b181bbcbad7 100644
--- a/chromium/content/browser/devtools/devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_manager_unittest.cc
@@ -44,7 +44,7 @@ class TestDevToolsClientHost : public DevToolsAgentHostClient {
void Close() {
EXPECT_FALSE(closed_);
close_counter++;
- agent_host_->DetachClient();
+ agent_host_->DetachClient(this);
closed_ = true;
}
@@ -144,7 +144,8 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
// Start with a short timeout.
inspected_rvh->GetWidget()->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(10));
+ TimeDelta::FromMilliseconds(10),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
@@ -156,7 +157,8 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
client_host.Close();
// Start with a short timeout.
inspected_rvh->GetWidget()->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(10));
+ TimeDelta::FromMilliseconds(10),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
@@ -247,9 +249,9 @@ TEST_F(DevToolsManagerTest, TestExternalProxy) {
TestDevToolsClientHost client_host;
client_host.InspectAgentHost(agent_host.get());
- agent_host->DispatchProtocolMessage("message1");
- agent_host->DispatchProtocolMessage("message2");
- agent_host->DispatchProtocolMessage("message2");
+ agent_host->DispatchProtocolMessage(&client_host, "message1");
+ agent_host->DispatchProtocolMessage(&client_host, "message2");
+ agent_host->DispatchProtocolMessage(&client_host, "message2");
client_host.Close();
}
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.cc b/chromium/content/browser/devtools/protocol/browser_handler.cc
new file mode 100644
index 00000000000..ac575f616ea
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/browser_handler.cc
@@ -0,0 +1,104 @@
+// 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"
+
+namespace content {
+namespace devtools {
+namespace browser {
+
+namespace {
+const char kTargetTypeWebContents[] = "web_contents";
+const char kTargetTypeFrame[] = "frame";
+const char kTargetTypeSharedWorker[] = "shared_worker";
+const char kTargetTypeServiceWorker[] = "service_worker";
+const char kTargetTypeServiceOther[] = "other";
+}
+
+using Response = DevToolsProtocolClient::Response;
+
+BrowserHandler::BrowserHandler() {
+}
+
+BrowserHandler::~BrowserHandler() {
+}
+
+void BrowserHandler::SetClient(std::unique_ptr<Client> client) {
+ client_.swap(client);
+}
+
+static std::string GetTypeString(DevToolsAgentHost* agent_host) {
+ switch (agent_host->GetType()) {
+ case DevToolsAgentHost::TYPE_WEB_CONTENTS:
+ return kTargetTypeWebContents;
+ case DevToolsAgentHost::TYPE_FRAME:
+ return kTargetTypeFrame;
+ case DevToolsAgentHost::TYPE_SHARED_WORKER:
+ return kTargetTypeSharedWorker;
+ case DevToolsAgentHost::TYPE_SERVICE_WORKER:
+ return kTargetTypeServiceWorker;
+ default:
+ return kTargetTypeServiceOther;
+ }
+}
+
+Response BrowserHandler::GetTargets(TargetInfos* infos) {
+ DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll();
+ for (DevToolsAgentHost::List::iterator it = agents.begin();
+ it != agents.end(); ++it) {
+ DevToolsAgentHost* agent_host = (*it).get();
+ scoped_refptr<devtools::browser::TargetInfo> info =
+ devtools::browser::TargetInfo::Create()->
+ set_target_id(agent_host->GetId())->
+ set_type(GetTypeString(agent_host))->
+ set_title(agent_host->GetTitle())->
+ set_url(agent_host->GetURL().spec());
+ }
+ return Response::OK();
+}
+
+Response BrowserHandler::Attach(const std::string& targetId) {
+ scoped_refptr<DevToolsAgentHost> agent_host =
+ DevToolsAgentHost::GetForId(targetId);
+ if (!agent_host)
+ return Response::ServerError("No target with given id found");
+ bool success = agent_host->AttachClient(this);
+ return success ? Response::OK() :
+ Response::ServerError("Target is already being debugged");
+}
+
+Response BrowserHandler::Detach(const std::string& targetId) {
+ scoped_refptr<DevToolsAgentHost> agent_host =
+ DevToolsAgentHost::GetForId(targetId);
+ if (!agent_host)
+ return Response::ServerError("No target with given id found");
+ bool success = agent_host->DetachClient(this);
+ return success ? Response::OK() :
+ Response::ServerError("Target is not being debugged");
+}
+
+Response BrowserHandler::SendMessage(const std::string& targetId,
+ const std::string& message) {
+ scoped_refptr<DevToolsAgentHost> agent_host =
+ DevToolsAgentHost::GetForId(targetId);
+ if (!agent_host)
+ return Response::ServerError("No target with given id found");
+ agent_host->DispatchProtocolMessage(this, message);
+ 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) {
+}
+
+} // 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
new file mode 100644
index 00000000000..d4135bc1625
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/browser_handler.h
@@ -0,0 +1,56 @@
+// 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 "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);
+
+ using TargetInfos = std::vector<scoped_refptr<devtools::browser::TargetInfo>>;
+ Response GetTargets(TargetInfos* infos);
+ Response Attach(const std::string& targetId);
+ Response Detach(const std::string& targetId);
+ Response SendMessage(const std::string& targetId, const std::string& message);
+
+ private:
+ void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+ const std::string& message) override;
+
+ void AgentHostClosed(DevToolsAgentHost* agent_host,
+ bool replaced_with_another_client) override;
+
+ std::unique_ptr<Client> client_;
+ 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/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 0a243395c5f..1a7e764be65 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -122,7 +122,7 @@ class DevToolsProtocolTest : public ContentBrowserTest,
std::string json_command;
base::JSONWriter::Write(command, &json_command);
- agent_host_->DispatchProtocolMessage(json_command);
+ agent_host_->DispatchProtocolMessage(this, json_command);
// Some messages are dispatched synchronously.
// Only run loop if we are not finished yet.
if (in_dispatch_ && wait) {
@@ -164,7 +164,7 @@ class DevToolsProtocolTest : public ContentBrowserTest,
void TearDownOnMainThread() override {
if (agent_host_) {
- agent_host_->DetachClient();
+ agent_host_->DetachClient(this);
agent_host_ = nullptr;
}
}
@@ -315,13 +315,12 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizePinchGesture) {
int old_width;
ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(window.innerWidth)", &old_width));
+ shell(), "domAutomationController.send(window.innerWidth)", &old_width));
int old_height;
ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(window.innerHeight)", &old_height));
+ shell(), "domAutomationController.send(window.innerHeight)",
+ &old_height));
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
params->SetInteger("x", old_width / 2);
@@ -331,14 +330,13 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizePinchGesture) {
int new_width;
ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(window.innerWidth)", &new_width));
+ shell(), "domAutomationController.send(window.innerWidth)", &new_width));
ASSERT_DOUBLE_EQ(2.0, static_cast<double>(old_width) / new_width);
int new_height;
ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(window.innerHeight)", &new_height));
+ shell(), "domAutomationController.send(window.innerHeight)",
+ &new_height));
ASSERT_DOUBLE_EQ(2.0, static_cast<double>(old_height) / new_height);
}
@@ -349,8 +347,8 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizeScrollGesture) {
int scroll_top;
ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(document.body.scrollTop)", &scroll_top));
+ shell(), "domAutomationController.send(document.body.scrollTop)",
+ &scroll_top));
ASSERT_EQ(0, scroll_top);
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
@@ -361,8 +359,8 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizeScrollGesture) {
SendCommand("Input.synthesizeScrollGesture", std::move(params));
ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(document.body.scrollTop)", &scroll_top));
+ shell(), "domAutomationController.send(document.body.scrollTop)",
+ &scroll_top));
ASSERT_EQ(100, scroll_top);
}
@@ -373,8 +371,8 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizeTapGesture) {
int scroll_top;
ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(document.body.scrollTop)", &scroll_top));
+ shell(), "domAutomationController.send(document.body.scrollTop)",
+ &scroll_top));
ASSERT_EQ(0, scroll_top);
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
@@ -388,8 +386,8 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizeTapGesture) {
// of the device that we're testing on, but in any case it should be greater
// than 0.
ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(document.body.scrollTop)", &scroll_top));
+ shell(), "domAutomationController.send(document.body.scrollTop)",
+ &scroll_top));
ASSERT_GT(scroll_top, 0);
}
#endif // defined(OS_ANDROID)
@@ -469,7 +467,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CrossSitePauseInBeforeUnload) {
SendCommand("Debugger.enable", nullptr);
ASSERT_TRUE(content::ExecuteScript(
- shell()->web_contents(),
+ shell(),
"window.onbeforeunload = function() { debugger; return null; }"));
shell()->LoadURL(
@@ -490,8 +488,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, InspectDuringFrameSwap) {
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url1, 1);
ShellAddedObserver new_shell_observer;
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.open('about:blank','foo');"));
+ EXPECT_TRUE(ExecuteScript(shell(), "window.open('about:blank','foo');"));
Shell* new_shell = new_shell_observer.GetShell();
EXPECT_TRUE(new_shell->web_contents()->HasOpener());
@@ -514,7 +511,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, InspectDuringFrameSwap) {
// should be fixed to support waiting on both WATCH_FOR_PROCESS_EXIT and
// WATCH_FOR_HOST_DESTRUCTION, and then used here.
bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(shell()->web_contents(),
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(shell(),
"window.domAutomationController.send("
" !!window.open('', 'foo'));",
&success));
@@ -529,7 +526,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, InspectDuringFrameSwap) {
// Ensure that the A.com process is still alive by executing a script in the
// original tab.
success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(shell()->web_contents(),
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(shell(),
"window.domAutomationController.send("
" !!window.open('', 'foo'));",
&success));
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 fc1893ec6a0..f9cb63cea09 100755
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
@@ -20,7 +20,7 @@ header = """\
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// Generated by
// content/public/browser/devtools_protocol_handler_generator.py from
-// third_party/WebKit/Source/devtools/protocol.json and
+// gen/blink/core/inspector/protocol.json and
// content/browser/devtools/browser_protocol.json
"""
diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc
index 48e901af732..7e45f1b343a 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.cc
+++ b/chromium/content/browser/devtools/protocol/input_handler.cc
@@ -6,9 +6,9 @@
#include <stddef.h>
-#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "cc/output/compositor_frame_metadata.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -431,7 +431,7 @@ void InputHandler::OnScrollFinished(
}
if (repeat_count > 0) {
- base::MessageLoop::current()->task_runner()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::Bind(&InputHandler::SynthesizeRepeatingScroll,
weak_factory_.GetWeakPtr(), gesture_params, repeat_count - 1,
diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc
index 46e07045336..ae9a58d7ce8 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.cc
+++ b/chromium/content/browser/devtools/protocol/network_handler.cc
@@ -289,10 +289,12 @@ Response NetworkHandler::CanEmulateNetworkConditions(bool* result) {
return Response::OK();
}
-Response NetworkHandler::EmulateNetworkConditions(bool offline,
- double latency,
- double download_throughput,
- double upload_throughput) {
+Response NetworkHandler::EmulateNetworkConditions(
+ bool offline,
+ double latency,
+ double download_throughput,
+ double upload_throughput,
+ const std::string* connection_type) {
return Response::FallThrough();
}
diff --git a/chromium/content/browser/devtools/protocol/network_handler.h b/chromium/content/browser/devtools/protocol/network_handler.h
index 9e1c1fc6703..d3270628aaf 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.h
+++ b/chromium/content/browser/devtools/protocol/network_handler.h
@@ -38,7 +38,8 @@ class NetworkHandler {
Response EmulateNetworkConditions(bool offline,
double latency,
double download_throughput,
- double upload_throughput);
+ double upload_throughput,
+ const std::string* connection_type);
Response GetCertificateDetails(int certificate_id,
scoped_refptr<CertificateDetails>* result);
Response ShowCertificateViewer(int certificate_id);
diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc
index d472554b9e3..d5a9244dc95 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.cc
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -145,8 +145,8 @@ void PageHandler::Detached() {
}
void PageHandler::OnSwapCompositorFrame(
- const cc::CompositorFrameMetadata& frame_metadata) {
- last_compositor_frame_metadata_ = frame_metadata;
+ cc::CompositorFrameMetadata frame_metadata) {
+ last_compositor_frame_metadata_ = std::move(frame_metadata);
has_compositor_frame_metadata_ = true;
if (screencast_enabled_)
@@ -155,10 +155,15 @@ void PageHandler::OnSwapCompositorFrame(
}
void PageHandler::OnSynchronousSwapCompositorFrame(
- const cc::CompositorFrameMetadata& frame_metadata) {
- last_compositor_frame_metadata_ = has_compositor_frame_metadata_ ?
- next_compositor_frame_metadata_ : frame_metadata;
- next_compositor_frame_metadata_ = frame_metadata;
+ cc::CompositorFrameMetadata frame_metadata) {
+ if (has_compositor_frame_metadata_) {
+ last_compositor_frame_metadata_ =
+ std::move(next_compositor_frame_metadata_);
+ } else {
+ last_compositor_frame_metadata_ = frame_metadata.Clone();
+ }
+ next_compositor_frame_metadata_ = std::move(frame_metadata);
+
has_compositor_frame_metadata_ = true;
if (screencast_enabled_)
@@ -425,20 +430,18 @@ void PageHandler::InnerSwapCompositorFrame() {
if (snapshot_size_dip.width() > 0 && snapshot_size_dip.height() > 0) {
gfx::Rect viewport_bounds_dip(gfx::ToRoundedSize(viewport_size_dip));
view->CopyFromCompositingSurface(
- viewport_bounds_dip,
- snapshot_size_dip,
+ viewport_bounds_dip, snapshot_size_dip,
base::Bind(&PageHandler::ScreencastFrameCaptured,
weak_factory_.GetWeakPtr(),
- last_compositor_frame_metadata_),
+ base::Passed(last_compositor_frame_metadata_.Clone())),
kN32_SkColorType);
frames_in_flight_++;
}
}
-void PageHandler::ScreencastFrameCaptured(
- const cc::CompositorFrameMetadata& metadata,
- const SkBitmap& bitmap,
- ReadbackResponse response) {
+void PageHandler::ScreencastFrameCaptured(cc::CompositorFrameMetadata metadata,
+ const SkBitmap& bitmap,
+ ReadbackResponse response) {
if (response != READBACK_SUCCESS) {
if (capture_retry_count_) {
--capture_retry_count_;
@@ -451,18 +454,17 @@ void PageHandler::ScreencastFrameCaptured(
return;
}
base::PostTaskAndReplyWithResult(
- base::WorkerPool::GetTaskRunner(true).get(),
- FROM_HERE,
- base::Bind(&EncodeScreencastFrame,
- bitmap, screencast_format_, screencast_quality_),
+ base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE,
+ base::Bind(&EncodeScreencastFrame, bitmap, screencast_format_,
+ screencast_quality_),
base::Bind(&PageHandler::ScreencastFrameEncoded,
- weak_factory_.GetWeakPtr(), metadata, base::Time::Now()));
+ weak_factory_.GetWeakPtr(), base::Passed(&metadata),
+ base::Time::Now()));
}
-void PageHandler::ScreencastFrameEncoded(
- const cc::CompositorFrameMetadata& metadata,
- const base::Time& timestamp,
- const std::string& data) {
+void PageHandler::ScreencastFrameEncoded(cc::CompositorFrameMetadata metadata,
+ const base::Time& timestamp,
+ const std::string& data) {
// Consider metadata empty in case it has no device scale factor.
if (metadata.device_scale_factor == 0 || !host_ || data.empty()) {
--frames_in_flight_;
diff --git a/chromium/content/browser/devtools/protocol/page_handler.h b/chromium/content/browser/devtools/protocol/page_handler.h
index 6dbca0a58b4..d6eb3a556b9 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.h
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -39,9 +39,9 @@ class PageHandler : public NotificationObserver {
void SetRenderFrameHost(RenderFrameHostImpl* host);
void SetClient(std::unique_ptr<Client> client);
void Detached();
- void OnSwapCompositorFrame(const cc::CompositorFrameMetadata& frame_metadata);
- void OnSynchronousSwapCompositorFrame(const cc::CompositorFrameMetadata&
- frame_metadata);
+ void OnSwapCompositorFrame(cc::CompositorFrameMetadata frame_metadata);
+ void OnSynchronousSwapCompositorFrame(
+ cc::CompositorFrameMetadata frame_metadata);
void DidAttachInterstitialPage();
void DidDetachInterstitialPage();
bool screencast_enabled() const { return enabled_ && screencast_enabled_; }
@@ -83,10 +83,10 @@ class PageHandler : public NotificationObserver {
WebContentsImpl* GetWebContents();
void NotifyScreencastVisibility(bool visible);
void InnerSwapCompositorFrame();
- void ScreencastFrameCaptured(const cc::CompositorFrameMetadata& metadata,
+ void ScreencastFrameCaptured(cc::CompositorFrameMetadata metadata,
const SkBitmap& bitmap,
ReadbackResponse response);
- void ScreencastFrameEncoded(const cc::CompositorFrameMetadata& metadata,
+ void ScreencastFrameEncoded(cc::CompositorFrameMetadata metadata,
const base::Time& timestamp,
const std::string& data);
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.cc b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
index a3034a2a88a..b9f528fdd5b 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
@@ -8,14 +8,18 @@
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/background_sync/background_sync_context.h"
+#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_watcher.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/browser/storage_partition_impl_map.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -46,21 +50,28 @@ using ScopeAgentsMap =
void ResultNoOp(bool success) {
}
+
void StatusNoOp(ServiceWorkerStatusCode status) {
}
+
+void StatusNoOpKeepingRegistration(
+ scoped_refptr<content::ServiceWorkerRegistration> protect,
+ ServiceWorkerStatusCode status) {
+}
+
void PushDeliveryNoOp(PushDeliveryStatus status) {
}
const std::string GetVersionRunningStatusString(
- content::ServiceWorkerVersion::RunningStatus running_status) {
+ EmbeddedWorkerStatus running_status) {
switch (running_status) {
- case content::ServiceWorkerVersion::STOPPED:
+ case EmbeddedWorkerStatus::STOPPED:
return kServiceWorkerVersionRunningStatusStopped;
- case content::ServiceWorkerVersion::STARTING:
+ case EmbeddedWorkerStatus::STARTING:
return kServiceWorkerVersionRunningStatusStarting;
- case content::ServiceWorkerVersion::RUNNING:
+ case EmbeddedWorkerStatus::RUNNING:
return kServiceWorkerVersionRunningStatusRunning;
- case content::ServiceWorkerVersion::STOPPING:
+ case EmbeddedWorkerStatus::STOPPING:
return kServiceWorkerVersionRunningStatusStopping;
}
return std::string();
@@ -253,6 +264,36 @@ const std::string GetDevToolsAgentHostTypeString(
return std::string();
}
+void DidFindRegistrationForDispatchSyncEventOnIO(
+ scoped_refptr<BackgroundSyncContext> sync_context,
+ const std::string& tag,
+ bool last_chance,
+ ServiceWorkerStatusCode status,
+ const scoped_refptr<content::ServiceWorkerRegistration>& registration) {
+ if (status != SERVICE_WORKER_OK || !registration->active_version())
+ return;
+ BackgroundSyncManager* background_sync_manager =
+ sync_context->background_sync_manager();
+ scoped_refptr<content::ServiceWorkerVersion> version(
+ registration->active_version());
+ // Keep the registration while dispatching the sync event.
+ background_sync_manager->EmulateDispatchSyncEvent(
+ tag, std::move(version), last_chance,
+ base::Bind(&StatusNoOpKeepingRegistration, registration));
+}
+
+void DispatchSyncEventOnIO(scoped_refptr<ServiceWorkerContextWrapper> context,
+ scoped_refptr<BackgroundSyncContext> sync_context,
+ const GURL& origin,
+ int64_t registration_id,
+ const std::string& tag,
+ bool last_chance) {
+ context->FindReadyRegistrationForId(
+ registration_id, origin,
+ base::Bind(&DidFindRegistrationForDispatchSyncEventOnIO, sync_context,
+ tag, last_chance));
+}
+
} // namespace
ServiceWorkerHandler::ServiceWorkerHandler()
@@ -347,7 +388,7 @@ Response ServiceWorkerHandler::Disable() {
ServiceWorkerDevToolsManager::GetInstance()->RemoveObserver(this);
ClearForceUpdate();
for (const auto& pair : attached_hosts_)
- pair.second->DetachClient();
+ pair.second->DetachClient(this);
attached_hosts_.clear();
DCHECK(context_watcher_);
context_watcher_->Stop();
@@ -469,6 +510,32 @@ Response ServiceWorkerHandler::DeliverPushMessage(
return Response::OK();
}
+Response ServiceWorkerHandler::DispatchSyncEvent(
+ const std::string& origin,
+ const std::string& registration_id,
+ const std::string& tag,
+ bool last_chance) {
+ if (!enabled_)
+ return Response::OK();
+ if (!render_frame_host_)
+ return CreateContextErrorResponse();
+ int64_t id = 0;
+ if (!base::StringToInt64(registration_id, &id))
+ return CreateInvalidVersionIdErrorResponse();
+
+ StoragePartitionImpl* partition =
+ static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
+ render_frame_host_->GetProcess()->GetBrowserContext(),
+ render_frame_host_->GetSiteInstance()));
+ BackgroundSyncContext* sync_context = partition->GetBackgroundSyncContext();
+
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&DispatchSyncEventOnIO, context_,
+ make_scoped_refptr(sync_context),
+ GURL(origin), id, tag, last_chance));
+ return Response::OK();
+}
+
Response ServiceWorkerHandler::GetTargetInfo(
const std::string& target_id,
scoped_refptr<TargetInfo>* target_info) {
@@ -618,7 +685,7 @@ void ServiceWorkerHandler::ReportWorkerTerminated(
auto it = attached_hosts_.find(host->GetId());
if (it == attached_hosts_.end())
return;
- host->DetachClient();
+ host->DetachClient(this);
client_->WorkerTerminated(WorkerTerminatedParams::Create()->
set_worker_id(host->GetId()));
attached_hosts_.erase(it);
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.h b/chromium/content/browser/devtools/protocol/service_worker_handler.h
index cf875370d52..ac7d460cafb 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.h
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.h
@@ -62,6 +62,10 @@ class ServiceWorkerHandler : public DevToolsAgentHostClient,
Response DeliverPushMessage(const std::string& origin,
const std::string& registration_id,
const std::string& data);
+ Response DispatchSyncEvent(const std::string& origin,
+ const std::string& registration_id,
+ const std::string& tag,
+ bool last_chance);
Response GetTargetInfo(const std::string& target_id,
scoped_refptr<TargetInfo>* target_info);
Response ActivateTarget(const std::string& target_id);
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc
index 59cbfc9e0a1..12f9c1899e8 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc
@@ -17,7 +17,7 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event_impl.h"
#include "base/trace_event/tracing_agent.h"
-#include "components/tracing/trace_config_file.h"
+#include "components/tracing/browser/trace_config_file.h"
#include "content/browser/devtools/devtools_io_context.h"
#include "content/browser/tracing/tracing_controller_impl.h"
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
index 85b01d883ab..6b1f7a9c3f8 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
@@ -25,6 +25,7 @@ const char kCustomTraceConfigString[] =
"\"disabled-by-default-cc\","
"\"disabled-by-default-memory-infra\"],"
"\"memory_dump_config\":{"
+ "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"],"
"\"triggers\":["
"{\"mode\":\"light\",\"periodic_interval_ms\":50},"
"{\"mode\":\"detailed\",\"periodic_interval_ms\":1000}"
@@ -45,6 +46,7 @@ const char kCustomTraceConfigStringDevToolsStyle[] =
"\"disabled-by-default-cc\","
"\"disabled-by-default-memory-infra\"],"
"\"memoryDumpConfig\":{"
+ "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"],"
"\"triggers\":["
"{\"mode\":\"light\",\"periodicIntervalMs\":50},"
"{\"mode\":\"detailed\",\"periodicIntervalMs\":1000}"
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 f2aaf547399..6646dcdbf47 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -4,6 +4,7 @@
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include <tuple>
#include <utility>
#include "base/lazy_instance.h"
@@ -12,6 +13,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/devtools_frame_trace_recorder.h"
#include "content/browser/devtools/devtools_protocol_handler.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"
@@ -38,8 +40,8 @@
#include "content/public/common/browser_side_navigation_policy.h"
#if defined(OS_ANDROID)
-#include "content/browser/power_save_blocker_impl.h"
#include "content/public/browser/render_widget_host_view.h"
+#include "device/power_save_blocker/power_save_blocker.h"
#endif
namespace content {
@@ -345,7 +347,8 @@ void RenderFrameDevToolsAgentHost::OnBeforeNavigation(
RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
RenderFrameHostImpl* host)
- : dom_handler_(new devtools::dom::DOMHandler()),
+ : browser_handler_(new devtools::browser::BrowserHandler()),
+ dom_handler_(new devtools::dom::DOMHandler()),
input_handler_(new devtools::input::InputHandler()),
inspector_handler_(new devtools::inspector::InspectorHandler()),
io_handler_(new devtools::io::IOHandler(GetIOContext())),
@@ -366,6 +369,7 @@ 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());
@@ -496,11 +500,17 @@ void RenderFrameDevToolsAgentHost::OnClientAttached() {
frame_trace_recorder_.reset(new DevToolsFrameTraceRecorder());
#if defined(OS_ANDROID)
- power_save_blocker_.reset(static_cast<PowerSaveBlockerImpl*>(
- PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
- PowerSaveBlocker::kReasonOther, "DevTools").release()));
- power_save_blocker_->InitDisplaySleepBlocker(web_contents());
+ power_save_blocker_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ device::PowerSaveBlocker::kReasonOther, "DevTools",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
+ if (web_contents()->GetNativeView()) {
+ view_weak_factory_.reset(new base::WeakPtrFactory<ui::ViewAndroid>(
+ web_contents()->GetNativeView()));
+ power_save_blocker_->InitDisplaySleepBlocker(
+ view_weak_factory_->GetWeakPtr());
+ }
#endif
// TODO(kaznacheev): Move this call back to DevToolsManager when
@@ -747,6 +757,12 @@ void RenderFrameDevToolsAgentHost::DidFailProvisionalLoad(
DiscardPending();
}
+void RenderFrameDevToolsAgentHost::WebContentsDestroyed() {
+#if defined(OS_ANDROID)
+ view_weak_factory_.reset();
+#endif
+}
+
void RenderFrameDevToolsAgentHost::
DispatchBufferedProtocolMessagesIfNecessary() {
if (navigating_handles_.empty() &&
@@ -852,20 +868,20 @@ void RenderFrameDevToolsAgentHost::OnSwapCompositorFrame(
if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
return;
if (page_handler_)
- page_handler_->OnSwapCompositorFrame(base::get<1>(param).metadata);
+ page_handler_->OnSwapCompositorFrame(
+ std::move(std::get<1>(param).metadata));
if (input_handler_)
- input_handler_->OnSwapCompositorFrame(base::get<1>(param).metadata);
+ input_handler_->OnSwapCompositorFrame(std::get<1>(param).metadata);
if (frame_trace_recorder_ && tracing_handler_->did_initiate_recording()) {
frame_trace_recorder_->OnSwapCompositorFrame(
- current_ ? current_->host() : nullptr,
- base::get<1>(param).metadata);
+ current_ ? current_->host() : nullptr, std::get<1>(param).metadata);
}
}
void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame(
- const cc::CompositorFrameMetadata& frame_metadata) {
+ cc::CompositorFrameMetadata frame_metadata) {
if (page_handler_)
- page_handler_->OnSynchronousSwapCompositorFrame(frame_metadata);
+ page_handler_->OnSynchronousSwapCompositorFrame(std::move(frame_metadata));
if (input_handler_)
input_handler_->OnSwapCompositorFrame(frame_metadata);
if (frame_trace_recorder_ && tracing_handler_->did_initiate_recording()) {
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 e6cc44024d0..e9ae1483b9e 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -15,10 +15,20 @@
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
+#if defined(OS_ANDROID)
+#include "ui/android/view_android.h"
+#endif // OS_ANDROID
+
namespace cc {
class CompositorFrameMetadata;
}
+#if defined(OS_ANDROID)
+namespace device {
+class PowerSaveBlocker;
+} // namespace device
+#endif
+
namespace content {
class BrowserContext;
@@ -28,11 +38,8 @@ class FrameTreeNode;
class NavigationHandle;
class RenderFrameHostImpl;
-#if defined(OS_ANDROID)
-class PowerSaveBlockerImpl;
-#endif
-
namespace devtools {
+namespace browser { class BrowserHandler; }
namespace dom { class DOMHandler; }
namespace emulation { class EmulationHandler; }
namespace input { class InputHandler; }
@@ -59,7 +66,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
static void OnBeforeNavigation(NavigationHandle* navigation_handle);
void SynchronousSwapCompositorFrame(
- const cc::CompositorFrameMetadata& frame_metadata);
+ cc::CompositorFrameMetadata frame_metadata);
bool HasRenderFrameHost(RenderFrameHost* host);
@@ -116,6 +123,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
int error_code,
const base::string16& error_description,
bool was_ignored_by_handler) override;
+ void WebContentsDestroyed() override;
void AboutToNavigateRenderFrame(RenderFrameHost* old_host,
RenderFrameHost* new_host);
@@ -149,6 +157,7 @@ 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_;
@@ -164,7 +173,8 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
std::unique_ptr<devtools::emulation::EmulationHandler> emulation_handler_;
std::unique_ptr<DevToolsFrameTraceRecorder> frame_trace_recorder_;
#if defined(OS_ANDROID)
- std::unique_ptr<PowerSaveBlockerImpl> power_save_blocker_;
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<base::WeakPtrFactory<ui::ViewAndroid>> view_weak_factory_;
#endif
std::unique_ptr<DevToolsProtocolHandler> protocol_handler_;
bool current_frame_crashed_;
diff --git a/chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc b/chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc
index c9c299e8e4d..c441256c7cf 100644
--- a/chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc
@@ -34,7 +34,7 @@ class TestDevToolsClientHost : public DevToolsAgentHostClient {
void InspectAgentHost(DevToolsAgentHost* agent_host) {
if (agent_host_.get())
- agent_host_->DetachClient();
+ agent_host_->DetachClient(this);
agent_host_ = agent_host;
if (agent_host_.get())
agent_host_->AttachClient(this);
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 e3c3cf222bc..1cd0052fa69 100644
--- a/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
+++ b/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
@@ -110,9 +110,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest,
// Send message to parent and child frames and get result back.
char message[] = "{\"id\": 0, \"method\": \"incorrect.method\"}";
- child_host->DispatchProtocolMessage(message);
+ child_host->DispatchProtocolMessage(&child_client, message);
child_client.WaitForReply();
- parent_host->DispatchProtocolMessage(message);
+ parent_host->DispatchProtocolMessage(&parent_client, message);
parent_client.WaitForReply();
// Load back same-site page into iframe.
@@ -123,10 +123,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest,
EXPECT_EQ(DevToolsAgentHost::TYPE_WEB_CONTENTS, list[0]->GetType());
EXPECT_EQ(main_url.spec(), list[0]->GetURL().spec());
EXPECT_TRUE(child_client.closed());
- child_host->DetachClient();
+ child_host->DetachClient(&child_client);
child_host = nullptr;
EXPECT_FALSE(parent_client.closed());
- parent_host->DetachClient();
+ parent_host->DetachClient(&parent_client);
parent_host = nullptr;
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_area.cc b/chromium/content/browser/dom_storage/dom_storage_area.cc
index 26e984b0b2b..81c2be745d6 100644
--- a/chromium/content/browser/dom_storage/dom_storage_area.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_area.cc
@@ -4,6 +4,8 @@
#include "content/browser/dom_storage/dom_storage_area.h"
+#include <inttypes.h>
+
#include <algorithm>
#include <cctype> // for std::isalnum
@@ -338,8 +340,7 @@ void DOMStorageArea::Shutdown() {
void DOMStorageArea::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd) {
DCHECK(task_runner_->IsRunningOnPrimarySequence());
- // Do not trace if usage is very low.
- if (map_->bytes_used() < 1024)
+ if (!is_initial_import_done_)
return;
// Limit the url length to 50 and strip special characters.
@@ -348,17 +349,33 @@ void DOMStorageArea::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd) {
if (!std::isalnum(url[index]))
url[index] = '_';
}
- std::string name = StringPrintf("dom_storage/%s/%p", url.c_str(), this);
- auto mad = pmd->CreateAllocatorDump(name + "/storage_map");
- mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
- base::trace_event::MemoryAllocatorDump::kUnitsBytes,
- map_->bytes_used());
+ std::string name =
+ base::StringPrintf("dom_storage/%s/0x%" PRIXPTR, url.c_str(),
+ reinterpret_cast<uintptr_t>(this));
const char* system_allocator_name =
base::trace_event::MemoryDumpManager::GetInstance()
->system_allocator_pool_name();
+ if (commit_batch_) {
+ auto commit_batch_mad = pmd->CreateAllocatorDump(name + "/commit_batch");
+ commit_batch_mad->AddScalar(
+ base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ commit_batch_->GetDataSize());
+ if (system_allocator_name)
+ pmd->AddSuballocation(commit_batch_mad->guid(), system_allocator_name);
+ }
+
+ // Do not add storage map usage if less than 1KB.
+ if (map_->bytes_used() < 1024)
+ return;
+
+ auto map_mad = pmd->CreateAllocatorDump(name + "/storage_map");
+ map_mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ map_->bytes_used());
if (system_allocator_name)
- pmd->AddSuballocation(mad->guid(), system_allocator_name);
+ pmd->AddSuballocation(map_mad->guid(), system_allocator_name);
// TODO(ssid): Add memory usage of local backing storage crbug.com/605785.
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_area.h b/chromium/content/browser/dom_storage/dom_storage_area.h
index 9fc646be19b..9909fdd6c5b 100644
--- a/chromium/content/browser/dom_storage/dom_storage_area.h
+++ b/chromium/content/browser/dom_storage/dom_storage_area.h
@@ -18,6 +18,7 @@
#include "base/strings/nullable_string16.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
+#include "content/common/dom_storage/dom_storage_map.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "url/gurl.h"
@@ -30,7 +31,6 @@ class ProcessMemoryDump;
namespace content {
class DOMStorageDatabaseAdapter;
-class DOMStorageMap;
class DOMStorageTaskRunner;
class SessionStorageDatabase;
@@ -65,6 +65,7 @@ class CONTENT_EXPORT DOMStorageArea
const GURL& origin() const { return origin_; }
int64_t namespace_id() const { return namespace_id_; }
+ size_t map_usage_in_bytes() const { return map_ ? map_->bytes_used() : 0; }
// Writes a copy of the current set of values in the area to the |map|.
void ExtractValues(DOMStorageValuesMap* map);
@@ -116,6 +117,7 @@ class CONTENT_EXPORT DOMStorageArea
FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaTest, PurgeMemory);
FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaTest, RateLimiter);
FRIEND_TEST_ALL_PREFIXES(DOMStorageContextImplTest, PersistentIds);
+ FRIEND_TEST_ALL_PREFIXES(DOMStorageContextImplTest, PurgeMemory);
friend class base::RefCountedThreadSafe<DOMStorageArea>;
// Used to rate limit commits.
@@ -143,7 +145,7 @@ class CONTENT_EXPORT DOMStorageArea
base::TimeDelta time_quantum_;
};
- struct CommitBatch {
+ struct CONTENT_EXPORT CommitBatch {
bool clear_all_first;
DOMStorageValuesMap changed_values;
diff --git a/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
index 99521369113..b9137682bf9 100644
--- a/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
@@ -11,6 +11,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
@@ -203,7 +204,7 @@ TEST_F(DOMStorageAreaTest, BackingDatabaseOpened) {
EXPECT_TRUE(area->commit_batch_.get());
EXPECT_EQ(0, area->commit_batches_in_flight_);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(area->commit_batch_.get());
EXPECT_EQ(0, area->commit_batches_in_flight_);
@@ -251,7 +252,7 @@ TEST_F(DOMStorageAreaTest, CommitTasks) {
EXPECT_TRUE(area->commit_batch_.get());
EXPECT_FALSE(area->commit_batch_->clear_all_first);
EXPECT_EQ(2u, area->commit_batch_->changed_values.size());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(area->HasUncommittedChanges());
EXPECT_FALSE(area->commit_batch_.get());
EXPECT_EQ(0, area->commit_batches_in_flight_);
@@ -267,7 +268,7 @@ TEST_F(DOMStorageAreaTest, CommitTasks) {
EXPECT_TRUE(area->commit_batch_.get());
EXPECT_TRUE(area->commit_batch_->clear_all_first);
EXPECT_TRUE(area->commit_batch_->changed_values.empty());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(area->commit_batch_.get());
EXPECT_EQ(0, area->commit_batches_in_flight_);
// Verify the changes made it to the database.
@@ -289,7 +290,7 @@ TEST_F(DOMStorageAreaTest, CommitTasks) {
base::Bind(&DOMStorageAreaTest::InjectedCommitSequencingTask1,
base::Unretained(this),
area));
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(area->HasOneRef());
EXPECT_FALSE(area->HasUncommittedChanges());
// Verify the changes made it to the database.
@@ -319,7 +320,7 @@ TEST_F(DOMStorageAreaTest, CommitChangesAtShutdown) {
area->backing_->ReadAllValues(&values);
EXPECT_TRUE(values.empty()); // not committed yet
area->Shutdown();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(area->HasOneRef());
EXPECT_FALSE(area->backing_.get());
// The VerifyChangesCommittedDatabase destructor verifies values
@@ -346,7 +347,7 @@ TEST_F(DOMStorageAreaTest, DeleteOrigin) {
// Commit something in the database and then delete.
base::NullableString16 old_value;
area->SetItem(kKey, kValue, &old_value);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(base::PathExists(db_file_path));
area->DeleteOrigin();
EXPECT_EQ(0u, area->Length());
@@ -361,14 +362,14 @@ TEST_F(DOMStorageAreaTest, DeleteOrigin) {
area->DeleteOrigin();
EXPECT_TRUE(area->HasUncommittedChanges());
EXPECT_EQ(0u, area->Length());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(area->HasUncommittedChanges());
EXPECT_FALSE(base::PathExists(db_file_path));
// Put some uncommitted changes to a an existing database in
// and then delete.
area->SetItem(kKey, kValue, &old_value);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(base::PathExists(db_file_path));
area->SetItem(kKey2, kValue2, &old_value);
EXPECT_TRUE(area->HasUncommittedChanges());
@@ -376,13 +377,13 @@ TEST_F(DOMStorageAreaTest, DeleteOrigin) {
area->DeleteOrigin();
EXPECT_TRUE(area->HasUncommittedChanges());
EXPECT_EQ(0u, area->Length());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(area->HasUncommittedChanges());
// Since the area had uncommitted changes at the time delete
// was called, the file will linger until the shutdown time.
EXPECT_TRUE(base::PathExists(db_file_path));
area->Shutdown();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(base::PathExists(db_file_path));
}
@@ -425,7 +426,7 @@ TEST_F(DOMStorageAreaTest, PurgeMemory) {
EXPECT_EQ(original_map, area->map_.get());
// Commit the changes from above,
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(area->HasUncommittedChanges());
new_backing = static_cast<LocalStorageDatabaseAdapter*>(
area->backing_.get())->db_.get();
diff --git a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
index f1d522352a2..326c91e94c3 100644
--- a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
@@ -30,8 +30,7 @@ class DOMStorageBrowserTest : public ContentBrowserTest {
if (result != "pass") {
std::string js_result;
ASSERT_TRUE(ExecuteScriptAndExtractString(
- the_browser->web_contents(),
- "window.domAutomationController.send(getLog())",
+ the_browser, "window.domAutomationController.send(getLog())",
&js_result));
FAIL() << "Failed: " << js_result;
}
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 1e6afa770e5..425c45bee84 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
@@ -4,6 +4,7 @@
#include "content/browser/dom_storage/dom_storage_context_impl.h"
+#include <inttypes.h>
#include <stddef.h>
#include <stdlib.h>
@@ -13,6 +14,9 @@
#include "base/files/file_util.h"
#include "base/guid.h"
#include "base/location.h"
+#include "base/metrics/histogram.h"
+#include "base/strings/stringprintf.h"
+#include "base/sys_info.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
@@ -28,12 +32,39 @@
#include "storage/browser/quota/special_storage_policy.h"
namespace content {
+namespace {
-static const int kSessionStoraceScavengingSeconds = 60;
+// Limits on the cache size and number of areas in memory, over which the areas
+// are purged.
+#if defined(OS_ANDROID)
+const unsigned kMaxStorageAreaCount = 20;
+const size_t kMaxCacheSize = 2 * 1024 * 1024;
+#else
+const unsigned kMaxStorageAreaCount = 100;
+const size_t kMaxCacheSize = 20 * 1024 * 1024;
+#endif
+
+const int kSessionStoraceScavengingSeconds = 60;
// Offset the session storage namespace ids generated by different contexts
// to help identify when an id from one is mistakenly used in another.
-static int g_session_id_offset_sequence = 1;
+int g_session_id_offset_sequence = 1;
+
+// Aggregates statistics from all the namespaces.
+DOMStorageNamespace::UsageStatistics GetTotalNamespaceStatistics(
+ const DOMStorageContextImpl::StorageNamespaceMap& namespace_map) {
+ DOMStorageNamespace::UsageStatistics total_stats = {0};
+ for (const auto& it : namespace_map) {
+ DOMStorageNamespace::UsageStatistics stats =
+ it.second->GetUsageStatistics();
+ total_stats.total_cache_size += stats.total_cache_size;
+ total_stats.total_area_count += stats.total_area_count;
+ total_stats.inactive_area_count += stats.inactive_area_count;
+ }
+ return total_stats;
+}
+
+} // namespace
DOMStorageContextImpl::DOMStorageContextImpl(
const base::FilePath& localstorage_directory,
@@ -47,7 +78,8 @@ DOMStorageContextImpl::DOMStorageContextImpl(
is_shutdown_(false),
force_keep_session_state_(false),
special_storage_policy_(special_storage_policy),
- scavenging_started_(false) {
+ scavenging_started_(false),
+ is_low_end_device_(base::SysInfo::IsLowEndDevice()) {
// AtomicSequenceNum starts at 0 but we want to start session
// namespace ids at one since zero is reserved for the
// kLocalStorageNamespaceId.
@@ -396,14 +428,93 @@ void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() {
}
}
+void DOMStorageContextImpl::PurgeMemory(PurgeOption purge_option) {
+ if (is_shutdown_)
+ return;
+
+ DOMStorageNamespace::UsageStatistics initial_stats =
+ GetTotalNamespaceStatistics(namespaces_);
+ if (!initial_stats.total_area_count)
+ return;
+
+ // Track the total localStorage cache size.
+ UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.BrowserLocalStorageCacheSizeInKB",
+ initial_stats.total_cache_size / 1024, 1, 100000,
+ 50);
+
+ const char* purge_reason = nullptr;
+ if (purge_option == PURGE_IF_NEEDED) {
+ // Purging is done based on the cache sizes without including the database
+ // size since it can be expensive trying to estimate the sqlite usage for
+ // all databases. For low end devices purge all inactive areas.
+ if (initial_stats.total_cache_size > kMaxCacheSize)
+ purge_reason = "SizeLimitExceeded";
+ else if (initial_stats.total_area_count > kMaxStorageAreaCount)
+ purge_reason = "AreaCountLimitExceeded";
+ else if (is_low_end_device_)
+ purge_reason = "InactiveOnLowEndDevice";
+ if (!purge_reason)
+ return;
+
+ purge_option = PURGE_UNOPENED;
+ } else {
+ if (purge_option == PURGE_AGGRESSIVE)
+ purge_reason = "AggressivePurgeTriggered";
+ else
+ purge_reason = "ModeratePurgeTriggered";
+ }
+
+ // Return if no areas can be purged with the given option.
+ bool aggressively = purge_option == PURGE_AGGRESSIVE;
+ if (!aggressively && !initial_stats.inactive_area_count) {
+ return;
+ }
+ for (const auto& it : namespaces_)
+ it.second->PurgeMemory(aggressively);
+
+ // Track the size of cache purged.
+ size_t purged_size_kib =
+ (initial_stats.total_cache_size -
+ GetTotalNamespaceStatistics(namespaces_).total_cache_size) /
+ 1024;
+ std::string full_histogram_name =
+ std::string("LocalStorage.BrowserLocalStorageCachePurgedInKB.") +
+ purge_reason;
+ base::HistogramBase* histogram = base::Histogram::FactoryGet(
+ full_histogram_name, 1, 100000, 50,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ if (histogram)
+ histogram->Add(purged_size_kib);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.BrowserLocalStorageCachePurgedInKB",
+ purged_size_kib, 1, 100000, 50);
+}
+
bool DOMStorageContextImpl::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
+ if (session_storage_database_)
+ session_storage_database_->OnMemoryDump(pmd);
+ if (args.level_of_detail ==
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
+ DOMStorageNamespace::UsageStatistics total_stats =
+ GetTotalNamespaceStatistics(namespaces_);
+ auto mad = pmd->CreateAllocatorDump(
+ base::StringPrintf("dom_storage/0x%" PRIXPTR "/cache_size",
+ reinterpret_cast<uintptr_t>(this)));
+ mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ total_stats.total_cache_size);
+ mad->AddScalar("inactive_areas",
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ total_stats.inactive_area_count);
+ mad->AddScalar("total_areas",
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ total_stats.total_area_count);
+ return true;
+ }
for (const auto& it : namespaces_) {
it.second->OnMemoryDump(pmd);
}
- if (session_storage_database_)
- session_storage_database_->OnMemoryDump(pmd);
return true;
}
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 c2bbe4d42b5..c8f27e37ed8 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.h
@@ -65,6 +65,9 @@ class CONTENT_EXPORT DOMStorageContextImpl
: public base::RefCountedThreadSafe<DOMStorageContextImpl>,
public base::trace_event::MemoryDumpProvider {
public:
+ typedef std::map<int64_t, scoped_refptr<DOMStorageNamespace>>
+ StorageNamespaceMap;
+
// An interface for observing Local and Session Storage events on the
// background thread.
class EventObserver {
@@ -89,6 +92,19 @@ class CONTENT_EXPORT DOMStorageContextImpl
virtual ~EventObserver() {}
};
+ // Option for PurgeMemory.
+ enum PurgeOption {
+ // Determines if purging is required based on the usage and the platform.
+ PURGE_IF_NEEDED,
+
+ // Purge unopened areas only.
+ PURGE_UNOPENED,
+
+ // Purge aggressively, i.e. discard cache even for areas that have
+ // non-zero open count.
+ PURGE_AGGRESSIVE,
+ };
+
// |localstorage_directory| and |sessionstorage_directory| may be empty
// for incognito browser contexts.
DOMStorageContextImpl(const base::FilePath& localstorage_directory,
@@ -175,6 +191,10 @@ class CONTENT_EXPORT DOMStorageContextImpl
// unclean exit.
void StartScavengingUnusedSessionStorage();
+ // Frees up memory when possible. Purges caches and schedules commits
+ // depending on the given |purge_option|.
+ void PurgeMemory(PurgeOption purge_option);
+
// base::trace_event::MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
@@ -183,8 +203,6 @@ class CONTENT_EXPORT DOMStorageContextImpl
friend class DOMStorageContextImplTest;
FRIEND_TEST_ALL_PREFIXES(DOMStorageContextImplTest, Basics);
friend class base::RefCountedThreadSafe<DOMStorageContextImpl>;
- typedef std::map<int64_t, scoped_refptr<DOMStorageNamespace>>
- StorageNamespaceMap;
~DOMStorageContextImpl() override;
@@ -238,6 +256,9 @@ class CONTENT_EXPORT DOMStorageContextImpl
// Mapping between persistent namespace IDs and namespace IDs for
// sessionStorage.
std::map<std::string, int64_t> persistent_namespace_id_to_namespace_id_;
+
+ // For cleaning up unused databases more aggressively.
+ bool is_low_end_device_;
};
} // namespace content
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 e14e4e244bb..d5ca90b7412 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
@@ -7,6 +7,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -54,7 +55,7 @@ class DOMStorageContextImplTest : public testing::Test {
void TearDown() override {
if (context_)
context_->Shutdown();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
void VerifySingleOriginRemains(const GURL& origin) {
@@ -113,7 +114,7 @@ TEST_F(DOMStorageContextImplTest, UsageInfo) {
OpenStorageArea(kOrigin)->SetItem(kKey, kValue, &old_value));
context_->Shutdown();
context_ = NULL;
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Create a new context that points to the same directory, see that
// it knows about the origin that we stored data for.
@@ -146,7 +147,7 @@ TEST_F(DOMStorageContextImplTest, SessionOnly) {
OpenStorageArea(kSessionOnlyOrigin)->SetItem(kKey, kValue, &old_value));
context_->Shutdown();
context_ = NULL;
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Verify that the session-only origin data is gone.
VerifySingleOriginRemains(kOrigin);
@@ -164,7 +165,7 @@ TEST_F(DOMStorageContextImplTest, SetForceKeepSessionState) {
context_->SetForceKeepSessionState(); // Should override clear behavior.
context_->Shutdown();
context_ = NULL;
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
VerifySingleOriginRemains(kSessionOnlyOrigin);
}
@@ -225,7 +226,7 @@ TEST_F(DOMStorageContextImplTest, DeleteSessionStorage) {
// Destroy and recreate the DOMStorageContextImpl.
context_->Shutdown();
context_ = NULL;
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
context_ = new DOMStorageContextImpl(
temp_dir_.path(), temp_dir_.path(),
storage_policy_.get(), task_runner_.get());
@@ -249,7 +250,7 @@ TEST_F(DOMStorageContextImplTest, DeleteSessionStorage) {
// Destroy and recreate again.
context_->Shutdown();
context_ = NULL;
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
context_ = new DOMStorageContextImpl(
temp_dir_.path(), temp_dir_.path(),
storage_policy_.get(), task_runner_.get());
@@ -265,7 +266,38 @@ TEST_F(DOMStorageContextImplTest, DeleteSessionStorage) {
dom_namespace->CloseStorageArea(area);
context_->Shutdown();
context_ = NULL;
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(DOMStorageContextImplTest, PurgeMemory) {
+ auto dom_namespace = context_->GetStorageNamespace(kLocalStorageNamespaceId);
+ auto area1 = dom_namespace->OpenStorageArea(kOrigin);
+ area1->InitialImportIfNeeded();
+
+ // PURGE_UNOPENED does not delete the open area.
+ context_->PurgeMemory(DOMStorageContextImpl::PURGE_UNOPENED);
+ EXPECT_EQ(1u, dom_namespace->GetUsageStatistics().total_area_count);
+ EXPECT_EQ(0u, dom_namespace->GetUsageStatistics().inactive_area_count);
+
+ // PURGE_UNOPENED deletes the unopened area.
+ dom_namespace->CloseStorageArea(area1);
+ EXPECT_EQ(1u, dom_namespace->GetUsageStatistics().inactive_area_count);
+ context_->PurgeMemory(DOMStorageContextImpl::PURGE_UNOPENED);
+ EXPECT_EQ(0u, dom_namespace->GetUsageStatistics().total_area_count);
+
+ // Add an item to the database and commit changes, and keep it open. So, cache
+ // is kept alive.
+ auto area2 = dom_namespace->OpenStorageArea(kOrigin);
+ base::NullableString16 old_value;
+ area2->SetItem(kKey, kValue, &old_value);
+ // Call commit directly instead of posting task.
+ area2->CommitChanges(area2->commit_batch_.get());
+ area2->commit_batch_ = nullptr;
+
+ // PURGE_AGGRESSIVE clears the cache in the open area.
+ EXPECT_NE(0u, dom_namespace->GetUsageStatistics().total_cache_size);
+ context_->PurgeMemory(DOMStorageContextImpl::PURGE_AGGRESSIVE);
+ EXPECT_EQ(0u, dom_namespace->GetUsageStatistics().total_cache_size);
}
} // 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 8c80476cfc5..bd449721609 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -285,6 +285,9 @@ DOMStorageContextWrapper::DOMStorageContextWrapper(
worker_pool->GetNamedSequenceToken("dom_storage_commit"),
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)
.get()));
+
+ memory_pressure_listener_.reset(new base::MemoryPressureListener(
+ base::Bind(&DOMStorageContextWrapper::OnMemoryPressure, this)));
}
DOMStorageContextWrapper::~DOMStorageContextWrapper() {}
@@ -359,6 +362,7 @@ void DOMStorageContextWrapper::SetForceKeepSessionState() {
void DOMStorageContextWrapper::Shutdown() {
DCHECK(context_.get());
mojo_state_.reset();
+ memory_pressure_listener_.reset();
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE,
DOMStorageTaskRunner::PRIMARY_SEQUENCE,
@@ -380,4 +384,17 @@ void DOMStorageContextWrapper::OpenLocalStorage(
origin, std::move(observer), std::move(request));
}
+void DOMStorageContextWrapper::OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
+ DOMStorageContextImpl::PurgeOption purge_option =
+ DOMStorageContextImpl::PURGE_UNOPENED;
+ if (memory_pressure_level ==
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
+ purge_option = DOMStorageContextImpl::PURGE_AGGRESSIVE;
+ }
+ context_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DOMStorageContextImpl::PurgeMemory, context_, purge_option));
+}
+
} // namespace content
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 17796ff8bb5..701324850ac 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/memory_pressure_listener.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/common/storage_partition_service.mojom.h"
@@ -73,6 +74,10 @@ class CONTENT_EXPORT DOMStorageContextWrapper :
mojom::LevelDBObserverPtr observer,
mojom::LevelDBWrapperRequest request);
+ // Called on UI thread when the system is under memory pressure.
+ void OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
+
private:
friend class DOMStorageMessageFilter; // for access to context()
friend class SessionStorageNamespaceImpl; // ditto
@@ -86,6 +91,9 @@ class CONTENT_EXPORT DOMStorageContextWrapper :
class MojoState;
std::unique_ptr<MojoState> mojo_state_;
+ // To receive memory pressure signals.
+ std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
+
scoped_refptr<DOMStorageContextImpl> context_;
DISALLOW_IMPLICIT_CONSTRUCTORS(DOMStorageContextWrapper);
diff --git a/chromium/content/browser/dom_storage/dom_storage_database.cc b/chromium/content/browser/dom_storage/dom_storage_database.cc
index b19dffa6c2f..5b1b5bd63c3 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database.cc
@@ -68,6 +68,9 @@ void DOMStorageDatabase::ReadAllValues(DOMStorageValuesMap* result) {
(*result)[key] = base::NullableString16(value, false);
}
known_to_be_empty_ = result->empty();
+
+ // Reduce the size of sqlite caches.
+ db_->TrimMemory(false /* aggressively */);
}
bool DOMStorageDatabase::CommitChanges(bool clear_all_first,
@@ -125,6 +128,10 @@ bool DOMStorageDatabase::CommitChanges(bool clear_all_first,
bool success = transaction.Commit();
if (!success)
known_to_be_empty_ = old_known_to_be_empty;
+
+ // Reduce the size of sqlite caches.
+ db_->TrimMemory(false /* aggressively */);
+
return success;
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
index caea649f970..38f4fff87d7 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
@@ -11,7 +11,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/public/common/content_paths.h"
#include "sql/statement.h"
-#include "sql/test/scoped_error_ignorer.h"
+#include "sql/test/scoped_error_expecter.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
@@ -347,15 +347,15 @@ TEST(DOMStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) {
base::WriteFile(file_name, kData, strlen(kData));
{
- sql::ScopedErrorIgnorer ignore_errors;
+ sql::test::ScopedErrorExpecter expecter;
// Earlier versions of Chromium compiled against SQLite 3.6.7.3, which
// returned SQLITE_IOERR_SHORT_READ in this case. Some platforms may still
// compile against an earlier SQLite via USE_SYSTEM_SQLITE.
- if (ignore_errors.SQLiteLibVersionNumber() < 3008005) {
- ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ);
+ if (expecter.SQLiteLibVersionNumber() < 3008005) {
+ expecter.ExpectError(SQLITE_IOERR_SHORT_READ);
} else {
- ignore_errors.IgnoreError(SQLITE_NOTADB);
+ expecter.ExpectError(SQLITE_NOTADB);
}
// Try and open the file. As it's not a database, we should end up deleting
@@ -370,12 +370,12 @@ TEST(DOMStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) {
CheckValuesMatch(&db, values);
- ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ ASSERT_TRUE(expecter.SawExpectedErrors());
}
{
- sql::ScopedErrorIgnorer ignore_errors;
- ignore_errors.IgnoreError(SQLITE_CANTOPEN);
+ sql::test::ScopedErrorExpecter expecter;
+ expecter.ExpectError(SQLITE_CANTOPEN);
// Try to open a directory, we should fail gracefully and not attempt
// to delete it.
@@ -394,7 +394,7 @@ TEST(DOMStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) {
EXPECT_TRUE(base::PathExists(temp_dir.path()));
- ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ ASSERT_TRUE(expecter.SawExpectedErrors());
}
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_host.cc b/chromium/content/browser/dom_storage/dom_storage_host.cc
index 3db7d5a15ec..bba4460ce17 100644
--- a/chromium/content/browser/dom_storage/dom_storage_host.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_host.cc
@@ -7,7 +7,6 @@
#include "content/browser/dom_storage/dom_storage_area.h"
#include "content/browser/dom_storage/dom_storage_context_impl.h"
#include "content/browser/dom_storage/dom_storage_namespace.h"
-#include "content/common/dom_storage/dom_storage_types.h"
#include "url/gurl.h"
namespace content {
@@ -55,11 +54,7 @@ bool DOMStorageHost::ExtractAreaValues(
if (!area->IsLoadedInMemory()) {
DOMStorageNamespace* ns = GetNamespace(connection_id);
DCHECK(ns);
- if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas) {
- ns->PurgeMemory(DOMStorageNamespace::PURGE_UNOPENED);
- if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas)
- ns->PurgeMemory(DOMStorageNamespace::PURGE_AGGRESSIVE);
- }
+ context_->PurgeMemory(DOMStorageContextImpl::PURGE_IF_NEEDED);
}
area->ExtractValues(map);
return true;
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.cc b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
index 6f976f0d501..9aba4238b0e 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
@@ -117,9 +117,10 @@ void DOMStorageNamespace::DeleteSessionStorageOrigin(const GURL& origin) {
CloseStorageArea(area);
}
-void DOMStorageNamespace::PurgeMemory(PurgeOption option) {
+void DOMStorageNamespace::PurgeMemory(bool aggressively) {
if (directory_.empty())
return; // We can't purge w/o backing on disk.
+
AreaMap::iterator it = areas_.begin();
while (it != areas_.end()) {
const AreaHolder& holder = it->second;
@@ -143,7 +144,7 @@ void DOMStorageNamespace::PurgeMemory(PurgeOption option) {
continue;
}
- if (option == PURGE_AGGRESSIVE) {
+ if (aggressively) {
// If aggressive is true, we clear caches and such
// for opened areas.
holder.area_->PurgeMemory();
@@ -167,13 +168,18 @@ void DOMStorageNamespace::Flush() {
}
}
-unsigned int DOMStorageNamespace::CountInMemoryAreas() const {
- unsigned int area_count = 0;
+DOMStorageNamespace::UsageStatistics DOMStorageNamespace::GetUsageStatistics()
+ const {
+ UsageStatistics stats = {0};
for (AreaMap::const_iterator it = areas_.begin(); it != areas_.end(); ++it) {
- if (it->second.area_->IsLoadedInMemory())
- ++area_count;
+ if (it->second.area_->IsLoadedInMemory()) {
+ stats.total_cache_size += it->second.area_->map_usage_in_bytes();
+ ++stats.total_area_count;
+ if (it->second.open_count_ == 0)
+ ++stats.inactive_area_count;
+ }
}
- return area_count;
+ return stats;
}
void DOMStorageNamespace::OnMemoryDump(
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.h b/chromium/content/browser/dom_storage/dom_storage_namespace.h
index f572284d5ae..8f75f2ab825 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.h
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.h
@@ -32,14 +32,11 @@ class SessionStorageDatabase;
class CONTENT_EXPORT DOMStorageNamespace
: public base::RefCountedThreadSafe<DOMStorageNamespace> {
public:
- // Option for PurgeMemory.
- enum PurgeOption {
- // Purge unopened areas only.
- PURGE_UNOPENED,
-
- // Purge aggressively, i.e. discard cache even for areas that have
- // non-zero open count.
- PURGE_AGGRESSIVE,
+ // Struct to hold statistics about the areas in the namespace.
+ struct UsageStatistics {
+ size_t total_cache_size;
+ unsigned total_area_count;
+ unsigned inactive_area_count; // areas with open count 0.
};
// Constructor for a LocalStorage namespace with id of 0
@@ -76,11 +73,12 @@ class CONTENT_EXPORT DOMStorageNamespace
void DeleteLocalStorageOrigin(const GURL& origin);
void DeleteSessionStorageOrigin(const GURL& origin);
- void PurgeMemory(PurgeOption purge);
+ void PurgeMemory(bool aggressively);
void Shutdown();
void Flush();
- unsigned int CountInMemoryAreas() const;
+ // Returns statistics about the areas in the namespace.
+ UsageStatistics GetUsageStatistics() const;
// Adds memory statistics to |pmd| for chrome://tracing.
void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd);
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index 219c184e244..3a9457121d2 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -4,6 +4,7 @@
#include "content/browser/dom_storage/session_storage_database.h"
+#include <inttypes.h>
#include <stddef.h>
#include <vector>
@@ -345,7 +346,8 @@ void SessionStorageDatabase::OnMemoryDump(
DCHECK(res);
auto mad = pmd->CreateAllocatorDump(
- base::StringPrintf("dom_storage/session_storage_%p", this));
+ base::StringPrintf("dom_storage/session_storage_0x%" PRIXPTR,
+ reinterpret_cast<uintptr_t>(this)));
mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes, size);
diff --git a/chromium/content/browser/download/base_file.cc b/chromium/content/browser/download/base_file.cc
index e34970f7868..735793270ff 100644
--- a/chromium/content/browser/download/base_file.cc
+++ b/chromium/content/browser/download/base_file.cc
@@ -208,7 +208,7 @@ std::string BaseFile::DebugString() const {
DownloadInterruptReason BaseFile::CalculatePartialHash(
const std::string& hash_to_expect) {
- secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+ secure_hash_ = crypto::SecureHash::Create(crypto::SecureHash::SHA256);
if (bytes_so_far_ == 0)
return DOWNLOAD_INTERRUPT_REASON_NONE;
diff --git a/chromium/content/browser/download/docs/save-page-as.md b/chromium/content/browser/download/docs/save-page-as.md
index 2661289b375..a4b6fd24071 100644
--- a/chromium/content/browser/download/docs/save-page-as.md
+++ b/chromium/content/browser/download/docs/save-page-as.md
@@ -16,10 +16,9 @@ are described by their code comments or by their code structure).
* UI-thread object
* SaveFileCreateInfo::SaveFileSource enum
- * classifies `SaveItem` and `SaveFile` processing into 3 flavours:
+ * classifies `SaveItem` and `SaveFile` processing into 2 flavours:
* `SAVE_FILE_FROM_NET` (see `SaveFileResourceHandler`)
* `SAVE_FILE_FROM_DOM` (see "Complete HTML" section below)
- * `SAVE_FILE_FROM_FILE` (see `SaveFileManager::SaveLocalFile`)
* SaveItem class
* tracks saving a single file
@@ -68,8 +67,8 @@ Very high-level flow of saving a page as "Complete HTML":
* Step 1: `SavePackage` asks all frames for "savable resources"
and creates `SaveItem` for each of files that need to be saved
-* Step 2: `SavePackage` first processes `SAVE_FILE_FROM_NET` and
- `SAVE_FILE_FROM_FILE` `SaveItem`s and asks `SaveFileManager` to save
+* Step 2: `SavePackage` first processes `SAVE_FILE_FROM_NET`
+ `SaveItem`s and asks `SaveFileManager` to save
them.
* Step 3: `SavePackage` handles remaining `SAVE_FILE_FROM_DOM` `SaveItem`s and
@@ -88,13 +87,16 @@ Very high-level flow of saving a page as MHTML:
API) or by an embedder of `WebContents` (since this is public API of
//content).
-* Step 2: `MHTMLGenerationManager` coordinates generation of the MHTML file
- by sequentially (one-at-a-time) asking each frame to write its portion
- of MHTML to a file handle. Other classes (i.e. `SavePackage` and/or
- `SaveFileManager`) are not used at this step at all.
+* Step 2: `MHTMLGenerationManager` creates a new instance of
+ `MHTMLGenerationManager::Job` that coordinates generation of
+ the MHTML file by sequentially (one-at-a-time) asking each
+ frame to write its portion of MHTML to a file handle. Other
+ classes (i.e. `SavePackage` and/or `SaveFileManager`) are not
+ used at this step at all.
-* Step 3: When done `MHTMLGenerationManager` calls a completion callback
- which in case of Save-Page-As will end up in
+* Step 3: When done `MHTMLGenerationManager` destroys
+ `MHTMLGenerationManager::Job` instance and calls a completion
+ callback which in case of Save-Page-As will end up in
`SavePackage::OnMHTMLGenerated`.
Note: MHTML format is by default disabled in Save-Page-As UI on Windows, MacOS
@@ -106,8 +108,8 @@ changed using `--save-page-as-mhtml` command line switch.
Very high-level flow of saving a page as "HTML Only":
-* `SavePackage` creates only a single `SaveItem` (either `SAVE_FILE_FROM_NET` or
- `SAVE_FILE_FROM_FILE`) and asks `SaveFileManager` to process it
+* `SavePackage` creates only a single `SaveItem` (always `SAVE_FILE_FROM_NET`)
+ and asks `SaveFileManager` to process it
(as in the Complete HTML individual SaveItem handling above.).
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index 5d78e1c7a82..352f7a22b1b 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -32,7 +32,6 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/download_danger_type.h"
-#include "content/public/browser/power_save_blocker.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/content_features.h"
@@ -48,6 +47,7 @@
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_download_manager_delegate.h"
#include "content/shell/browser/shell_network_delegate.h"
+#include "device/power_save_blocker/power_save_blocker.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
@@ -122,13 +122,14 @@ static DownloadManagerImpl* DownloadManagerForShell(Shell* shell) {
class DownloadFileWithDelay : public DownloadFileImpl {
public:
- DownloadFileWithDelay(std::unique_ptr<DownloadSaveInfo> save_info,
- const base::FilePath& default_download_directory,
- std::unique_ptr<ByteStreamReader> stream,
- const net::BoundNetLog& bound_net_log,
- std::unique_ptr<PowerSaveBlocker> power_save_blocker,
- base::WeakPtr<DownloadDestinationObserver> observer,
- base::WeakPtr<DownloadFileWithDelayFactory> owner);
+ DownloadFileWithDelay(
+ std::unique_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_download_directory,
+ std::unique_ptr<ByteStreamReader> stream,
+ const net::BoundNetLog& bound_net_log,
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker,
+ base::WeakPtr<DownloadDestinationObserver> observer,
+ base::WeakPtr<DownloadFileWithDelayFactory> owner);
~DownloadFileWithDelay() override;
@@ -193,7 +194,7 @@ DownloadFileWithDelay::DownloadFileWithDelay(
const base::FilePath& default_download_directory,
std::unique_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
- std::unique_ptr<PowerSaveBlocker> power_save_blocker,
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker,
base::WeakPtr<DownloadDestinationObserver> observer,
base::WeakPtr<DownloadFileWithDelayFactory> owner)
: DownloadFileImpl(std::move(save_info),
@@ -254,9 +255,11 @@ DownloadFile* DownloadFileWithDelayFactory::CreateFile(
std::unique_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer) {
- std::unique_ptr<PowerSaveBlocker> psb(PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
- PowerSaveBlocker::kReasonOther, "Download in progress"));
+ std::unique_ptr<device::PowerSaveBlocker> psb(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ device::PowerSaveBlocker::kReasonOther, "Download in progress",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
return new DownloadFileWithDelay(std::move(save_info),
default_download_directory,
std::move(stream),
@@ -291,12 +294,13 @@ void DownloadFileWithDelayFactory::WaitForSomeCallback() {
class CountingDownloadFile : public DownloadFileImpl {
public:
- CountingDownloadFile(std::unique_ptr<DownloadSaveInfo> save_info,
- const base::FilePath& default_downloads_directory,
- std::unique_ptr<ByteStreamReader> stream,
- const net::BoundNetLog& bound_net_log,
- std::unique_ptr<PowerSaveBlocker> power_save_blocker,
- base::WeakPtr<DownloadDestinationObserver> observer)
+ CountingDownloadFile(
+ std::unique_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_downloads_directory,
+ std::unique_ptr<ByteStreamReader> stream,
+ const net::BoundNetLog& bound_net_log,
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker,
+ base::WeakPtr<DownloadDestinationObserver> observer)
: DownloadFileImpl(std::move(save_info),
default_downloads_directory,
std::move(stream),
@@ -350,9 +354,11 @@ class CountingDownloadFileFactory : public DownloadFileFactory {
std::unique_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer) override {
- std::unique_ptr<PowerSaveBlocker> psb(PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
- PowerSaveBlocker::kReasonOther, "Download in progress"));
+ std::unique_ptr<device::PowerSaveBlocker> psb(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ device::PowerSaveBlocker::kReasonOther, "Download in progress",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
return new CountingDownloadFile(std::move(save_info),
default_downloads_directory,
std::move(stream),
@@ -548,13 +554,6 @@ class TestRequestStartHandler {
class DownloadContentTest : public ContentBrowserTest {
protected:
void SetUpOnMainThread() override {
- // Enable downloads resumption.
- base::FeatureList::ClearInstanceForTesting();
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(features::kDownloadResumption.name,
- std::string());
- base::FeatureList::SetInstance(std::move(feature_list));
-
ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
test_delegate_.reset(new TestShellDownloadManagerDelegate());
@@ -2253,8 +2252,8 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) {
// Download the file.
SetupEnsureNoPendingDownloads();
std::unique_ptr<DownloadUrlParameters> download_parameters(
- DownloadUrlParameters::FromWebContents(shell()->web_contents(),
- origin_two.GetURL("/bar")));
+ DownloadUrlParameters::CreateForWebContentsMainFrame(
+ shell()->web_contents(), origin_two.GetURL("/bar")));
std::unique_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
DownloadManagerForShell(shell())->DownloadUrl(std::move(download_parameters));
observer->WaitForFinished();
diff --git a/chromium/content/browser/download/download_item_impl.cc b/chromium/content/browser/download/download_item_impl.cc
index 56c8bcb13e0..be68b07963b 100644
--- a/chromium/content/browser/download/download_item_impl.cc
+++ b/chromium/content/browser/download/download_item_impl.cc
@@ -31,7 +31,6 @@
#include "base/format_macros.h"
#include "base/guid.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
@@ -95,10 +94,6 @@ static void DownloadFileCancel(std::unique_ptr<DownloadFile> download_file) {
download_file->Cancel();
}
-bool IsDownloadResumptionEnabled() {
- return base::FeatureList::IsEnabled(features::kDownloadResumption);
-}
-
} // namespace
const uint32_t DownloadItem::kInvalidId = 0;
@@ -375,7 +370,7 @@ void DownloadItemImpl::Resume() {
case INTERRUPTED_INTERNAL:
auto_resume_count_ = 0; // User input resets the counter.
- ResumeInterruptedDownload();
+ ResumeInterruptedDownload(ResumptionRequestSource::USER);
UpdateObservers();
return;
@@ -483,9 +478,8 @@ bool DownloadItemImpl::CanResume() const {
ResumeMode resume_mode = GetResumeMode();
// Only allow Resume() calls if the resumption mode requires a user
// action.
- return IsDownloadResumptionEnabled() &&
- (resume_mode == RESUME_MODE_USER_RESTART ||
- resume_mode == RESUME_MODE_USER_CONTINUE);
+ return resume_mode == RESUME_MODE_USER_RESTART ||
+ resume_mode == RESUME_MODE_USER_CONTINUE;
}
case MAX_DOWNLOAD_INTERNAL_STATE:
@@ -844,9 +838,6 @@ std::string DownloadItemImpl::DebugString(bool verbose) const {
DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!IsDownloadResumptionEnabled())
- return RESUME_MODE_INVALID;
-
// Only support resumption for HTTP(S).
if (!GetURL().SchemeIsHTTPOrHTTPS())
return RESUME_MODE_INVALID;
@@ -1183,9 +1174,9 @@ void DownloadItemImpl::Start(
int64_t offset = new_create_info.save_info->offset;
std::unique_ptr<crypto::SecureHash> hash_state =
- base::WrapUnique(new_create_info.save_info->hash_state
- ? new_create_info.save_info->hash_state->Clone()
- : nullptr);
+ new_create_info.save_info->hash_state
+ ? new_create_info.save_info->hash_state->Clone()
+ : nullptr;
// Interrupted downloads also need a target path.
if (target_path_.empty()) {
@@ -1878,14 +1869,12 @@ void DownloadItemImpl::AutoResumeIfValid() {
auto_resume_count_++;
- ResumeInterruptedDownload();
+ ResumeInterruptedDownload(ResumptionRequestSource::AUTOMATIC);
}
-void DownloadItemImpl::ResumeInterruptedDownload() {
+void DownloadItemImpl::ResumeInterruptedDownload(
+ ResumptionRequestSource source) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!IsDownloadResumptionEnabled())
- return;
-
// If we're not interrupted, ignore the request; our caller is drunk.
if (state_ != INTERRUPTED_INTERNAL)
return;
@@ -1914,7 +1903,7 @@ void DownloadItemImpl::ResumeInterruptedDownload() {
// request will not be dropped if the WebContents (and by extension, the
// associated renderer) goes away before a response is received.
std::unique_ptr<DownloadUrlParameters> download_params(
- new DownloadUrlParameters(GetURL(), -1, -1, -1,
+ new DownloadUrlParameters(GetURL(),
storage_partition->GetURLRequestContext()));
download_params->set_file_path(GetFullPath());
download_params->set_offset(GetReceivedBytes());
@@ -1930,6 +1919,9 @@ void DownloadItemImpl::ResumeInterruptedDownload() {
Referrer(GetReferrerUrl(), blink::WebReferrerPolicyAlways));
TransitionTo(RESUMING_INTERNAL);
+ RecordDownloadSource(source == ResumptionRequestSource::USER
+ ? INITIATED_BY_MANUAL_RESUMPTION
+ : INITIATED_BY_AUTOMATIC_RESUMPTION);
delegate_->ResumeInterruptedDownload(std::move(download_params), GetId());
// Just in case we were interrupted while paused.
is_paused_ = false;
diff --git a/chromium/content/browser/download/download_item_impl.h b/chromium/content/browser/download/download_item_impl.h
index ba5b2ae0d3c..802c5af06ea 100644
--- a/chromium/content/browser/download/download_item_impl.h
+++ b/chromium/content/browser/download/download_item_impl.h
@@ -476,7 +476,8 @@ class CONTENT_EXPORT DownloadItemImpl
void AutoResumeIfValid();
- void ResumeInterruptedDownload();
+ enum class ResumptionRequestSource { AUTOMATIC, USER };
+ void ResumeInterruptedDownload(ResumptionRequestSource source);
// Update origin information based on the response to a download resumption
// request. Should only be called if the resumption request was successful.
diff --git a/chromium/content/browser/download/download_item_impl_unittest.cc b/chromium/content/browser/download/download_item_impl_unittest.cc
index 4fd8b8756b0..c9389638c22 100644
--- a/chromium/content/browser/download/download_item_impl_unittest.cc
+++ b/chromium/content/browser/download/download_item_impl_unittest.cc
@@ -244,12 +244,6 @@ class DownloadItemTest : public testing::Test {
public:
DownloadItemTest()
: delegate_(), next_download_id_(DownloadItem::kInvalidId + 1) {
- base::FeatureList::ClearInstanceForTesting();
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(features::kDownloadResumption.name,
- std::string());
- base::FeatureList::SetInstance(std::move(feature_list));
-
create_info_.reset(new DownloadCreateInfo());
create_info_->save_info =
std::unique_ptr<DownloadSaveInfo>(new DownloadSaveInfo());
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index 22caf42d9d2..e5584bd4c06 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -470,7 +470,6 @@ void DownloadManagerImpl::OnSavePackageSuccessfullyFinished(
void DownloadManagerImpl::ResumeInterruptedDownload(
std::unique_ptr<content::DownloadUrlParameters> params,
uint32_t id) {
- RecordDownloadSource(INITIATED_BY_RESUMPTION);
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::IO, FROM_HERE,
base::Bind(&BeginDownload, base::Passed(&params),
diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc
index 4ab373f1877..fa768758946 100644
--- a/chromium/content/browser/download/download_request_core.cc
+++ b/chromium/content/browser/download/download_request_core.cc
@@ -29,9 +29,9 @@
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager_delegate.h"
#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/power_save_blocker.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/web_contents.h"
+#include "device/power_save_blocker/power_save_blocker.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
@@ -204,9 +204,11 @@ DownloadRequestCore::DownloadRequestCore(net::URLRequest* request,
DCHECK(request_);
DCHECK(delegate_);
RecordDownloadCount(UNTHROTTLED_COUNT);
- power_save_blocker_ = PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
- PowerSaveBlocker::kReasonOther, "Download in progress");
+ power_save_blocker_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ device::PowerSaveBlocker::kReasonOther, "Download in progress",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
DownloadRequestData* request_data = DownloadRequestData::Get(request_);
if (request_data) {
save_info_ = request_data->TakeSaveInfo();
@@ -523,23 +525,19 @@ std::string DownloadRequestCore::DebugString() const {
DownloadInterruptReason DownloadRequestCore::HandleRequestStatus(
const net::URLRequestStatus& status) {
net::Error error_code = net::OK;
- if (status.status() == net::URLRequestStatus::FAILED ||
- // Note cancels as failures too.
- status.status() == net::URLRequestStatus::CANCELED) {
+ if (!status.is_success()) {
error_code = static_cast<net::Error>(status.error()); // Normal case.
// Make sure that at least the fact of failure comes through.
if (error_code == net::OK)
error_code = net::ERR_FAILED;
}
- // ERR_CONTENT_LENGTH_MISMATCH and ERR_INCOMPLETE_CHUNKED_ENCODING are
- // allowed since a number of servers in the wild close the connection too
- // early by mistake. Other browsers - IE9, Firefox 11.0, and Safari 5.1.4 -
- // treat downloads as complete in both cases, so we follow their lead.
- if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH ||
- error_code == net::ERR_INCOMPLETE_CHUNKED_ENCODING) {
+ // ERR_CONTENT_LENGTH_MISMATCH is allowed since a number of servers in the
+ // wild close the connection too early by mistake. Other browsers - IE9,
+ // Firefox 11.0, and Safari 5.1.4 - treat downloads as complete in both cases,
+ // so we follow their lead.
+ if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH)
error_code = net::OK;
- }
DownloadInterruptReason reason = ConvertNetErrorToInterruptReason(
error_code, DOWNLOAD_INTERRUPT_FROM_NETWORK);
diff --git a/chromium/content/browser/download/download_request_core.h b/chromium/content/browser/download/download_request_core.h
index 84eb2e0a935..646911641b5 100644
--- a/chromium/content/browser/download/download_request_core.h
+++ b/chromium/content/browser/download/download_request_core.h
@@ -19,6 +19,10 @@
#include "content/public/browser/download_save_info.h"
#include "content/public/browser/download_url_parameters.h"
+namespace device {
+class PowerSaveBlocker;
+} // namespace device
+
namespace net {
class HttpResponseHeaders;
class URLRequest;
@@ -29,7 +33,6 @@ namespace content {
class DownloadManagerImpl;
class ByteStreamReader;
class ByteStreamWriter;
-class PowerSaveBlocker;
struct DownloadCreateInfo;
// This class encapsulates the core logic for reading data from a URLRequest and
@@ -140,7 +143,7 @@ class CONTENT_EXPORT DownloadRequestCore
// Keeps the system from sleeping while this is alive. If the
// system enters power saving mode while a request is alive, it can cause the
// request to fail and the associated download will be interrupted.
- std::unique_ptr<PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
// The following are used to collect stats.
base::TimeTicks download_start_time_;
diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc
index fabe1d62919..7798f926ad6 100644
--- a/chromium/content/browser/download/download_resource_handler.cc
+++ b/chromium/content/browser/download/download_resource_handler.cc
@@ -16,6 +16,7 @@
#include "content/browser/download/download_interrupt_reasons_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_request_handle.h"
+#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/public/browser/browser_thread.h"
@@ -23,6 +24,7 @@
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/resource_response.h"
namespace content {
@@ -42,11 +44,22 @@ static void StartOnUIThread(
std::unique_ptr<ByteStreamReader> stream,
int render_process_id,
int render_frame_id,
+ int frame_tree_node_id,
const DownloadUrlParameters::OnStartedCallback& started_cb) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHost* frame_host =
RenderFrameHost::FromID(render_process_id, render_frame_id);
+
+ // PlzNavigate: navigations don't have associated RenderFrameHosts. Get the
+ // SiteInstance from the FrameTreeNode.
+ if (!frame_host && IsBrowserSideNavigationEnabled()) {
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+ if (frame_tree_node)
+ frame_host = frame_tree_node->current_frame_host();
+ }
+
DownloadManager* download_manager =
info->request_handle->GetDownloadManager();
if (!download_manager || !frame_host) {
@@ -203,7 +216,8 @@ void DownloadResourceHandler::OnStart(
BrowserThread::UI, FROM_HERE,
base::Bind(&StartOnUIThread, base::Passed(&create_info),
base::Passed(&tab_info_), base::Passed(&stream_reader),
- render_process_id, render_frame_id, callback));
+ render_process_id, render_frame_id,
+ request_info->frame_tree_node_id(), callback));
}
void DownloadResourceHandler::OnReadyToRead() {
diff --git a/chromium/content/browser/download/download_stats.h b/chromium/content/browser/download/download_stats.h
index a029a0b4f34..8da7f022304 100644
--- a/chromium/content/browser/download/download_stats.h
+++ b/chromium/content/browser/download/download_stats.h
@@ -107,9 +107,16 @@ enum DownloadSource {
// Fomerly INITIATED_BY_PEPPER_SAVE.
DOWNLOAD_SOURCE_UNUSED_3,
- // A request that was initiated as a result of resuming an interrupted
- // download.
- INITIATED_BY_RESUMPTION,
+ // Formerly INITIATED_BY_RESUMPTION.
+ DOWNLOAD_SOURCE_UNUSED_4,
+
+ // A request that was initiated as a result of manually resuming an
+ // interrupted download.
+ INITIATED_BY_MANUAL_RESUMPTION,
+
+ // A request that was initiated as a result of automatically resuming an
+ // interrupted download.
+ INITIATED_BY_AUTOMATIC_RESUMPTION,
DOWNLOAD_SOURCE_LAST_ENTRY
};
diff --git a/chromium/content/browser/download/drag_download_file.cc b/chromium/content/browser/download/drag_download_file.cc
index 468c26f5c21..cd68969fb0d 100644
--- a/chromium/content/browser/download/drag_download_file.cc
+++ b/chromium/content/browser/download/drag_download_file.cc
@@ -65,8 +65,11 @@ class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer {
BrowserContext::GetDownloadManager(web_contents_->GetBrowserContext());
RecordDownloadSource(INITIATED_BY_DRAG_N_DROP);
+ // TODO(https://crbug.com/614134) This should use the frame actually
+ // containing the link being dragged rather than the main frame of the tab.
std::unique_ptr<content::DownloadUrlParameters> params(
- DownloadUrlParameters::FromWebContents(web_contents_, url_));
+ DownloadUrlParameters::CreateForWebContentsMainFrame(
+ web_contents_, url_));
params->set_referrer(referrer_);
params->set_referrer_encoding(referrer_encoding_);
params->set_callback(base::Bind(&DragDownloadFileUI::OnDownloadStarted,
diff --git a/chromium/content/browser/download/drag_download_file_browsertest.cc b/chromium/content/browser/download/drag_download_file_browsertest.cc
index 8986c391350..5821c3015bd 100644
--- a/chromium/content/browser/download/drag_download_file_browsertest.cc
+++ b/chromium/content/browser/download/drag_download_file_browsertest.cc
@@ -14,7 +14,6 @@
#include "content/browser/download/drag_download_util.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/power_save_blocker.h"
#include "content/public/common/content_client.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -23,6 +22,7 @@
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_download_manager_delegate.h"
+#include "device/power_save_blocker/power_save_blocker.h"
#include "net/test/url_request/url_request_mock_http_job.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/download/mhtml_generation_browsertest.cc b/chromium/content/browser/download/mhtml_generation_browsertest.cc
index 00f3aeb1964..8a8052efd3d 100644
--- a/chromium/content/browser/download/mhtml_generation_browsertest.cc
+++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc
@@ -11,6 +11,10 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/common/frame_messages.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/mhtml_generation_params.h"
#include "content/public/test/browser_test_utils.h"
@@ -18,10 +22,13 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "net/base/filename_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebFindOptions.h"
+#include "third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h"
using testing::ContainsRegex;
using testing::HasSubstr;
@@ -29,6 +36,58 @@ using testing::Not;
namespace content {
+namespace {
+
+// A dummy WebContentsDelegate which tracks the results of a find operation.
+class FindTrackingDelegate : public WebContentsDelegate {
+ public:
+ FindTrackingDelegate(const std::string& search)
+ : search_(search), matches_(-1) {}
+
+ // Returns number of results.
+ int Wait(WebContents* web_contents) {
+ WebContentsDelegate* old_delegate = web_contents->GetDelegate();
+ web_contents->SetDelegate(this);
+
+ blink::WebFindOptions options;
+ options.matchCase = false;
+
+ web_contents->Find(global_request_id++, base::UTF8ToUTF16(search_),
+ options);
+ run_loop_.Run();
+
+ web_contents->SetDelegate(old_delegate);
+
+ return matches_;
+ }
+
+ void FindReply(WebContents* web_contents,
+ int request_id,
+ int number_of_matches,
+ const gfx::Rect& selection_rect,
+ int active_match_ordinal,
+ bool final_update) override {
+ if (final_update) {
+ matches_ = number_of_matches;
+ run_loop_.Quit();
+ }
+ }
+
+ static int global_request_id;
+
+ private:
+ std::string search_;
+ int matches_;
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(FindTrackingDelegate);
+};
+
+// static
+int FindTrackingDelegate::global_request_id = 0;
+
+} // namespace
+
class MHTMLGenerationTest : public ContentBrowserTest {
public:
MHTMLGenerationTest() : has_mhtml_callback_run_(false), file_size_(0) {}
@@ -46,7 +105,10 @@ class MHTMLGenerationTest : public ContentBrowserTest {
void GenerateMHTML(const MHTMLGenerationParams& params, const GURL& url) {
NavigateToURL(shell(), url);
+ GenerateMHTMLForCurrentPage(params);
+ }
+ void GenerateMHTMLForCurrentPage(const MHTMLGenerationParams& params) {
base::RunLoop run_loop;
shell()->web_contents()->GenerateMHTML(
@@ -65,6 +127,68 @@ class MHTMLGenerationTest : public ContentBrowserTest {
return file_size;
}
+ void TestOriginalVsSavedPage(
+ const GURL& url,
+ const MHTMLGenerationParams params,
+ int expected_number_of_frames,
+ const std::vector<std::string>& expected_substrings,
+ const std::vector<std::string>& forbidden_substrings_in_saved_page,
+ bool skip_verification_of_original_page = false) {
+ // Navigate to the test page and verify if test expectations
+ // are met (this is mostly a sanity check - a failure to meet
+ // expectations would probably mean that there is a test bug
+ // (i.e. that we got called with wrong expected_foo argument).
+ NavigateToURL(shell(), url);
+ if (!skip_verification_of_original_page) {
+ AssertExpectationsAboutCurrentTab(expected_number_of_frames,
+ expected_substrings,
+ std::vector<std::string>());
+ }
+
+ GenerateMHTML(params, url);
+ ASSERT_FALSE(HasFailure());
+
+ // Stop the test server (to make sure the locally saved page
+ // is self-contained / won't try to open original resources).
+ ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+
+ // Open the saved page and verify if test expectations are
+ // met (i.e. if the same expectations are met for "after"
+ // [saved version of the page] as for the "before"
+ // [the original version of the page].
+ NavigateToURL(shell(), net::FilePathToFileURL(params.file_path));
+ AssertExpectationsAboutCurrentTab(expected_number_of_frames,
+ expected_substrings,
+ forbidden_substrings_in_saved_page);
+ }
+
+ void AssertExpectationsAboutCurrentTab(
+ int expected_number_of_frames,
+ const std::vector<std::string>& expected_substrings,
+ const std::vector<std::string>& forbidden_substrings) {
+ int actual_number_of_frames =
+ shell()->web_contents()->GetAllFrames().size();
+ EXPECT_EQ(expected_number_of_frames, actual_number_of_frames);
+
+ for (const auto& expected_substring : expected_substrings) {
+ FindTrackingDelegate delegate(expected_substring);
+ int actual_number_of_matches = delegate.Wait(shell()->web_contents());
+ EXPECT_EQ(1, actual_number_of_matches)
+ << "Verifying that \"" << expected_substring << "\" appears "
+ << "exactly once in the text of web contents of "
+ << shell()->web_contents()->GetURL().spec();
+ }
+
+ for (const auto& forbidden_substring : forbidden_substrings) {
+ FindTrackingDelegate delegate(forbidden_substring);
+ int actual_number_of_matches = delegate.Wait(shell()->web_contents());
+ EXPECT_EQ(0, actual_number_of_matches)
+ << "Verifying that \"" << forbidden_substring << "\" doesn't "
+ << "appear in the text of web contents of "
+ << shell()->web_contents()->GetURL().spec();
+ }
+ }
+
bool has_mhtml_callback_run() const { return has_mhtml_callback_run_; }
int64_t file_size() const { return file_size_; }
@@ -102,6 +226,121 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTML) {
HasSubstr("Content-Transfer-Encoding: quoted-printable"));
}
+class GenerateMHTMLAndExitRendererMessageFilter : public BrowserMessageFilter {
+ public:
+ GenerateMHTMLAndExitRendererMessageFilter(
+ RenderProcessHostImpl* render_process_host)
+ : BrowserMessageFilter(FrameMsgStart),
+ render_process_host_(render_process_host) {}
+
+ protected:
+ ~GenerateMHTMLAndExitRendererMessageFilter() override {}
+
+ private:
+ bool OnMessageReceived(const IPC::Message& message) override {
+ if (message.type() == FrameHostMsg_SerializeAsMHTMLResponse::ID) {
+ // After |return false| below, this IPC message will be handled by the
+ // product code as illustrated below. (1), (2), (3) depict points in time
+ // when product code runs on UI and FILE threads. (X), (Y), (Z) depict
+ // when we want test-injected tasks to run - for the repro, (Z) has to
+ // happen between (1) and (3). (Y?) and (Z?) depict when test tasks can
+ // theoretically happen and ruin the repro.
+ //
+ // IO thread UI thread FILE thread
+ // --------- --------- -----------
+ // | | |
+ // WE ARE HERE | |
+ // | | |
+ // after |return false| | |
+ // +--------------->+ |
+ // | | |
+ // | (X) |
+ // | | |
+ // | | (Y?)
+ // | (Z?) |
+ // | | |
+ // (1) | MHTMLGenerationManager |
+ // | ::OnSerializeAsMHTMLResponse |
+ // | +-------------------->+
+ // | | |
+ // | | (Y)
+ // | | |
+ // (2) | | MHTMLGenerationManager::Job
+ // | | ::CloseFileOnFileThread
+ // | | |
+ // | (Z) |
+ // | test needs to inject |
+ // | fast renderer shutdown |
+ // | HERE - between (1) and (3) |
+ // | | |
+ // | | |
+ // | +<--------------------+
+ // | | |
+ // (3) | MHTMLGenerationManager |
+ // | ::OnFileClosed |
+ // | | |
+ //
+ // We hope that (Z) happens between (1) and (3) by doing the following:
+ // - From here post TaskX to UI thread. (X) is guaranteed to happen
+ // before timepoint (1) (because posting of (1) happens after
+ // |return false| / before we post TaskX below).
+ // - From (X) post TaskY to FILE thread. Because this posting is done
+ // before (1), we can guarantee that (Y) will happen before (2).
+ // - From (Y) post TaskZ to UI thread. Because this posting is done
+ // before (2), we can guarantee that (Z) will happen before (3).
+ // - We cannot really guarantee that (Y) and (Z) happen *after* (1) - i.e.
+ // execution at (Y?) and (Z?) instead is possible. In practice,
+ // bouncing off of UI and FILE thread does mean (Z) happens after (1).
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE, base::Bind(
+ &GenerateMHTMLAndExitRendererMessageFilter::TaskX,
+ base::Unretained(this)));
+ }
+
+ return false;
+ };
+
+ void TaskX() {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE, base::Bind(
+ &GenerateMHTMLAndExitRendererMessageFilter::TaskY,
+ base::Unretained(this)));
+ }
+
+ void TaskY() {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE, base::Bind(
+ &GenerateMHTMLAndExitRendererMessageFilter::TaskZ,
+ base::Unretained(this)));
+ }
+
+ void TaskZ() {
+ render_process_host_->FastShutdownIfPossible();
+ }
+
+ RenderProcessHostImpl* render_process_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(GenerateMHTMLAndExitRendererMessageFilter);
+};
+
+// Regression test for the crash/race from https://crbug.com/612098.
+IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLAndExitRenderer) {
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
+
+ RenderProcessHostImpl* render_process_host =
+ static_cast<RenderProcessHostImpl*>(
+ shell()->web_contents()->GetRenderProcessHost());
+ scoped_refptr<BrowserMessageFilter> filter =
+ new GenerateMHTMLAndExitRendererMessageFilter(render_process_host);
+ render_process_host->AddFilter(filter.get());
+
+ base::FilePath path(temp_dir_.path());
+ path = path.Append(FILE_PATH_LITERAL("test.mht"));
+ GenerateMHTMLForCurrentPage(MHTMLGenerationParams(path));
+
+ EXPECT_GT(ReadFileSizeFromDisk(path), 100); // Verify the actual file size.
+}
+
IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, InvalidPath) {
base::FilePath path(FILE_PATH_LITERAL("/invalid/file/path"));
@@ -161,7 +400,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLIgnoreNoStore) {
GURL url(embedded_test_server()->GetURL("/nostore.html"));
- // Generate MHTML without specifying the FAIL_FOR_NO_STORE_MAIN_FRAME policy.
+ // Generate MHTML without specifying the FailForNoStoreMainFrame policy.
GenerateMHTML(path, url);
// We expect that there wasn't an error (file size -1 indicates an error.)
@@ -183,10 +422,10 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLObeyNoStoreMainFrame) {
GURL url(embedded_test_server()->GetURL("/nostore.html"));
- // Generate MHTML, specifying the FAIL_FOR_NO_STORE_MAIN_FRAME policy.
+ // Generate MHTML, specifying the FailForNoStoreMainFrame policy.
MHTMLGenerationParams params(path);
params.cache_control_policy =
- content::MHTMLCacheControlPolicy::FAIL_FOR_NO_STORE_MAIN_FRAME;
+ blink::WebFrameSerializerCacheControlPolicy::FailForNoStoreMainFrame;
GenerateMHTML(params, url);
// We expect that there was an error (file size -1 indicates an error.)
@@ -199,6 +438,114 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLObeyNoStoreMainFrame) {
EXPECT_THAT(mhtml, Not(HasSubstr("test body")));
}
+IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest,
+ GenerateMHTMLIgnoreNoStoreSubFrame) {
+ base::FilePath path(temp_dir_.path());
+ path = path.Append(FILE_PATH_LITERAL("test.mht"));
+
+ GURL url(embedded_test_server()->GetURL("/page_with_nostore_iframe.html"));
+
+ // Generate MHTML, specifying the FailForNoStoreMainFrame policy.
+ MHTMLGenerationParams params(path);
+ params.cache_control_policy =
+ blink::WebFrameSerializerCacheControlPolicy::FailForNoStoreMainFrame;
+
+ GenerateMHTML(params, url);
+ // We expect that there was no error (file size -1 indicates an error.)
+ EXPECT_LT(0, file_size());
+
+ std::string mhtml;
+ ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
+
+ EXPECT_THAT(mhtml, HasSubstr("Main Frame"));
+ // Make sure that no-store subresources exist in this mode.
+ EXPECT_THAT(mhtml, HasSubstr("no-store test body"));
+ EXPECT_THAT(mhtml, ContainsRegex("Content-Location:.*nostore.jpg"));
+}
+
+IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLObeyNoStoreSubFrame) {
+ base::FilePath path(temp_dir_.path());
+ path = path.Append(FILE_PATH_LITERAL("test.mht"));
+
+ GURL url(embedded_test_server()->GetURL("/page_with_nostore_iframe.html"));
+
+ // Generate MHTML, specifying the FailForNoStoreMainFrame policy.
+ MHTMLGenerationParams params(path);
+ params.cache_control_policy = blink::WebFrameSerializerCacheControlPolicy::
+ SkipAnyFrameOrResourceMarkedNoStore;
+
+ GenerateMHTML(params, url);
+ // We expect that there was no error (file size -1 indicates an error.)
+ EXPECT_LT(0, file_size());
+
+ std::string mhtml;
+ ASSERT_TRUE(base::ReadFileToString(path, &mhtml));
+
+ EXPECT_THAT(mhtml, HasSubstr("Main Frame"));
+ // Make sure the contents are missing.
+ EXPECT_THAT(mhtml, Not(HasSubstr("no-store test body")));
+ // This image comes from a resource marked no-store.
+ EXPECT_THAT(mhtml, Not(ContainsRegex("Content-Location:.*nostore.jpg")));
+}
+
+// TODO(crbug.com/615291): These fail on Android under some circumstances.
+#if defined(OS_ANDROID)
+#define MAYBE_ViewedMHTMLContainsNoStoreContentIfNoCacheControlPolicy \
+ DISABLED_ViewedMHTMLContainsNoStoreContentIfNoCacheControlPolicy
+#define MAYBE_ViewedMHTMLDoesNotContainNoStoreContent \
+ DISABLED_ViewedMHTMLDoesNotContainNoStoreContent
+#else
+#define MAYBE_ViewedMHTMLContainsNoStoreContentIfNoCacheControlPolicy \
+ ViewedMHTMLContainsNoStoreContentIfNoCacheControlPolicy
+#define MAYBE_ViewedMHTMLDoesNotContainNoStoreContent \
+ ViewedMHTMLDoesNotContainNoStoreContent
+#endif
+
+IN_PROC_BROWSER_TEST_F(
+ MHTMLGenerationTest,
+ MAYBE_ViewedMHTMLContainsNoStoreContentIfNoCacheControlPolicy) {
+ // Generate MHTML, specifying the FailForNoStoreMainFrame policy.
+ base::FilePath path(temp_dir_.path());
+ path = path.Append(FILE_PATH_LITERAL("test.mht"));
+ MHTMLGenerationParams params(path);
+
+ // No special cache control options so we should see both frames.
+ std::vector<std::string> expectations = {
+ "Main Frame, normal headers.", "Cache-Control: no-store test body",
+ };
+ std::vector<std::string> forbidden;
+ TestOriginalVsSavedPage(
+ embedded_test_server()->GetURL("/page_with_nostore_iframe.html"), params,
+ 2 /* expected number of frames */, expectations, forbidden);
+
+ std::string mhtml;
+ ASSERT_TRUE(base::ReadFileToString(params.file_path, &mhtml));
+}
+
+IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest,
+ MAYBE_ViewedMHTMLDoesNotContainNoStoreContent) {
+ // Generate MHTML, specifying the FailForNoStoreMainFrame policy.
+ base::FilePath path(temp_dir_.path());
+ path = path.Append(FILE_PATH_LITERAL("test.mht"));
+ MHTMLGenerationParams params(path);
+ params.cache_control_policy = blink::WebFrameSerializerCacheControlPolicy::
+ SkipAnyFrameOrResourceMarkedNoStore;
+
+ // No special cache control options so we should see both frames.
+ std::vector<std::string> expectations = {
+ "Main Frame, normal headers.",
+ };
+ std::vector<std::string> forbidden = {
+ "Cache-Control: no-store test body",
+ };
+ TestOriginalVsSavedPage(
+ embedded_test_server()->GetURL("/page_with_nostore_iframe.html"), params,
+ 2 /* expected number of frames */, expectations, forbidden);
+
+ std::string mhtml;
+ ASSERT_TRUE(base::ReadFileToString(params.file_path, &mhtml));
+}
+
// Test suite that allows testing --site-per-process against cross-site frames.
// See http://dev.chromium.org/developers/design-documents/site-isolation.
class MHTMLGenerationSitePerProcessTest : public MHTMLGenerationTest {
diff --git a/chromium/content/browser/download/mhtml_generation_manager.cc b/chromium/content/browser/download/mhtml_generation_manager.cc
index 60feca041a6..dc4ef122c21 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.cc
+++ b/chromium/content/browser/download/mhtml_generation_manager.cc
@@ -44,11 +44,15 @@ class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
const GenerateMHTMLCallback& callback() const { return callback_; }
+ // Indicates whether we expect a message from the |sender| at this time.
+ // We expect only one message per frame - therefore calling this method
+ // will always clear |frame_tree_node_id_of_busy_frame_|.
+ bool IsMessageFromFrameExpected(RenderFrameHostImpl* sender);
+
// Handler for FrameHostMsg_SerializeAsMHTMLResponse (a notification from the
// renderer that the MHTML generation for previous frame has finished).
// Returns |true| upon success; |false| otherwise.
bool OnSerializeAsMHTMLResponse(
- RenderFrameHostImpl* sender,
const std::set<std::string>& digests_of_uris_of_serialized_resources);
// Sends IPC to the renderer, asking for MHTML generation of the next frame.
@@ -75,6 +79,8 @@ class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
int exit_code) override;
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
+ void MarkAsFinished();
+
private:
static int64_t CloseFileOnFileThread(base::File file);
void AddFrame(RenderFrameHost* render_frame_host);
@@ -119,6 +125,11 @@ class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
// The callback to call once generation is complete.
const GenerateMHTMLCallback callback_;
+ // Whether the job is finished (set to true only for the short duration of
+ // time between MHTMLGenerationManager::JobFinished is called and the job is
+ // destroyed by MHTMLGenerationManager::OnFileClosed).
+ bool is_finished_;
+
// RAII helper for registering this Job as a RenderProcessHost observer.
ScopedObserver<RenderProcessHost, MHTMLGenerationManager::Job>
observed_renderer_process_host_;
@@ -136,6 +147,7 @@ MHTMLGenerationManager::Job::Job(int job_id,
mhtml_boundary_marker_(net::GenerateMimeMultipartBoundary()),
salt_(base::GenerateGUID()),
callback_(callback),
+ is_finished_(false),
observed_renderer_process_host_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
web_contents->ForEachFrame(base::Bind(
@@ -222,6 +234,15 @@ void MHTMLGenerationManager::Job::RenderProcessExited(
MHTMLGenerationManager::GetInstance()->RenderProcessExited(this);
}
+void MHTMLGenerationManager::Job::MarkAsFinished() {
+ DCHECK(!is_finished_);
+ is_finished_ = true;
+
+ // Stopping RenderProcessExited notifications is needed to avoid calling
+ // JobFinished twice. See also https://crbug.com/612098.
+ observed_renderer_process_host_.RemoveAll();
+}
+
void MHTMLGenerationManager::Job::AddFrame(RenderFrameHost* render_frame_host) {
auto* rfhi = static_cast<RenderFrameHostImpl*>(render_frame_host);
int frame_tree_node_id = rfhi->frame_tree_node()->frame_tree_node_id();
@@ -255,18 +276,21 @@ void MHTMLGenerationManager::Job::CloseFile(
callback);
}
-bool MHTMLGenerationManager::Job::OnSerializeAsMHTMLResponse(
- RenderFrameHostImpl* sender,
- const std::set<std::string>& digests_of_uris_of_serialized_resources) {
- // Sanitize renderer input / reject unexpected messages.
+bool MHTMLGenerationManager::Job::IsMessageFromFrameExpected(
+ RenderFrameHostImpl* sender) {
int sender_id = sender->frame_tree_node()->frame_tree_node_id();
- if (sender_id != frame_tree_node_id_of_busy_frame_) {
- ReceivedBadMessage(sender->GetProcess(),
- bad_message::DWNLD_INVALID_SERIALIZE_AS_MHTML_RESPONSE);
- return false; // Report failure.
- }
+ if (sender_id != frame_tree_node_id_of_busy_frame_)
+ return false;
+
+ // We only expect one message per frame - let's make sure subsequent messages
+ // from the same |sender| will be rejected.
frame_tree_node_id_of_busy_frame_ = FrameTreeNode::kFrameTreeNodeInvalidId;
+ return true;
+}
+
+bool MHTMLGenerationManager::Job::OnSerializeAsMHTMLResponse(
+ const std::set<std::string>& digests_of_uris_of_serialized_resources) {
// Renderer should be deduping resources with the same uris.
DCHECK_EQ(0u, base::STLSetIntersection<std::set<std::string>>(
digests_of_already_serialized_uris_,
@@ -276,7 +300,7 @@ bool MHTMLGenerationManager::Job::OnSerializeAsMHTMLResponse(
digests_of_uris_of_serialized_resources.end());
if (pending_frame_tree_node_ids_.empty())
- return true; // Report success.
+ return true; // Report success - all frames have been processed.
return SendToNextRenderFrame();
}
@@ -323,7 +347,8 @@ void MHTMLGenerationManager::OnSerializeAsMHTMLResponse(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
Job* job = FindJob(job_id);
- if (!job) {
+ if (!job || !job->IsMessageFromFrameExpected(sender)) {
+ NOTREACHED();
ReceivedBadMessage(sender->GetProcess(),
bad_message::DWNLD_INVALID_SERIALIZE_AS_MHTML_RESPONSE);
return;
@@ -335,7 +360,7 @@ void MHTMLGenerationManager::OnSerializeAsMHTMLResponse(
}
if (!job->OnSerializeAsMHTMLResponse(
- sender, digests_of_uris_of_serialized_resources)) {
+ digests_of_uris_of_serialized_resources)) {
JobFinished(job, JobStatus::FAILURE);
return;
}
@@ -388,6 +413,7 @@ void MHTMLGenerationManager::JobFinished(Job* job, JobStatus job_status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(job);
+ job->MarkAsFinished();
job->CloseFile(
base::Bind(&MHTMLGenerationManager::OnFileClosed,
base::Unretained(this), // Safe b/c |this| is a singleton.
diff --git a/chromium/content/browser/download/mhtml_generation_manager.h b/chromium/content/browser/download/mhtml_generation_manager.h
index d360cce0ac6..50d5bebc702 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.h
+++ b/chromium/content/browser/download/mhtml_generation_manager.h
@@ -28,6 +28,10 @@ class WebContents;
// The class and all of its members live on the UI thread. Only static methods
// are executed on other threads.
+//
+// MHTMLGenerationManager is a singleton. Each call to SaveMHTML method creates
+// a new instance of MHTMLGenerationManager::Job that tracks generation of a
+// single MHTML file.
class MHTMLGenerationManager {
public:
static MHTMLGenerationManager* GetInstance();
@@ -37,8 +41,8 @@ class MHTMLGenerationManager {
// generated file. On failure |file_size| is -1.
typedef base::Callback<void(int64_t file_size)> GenerateMHTMLCallback;
- // Instructs the render view to generate a MHTML representation of the current
- // page for |web_contents|.
+ // Instructs the RenderFrames in |web_contents| to generate a MHTML
+ // representation of the current page.
void SaveMHTML(WebContents* web_contents,
const MHTMLGenerationParams& params,
const GenerateMHTMLCallback& callback);
diff --git a/chromium/content/browser/download/save_file_manager.cc b/chromium/content/browser/download/save_file_manager.cc
index 527a7a18fbb..aed8eb0e0ca 100644
--- a/chromium/content/browser/download/save_file_manager.cc
+++ b/chromium/content/browser/download/save_file_manager.cc
@@ -19,7 +19,6 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
-#include "net/base/filename_util.h"
#include "net/base/io_buffer.h"
#include "url/gurl.h"
@@ -324,41 +323,6 @@ void SaveFileManager::CancelSave(SaveItemId save_item_id) {
}
}
-// It is possible that SaveItem which has specified save_item_id has been
-// canceled
-// before this function runs. So if we can not find corresponding SaveFile by
-// using specified save_item_id, just return.
-void SaveFileManager::SaveLocalFile(const GURL& original_file_url,
- SaveItemId save_item_id,
- SavePackageId save_package_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- SaveFile* save_file = LookupSaveFile(save_item_id);
- if (!save_file)
- return;
- // If it has finished, just return.
- if (!save_file->InProgress())
- return;
-
- // Close the save file before the copy operation.
- save_file->Finish();
- save_file->Detach();
-
- DCHECK(original_file_url.SchemeIsFile());
- base::FilePath file_path;
- net::FileURLToFilePath(original_file_url, &file_path);
- // If we can not get valid file path from original URL, treat it as
- // disk error.
- if (file_path.empty())
- SaveFinished(save_item_id, save_package_id, false);
-
- // Copy the local file to the temporary file. It will be renamed to its
- // final name later.
- bool success = base::CopyFile(file_path, save_file->FullPath());
- if (!success)
- base::DeleteFile(save_file->FullPath(), false);
- SaveFinished(save_item_id, save_package_id, success);
-}
-
void SaveFileManager::OnDeleteDirectoryOrFile(const base::FilePath& full_path,
bool is_dir) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
diff --git a/chromium/content/browser/download/save_file_resource_handler.cc b/chromium/content/browser/download/save_file_resource_handler.cc
index 7cba445aad5..2c1c5526ca4 100644
--- a/chromium/content/browser/download/save_file_resource_handler.cc
+++ b/chromium/content/browser/download/save_file_resource_handler.cc
@@ -16,13 +16,15 @@
namespace content {
-SaveFileResourceHandler::SaveFileResourceHandler(net::URLRequest* request,
- SaveItemId save_item_id,
- SavePackageId save_package_id,
- int render_process_host_id,
- int render_frame_routing_id,
- const GURL& url,
- SaveFileManager* manager)
+SaveFileResourceHandler::SaveFileResourceHandler(
+ net::URLRequest* request,
+ SaveItemId save_item_id,
+ SavePackageId save_package_id,
+ int render_process_host_id,
+ int render_frame_routing_id,
+ const GURL& url,
+ SaveFileManager* manager,
+ AuthorizationState authorization_state)
: ResourceHandler(request),
save_item_id_(save_item_id),
save_package_id_(save_package_id),
@@ -30,7 +32,8 @@ SaveFileResourceHandler::SaveFileResourceHandler(net::URLRequest* request,
render_frame_routing_id_(render_frame_routing_id),
url_(url),
content_length_(0),
- save_manager_(manager) {}
+ save_manager_(manager),
+ authorization_state_(authorization_state) {}
SaveFileResourceHandler::~SaveFileResourceHandler() {
}
@@ -57,7 +60,7 @@ bool SaveFileResourceHandler::OnResponseStarted(ResourceResponse* response,
}
bool SaveFileResourceHandler::OnWillStart(const GURL& url, bool* defer) {
- return true;
+ return authorization_state_ == AuthorizationState::AUTHORIZED;
}
bool SaveFileResourceHandler::OnBeforeNetworkStart(const GURL& url,
@@ -68,6 +71,7 @@ bool SaveFileResourceHandler::OnBeforeNetworkStart(const GURL& url,
bool SaveFileResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) {
+ DCHECK_EQ(AuthorizationState::AUTHORIZED, authorization_state_);
DCHECK(buf && buf_size);
if (!read_buffer_.get()) {
*buf_size = min_size < 0 ? kReadBufSize : min_size;
@@ -78,6 +82,7 @@ bool SaveFileResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
}
bool SaveFileResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
+ DCHECK_EQ(AuthorizationState::AUTHORIZED, authorization_state_);
DCHECK(read_buffer_.get());
// We are passing ownership of this buffer to the save file manager.
scoped_refptr<net::IOBuffer> buffer;
@@ -93,6 +98,9 @@ void SaveFileResourceHandler::OnResponseCompleted(
const net::URLRequestStatus& status,
const std::string& security_info,
bool* defer) {
+ if (authorization_state_ != AuthorizationState::AUTHORIZED)
+ DCHECK(!status.is_success());
+
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&SaveFileManager::SaveFinished, save_manager_, save_item_id_,
diff --git a/chromium/content/browser/download/save_file_resource_handler.h b/chromium/content/browser/download/save_file_resource_handler.h
index e559e44a63e..2644dcc124f 100644
--- a/chromium/content/browser/download/save_file_resource_handler.h
+++ b/chromium/content/browser/download/save_file_resource_handler.h
@@ -25,13 +25,26 @@ class SaveFileManager;
// Forwards data to the save thread.
class SaveFileResourceHandler : public ResourceHandler {
public:
+ // Unauthorized requests are cancelled from OnWillStart callback.
+ //
+ // This way of handling unauthorized requests allows unified handling of all
+ // SaveFile requests - communicating the failure to OnResponseCompleted
+ // happens in a generic, typical way, reusing common infrastructure code
+ // (rather than forcing an ad-hoc, Save-File-specific call to
+ // OnResponseCompleted from ResourceDispatcherHostImpl::BeginSaveFile).
+ enum class AuthorizationState {
+ AUTHORIZED,
+ NOT_AUTHORIZED,
+ };
+
SaveFileResourceHandler(net::URLRequest* request,
SaveItemId save_item_id,
SavePackageId save_package_id,
int render_process_host_id,
int render_frame_routing_id,
const GURL& url,
- SaveFileManager* manager);
+ SaveFileManager* manager,
+ AuthorizationState authorization_state);
~SaveFileResourceHandler() override;
// ResourceHandler Implementation:
@@ -88,6 +101,8 @@ class SaveFileResourceHandler : public ResourceHandler {
int64_t content_length_;
SaveFileManager* save_manager_;
+ AuthorizationState authorization_state_;
+
static const int kReadBufSize = 32768; // bytes
DISALLOW_COPY_AND_ASSIGN(SaveFileResourceHandler);
diff --git a/chromium/content/browser/download/save_item.cc b/chromium/content/browser/download/save_item.cc
index 5fa262778e8..9bff4fa482f 100644
--- a/chromium/content/browser/download/save_item.cc
+++ b/chromium/content/browser/download/save_item.cc
@@ -28,23 +28,23 @@ SaveItem::SaveItem(const GURL& url,
const Referrer& referrer,
SavePackage* package,
SaveFileCreateInfo::SaveFileSource save_source,
- int frame_tree_node_id)
+ int frame_tree_node_id,
+ int container_frame_tree_node_id)
: save_item_id_(GetNextSaveItemId()),
url_(url),
referrer_(referrer),
frame_tree_node_id_(frame_tree_node_id),
+ container_frame_tree_node_id_(container_frame_tree_node_id),
total_bytes_(0),
received_bytes_(0),
state_(WAIT_START),
- has_final_name_(false),
is_success_(false),
save_source_(save_source),
package_(package) {
DCHECK(package);
}
-SaveItem::~SaveItem() {
-}
+SaveItem::~SaveItem() {}
// Set start state for save item.
void SaveItem::Start() {
@@ -81,9 +81,8 @@ void SaveItem::Cancel() {
// Small downloads might be complete before method has a chance to run.
return;
}
- state_ = CANCELED;
- is_success_ = false;
Finish(received_bytes_, false);
+ state_ = CANCELED;
package_->SaveCanceled(this);
}
@@ -95,33 +94,9 @@ void SaveItem::Finish(int64_t size, bool is_success) {
UpdateSize(size);
}
-// Calculate the percentage of the save item
-int SaveItem::PercentComplete() const {
- switch (state_) {
- case COMPLETE:
- case CANCELED:
- return 100;
- case WAIT_START:
- return 0;
- case IN_PROGRESS: {
- int percent = 0;
- if (total_bytes_ > 0)
- percent = static_cast<int>(received_bytes_ * 100.0 / total_bytes_);
- return percent;
- }
- default: {
- NOTREACHED();
- return -1;
- }
- }
-}
-
-// Rename the save item with new path.
-void SaveItem::Rename(const base::FilePath& full_path) {
+void SaveItem::SetTargetPath(const base::FilePath& full_path) {
DCHECK(!full_path.empty() && !has_final_name());
full_path_ = full_path;
- file_name_ = full_path_.BaseName();
- has_final_name_ = true;
}
void SaveItem::SetTotalBytes(int64_t total_bytes) {
diff --git a/chromium/content/browser/download/save_item.h b/chromium/content/browser/download/save_item.h
index ef463953bf7..049c7f3936a 100644
--- a/chromium/content/browser/download/save_item.h
+++ b/chromium/content/browser/download/save_item.h
@@ -31,7 +31,8 @@ class SaveItem {
const Referrer& referrer,
SavePackage* package,
SaveFileCreateInfo::SaveFileSource save_source,
- int frame_tree_node_id);
+ int frame_tree_node_id,
+ int container_frame_tree_node_id);
~SaveItem();
@@ -46,12 +47,8 @@ class SaveItem {
// Saving operation completed.
void Finish(int64_t size, bool is_success);
- // Rough percent complete, -1 means we don't know (since we didn't receive a
- // total size).
- int PercentComplete() const;
-
// Update path for SaveItem, the actual file is renamed on the file thread.
- void Rename(const base::FilePath& full_path);
+ void SetTargetPath(const base::FilePath& full_path);
void SetTotalBytes(int64_t total_bytes);
@@ -59,18 +56,18 @@ class SaveItem {
SaveItemId id() const { return save_item_id_; }
SaveState state() const { return state_; }
const base::FilePath& full_path() const { return full_path_; }
- const base::FilePath& file_name() const { return file_name_; }
const GURL& url() const { return url_; }
const Referrer& referrer() const { return referrer_; }
int frame_tree_node_id() const { return frame_tree_node_id_; }
- int64_t total_bytes() const { return total_bytes_; }
+ int container_frame_tree_node_id() const {
+ return container_frame_tree_node_id_;
+ }
int64_t received_bytes() const { return received_bytes_; }
- bool has_final_name() const { return has_final_name_; }
+ bool has_final_name() const { return !full_path_.empty(); }
bool success() const { return is_success_; }
SaveFileCreateInfo::SaveFileSource save_source() const {
return save_source_;
}
- SavePackage* package() const { return package_; }
private:
// Internal helper for maintaining consistent received and total sizes.
@@ -82,17 +79,19 @@ class SaveItem {
// Full path to the save item file.
base::FilePath full_path_;
- // Short display version of the file.
- base::FilePath file_name_;
-
// The URL for this save item.
GURL url_;
Referrer referrer_;
// Frame tree node id, if this save item represents a frame
- // (otherwise FrameTreeNode::kFrameTreeNodeInvalidID).
+ // (otherwise FrameTreeNode::kFrameTreeNodeInvalidId).
int frame_tree_node_id_;
+ // Frame tree node id of the frame containing this save item.
+ // (FrameTreeNode::kFrameTreeNodeInvalidId if this save item represents the
+ // main frame, which obviously doesn't have a containing/parent frame).
+ int container_frame_tree_node_id_;
+
// Total bytes expected.
int64_t total_bytes_;
@@ -102,9 +101,6 @@ class SaveItem {
// The current state of this save item.
SaveState state_;
- // Specifies if this name is a final or not.
- bool has_final_name_;
-
// Flag indicates whether SaveItem has error while in saving process.
bool is_success_;
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index 7704eb4aae2..1a21d4125b1 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -90,21 +90,21 @@ const uint32_t kMaxFileOrdinalNumberPartLength = 6;
// file names, i.e. those stripped of their extensions.
// TODO(estade): improve this to not choke on alternate encodings.
base::FilePath::StringType StripOrdinalNumber(
- const base::FilePath::StringType& pure_file_name) {
+ const base::FilePath::StringType& base_name) {
base::FilePath::StringType::size_type r_paren_index =
- pure_file_name.rfind(FILE_PATH_LITERAL(')'));
+ base_name.rfind(FILE_PATH_LITERAL(')'));
base::FilePath::StringType::size_type l_paren_index =
- pure_file_name.rfind(FILE_PATH_LITERAL('('));
+ base_name.rfind(FILE_PATH_LITERAL('('));
if (l_paren_index >= r_paren_index)
- return pure_file_name;
+ return base_name;
for (base::FilePath::StringType::size_type i = l_paren_index + 1;
i != r_paren_index; ++i) {
- if (!base::IsAsciiDigit(pure_file_name[i]))
- return pure_file_name;
+ if (!base::IsAsciiDigit(base_name[i]))
+ return base_name;
}
- return pure_file_name.substr(0, l_paren_index);
+ return base_name.substr(0, l_paren_index);
}
// Check whether we can save page as complete-HTML for the contents which
@@ -140,31 +140,32 @@ class SavePackageRequestHandle : public DownloadRequestHandleInterface {
const base::FilePath::CharType SavePackage::kDefaultHtmlExtension[] =
FILE_PATH_LITERAL("html");
+SavePackage::SavePackage(WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ page_url_(GetUrlToBeSaved(web_contents)),
+ title_(web_contents->GetTitle()),
+ start_tick_(base::TimeTicks::Now()),
+ file_name_set_(&base::FilePath::CompareLessIgnoreCase),
+ unique_id_(GetNextSavePackageId()) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ InternalInit();
+}
+
+// Used for tests.
SavePackage::SavePackage(WebContents* web_contents,
SavePageType save_type,
const base::FilePath& file_full_path,
const base::FilePath& directory_full_path)
: WebContentsObserver(web_contents),
- number_of_frames_pending_response_(0),
- file_manager_(nullptr),
- download_manager_(nullptr),
- download_(nullptr),
- page_url_(GetUrlToBeSaved()),
+ page_url_(GetUrlToBeSaved(web_contents)),
saved_main_file_path_(file_full_path),
saved_main_directory_path_(directory_full_path),
title_(web_contents->GetTitle()),
start_tick_(base::TimeTicks::Now()),
- finished_(false),
- user_canceled_(false),
- disk_error_occurred_(false),
save_type_(save_type),
- all_save_items_count_(0),
file_name_set_(&base::FilePath::CompareLessIgnoreCase),
- wait_state_(INITIALIZE),
- unique_id_(GetNextSavePackageId()),
- wrote_to_completed_file_(false),
- wrote_to_failed_file_(false) {
- DCHECK(page_url_.is_valid());
+ unique_id_(GetNextSavePackageId()) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK((save_type_ == SAVE_PAGE_TYPE_AS_ONLY_HTML) ||
(save_type_ == SAVE_PAGE_TYPE_AS_MHTML) ||
(save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML))
@@ -176,55 +177,8 @@ SavePackage::SavePackage(WebContents* web_contents,
InternalInit();
}
-SavePackage::SavePackage(WebContents* web_contents)
- : WebContentsObserver(web_contents),
- number_of_frames_pending_response_(0),
- file_manager_(nullptr),
- download_manager_(nullptr),
- download_(nullptr),
- page_url_(GetUrlToBeSaved()),
- title_(web_contents->GetTitle()),
- start_tick_(base::TimeTicks::Now()),
- finished_(false),
- user_canceled_(false),
- disk_error_occurred_(false),
- save_type_(SAVE_PAGE_TYPE_UNKNOWN),
- all_save_items_count_(0),
- file_name_set_(&base::FilePath::CompareLessIgnoreCase),
- wait_state_(INITIALIZE),
- unique_id_(GetNextSavePackageId()),
- wrote_to_completed_file_(false),
- wrote_to_failed_file_(false) {
- DCHECK(page_url_.is_valid());
- InternalInit();
-}
-
-// This is for testing use. Set |finished_| as true because we don't want
-// method Cancel to be be called in destructor in test mode.
-// We also don't call InternalInit().
-SavePackage::SavePackage(WebContents* web_contents,
- const base::FilePath& file_full_path,
- const base::FilePath& directory_full_path)
- : WebContentsObserver(web_contents),
- number_of_frames_pending_response_(0),
- file_manager_(nullptr),
- download_manager_(nullptr),
- download_(nullptr),
- saved_main_file_path_(file_full_path),
- saved_main_directory_path_(directory_full_path),
- start_tick_(base::TimeTicks::Now()),
- finished_(true),
- user_canceled_(false),
- disk_error_occurred_(false),
- save_type_(SAVE_PAGE_TYPE_UNKNOWN),
- all_save_items_count_(0),
- file_name_set_(&base::FilePath::CompareLessIgnoreCase),
- wait_state_(INITIALIZE),
- unique_id_(GetNextSavePackageId()),
- wrote_to_completed_file_(false),
- wrote_to_failed_file_(false) {}
-
SavePackage::~SavePackage() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Stop receiving saving job's updates
if (!finished_ && !canceled()) {
// Unexpected quit.
@@ -252,17 +206,20 @@ SavePackage::~SavePackage() {
file_manager_ = nullptr;
}
-GURL SavePackage::GetUrlToBeSaved() {
- // Instead of using web_contents_.GetURL here, we use url() (which is the
+// static
+GURL SavePackage::GetUrlToBeSaved(WebContents* web_contents) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Instead of using web_contents->GetURL here, we call GetURL() (which is the
// "real" url of the page) from the NavigationEntry because it reflects its
- // origin rather than the displayed one (returned by GetURL) which may be
- // different (like having "view-source:" on the front).
+ // origin rather than the displayed one (returned by GetVirtualURL) which may
+ // be different (like having "view-source:" on the front).
NavigationEntry* visible_entry =
- web_contents()->GetController().GetVisibleEntry();
+ web_contents->GetController().GetVisibleEntry();
return visible_entry ? visible_entry->GetURL() : GURL::EmptyGURL();
}
void SavePackage::Cancel(bool user_action) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!canceled()) {
if (user_action)
user_canceled_ = true;
@@ -276,12 +233,9 @@ void SavePackage::Cancel(bool user_action) {
// Init() can be called directly, or indirectly via GetSaveInfo(). In both
// cases, we need file_manager_ to be initialized, so we do this first.
void SavePackage::InternalInit() {
- ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
- if (!rdh) {
- NOTREACHED();
- return;
- }
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
file_manager_ = rdh->save_file_manager();
DCHECK(file_manager_);
@@ -296,6 +250,7 @@ void SavePackage::InternalInit() {
bool SavePackage::Init(
const SavePackageDownloadCreatedCallback& download_created_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(page_url_.is_valid());
// Set proper running state.
if (wait_state_ != INITIALIZE)
return false;
@@ -346,13 +301,11 @@ void SavePackage::InitWithDownloadItem(
} else {
DCHECK_EQ(SAVE_PAGE_TYPE_AS_ONLY_HTML, save_type_);
wait_state_ = NET_FILES;
- SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ?
- SaveFileCreateInfo::SAVE_FILE_FROM_FILE :
- SaveFileCreateInfo::SAVE_FILE_FROM_NET;
// Add this item to waiting list.
- waiting_item_queue_.push_back(
- new SaveItem(page_url_, Referrer(), this, save_source,
- FrameTreeNode::kFrameTreeNodeInvalidId));
+ waiting_item_queue_.push_back(new SaveItem(
+ page_url_, Referrer(), this, SaveFileCreateInfo::SAVE_FILE_FROM_NET,
+ FrameTreeNode::kFrameTreeNodeInvalidId,
+ web_contents()->GetMainFrame()->GetFrameTreeNodeId()));
all_save_items_count_ = 1;
download_->SetTotalBytes(1);
@@ -361,6 +314,7 @@ void SavePackage::InitWithDownloadItem(
}
void SavePackage::OnMHTMLGenerated(int64_t size) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (size <= 0) {
Cancel(false);
return;
@@ -388,7 +342,7 @@ void SavePackage::OnMHTMLGenerated(int64_t size) {
}
}
-// On POSIX, the length of |pure_file_name| + |file_name_ext| is further
+// On POSIX, the length of |base_name| + |file_name_ext| is further
// restricted by NAME_MAX. The maximum allowed path looks like:
// '/path/to/save_dir' + '/' + NAME_MAX.
uint32_t SavePackage::GetMaxPathLengthForDirectory(
@@ -402,29 +356,12 @@ uint32_t SavePackage::GetMaxPathLengthForDirectory(
#endif
}
-// File name is considered being consist of pure file name, dot and file
-// extension name. File name might has no dot and file extension, or has
-// multiple dot inside file name. The dot, which separates the pure file
-// name and file extension name, is last dot in the whole file name.
-// This function is for making sure the length of specified file path is not
-// great than the specified maximum length of file path and getting safe pure
-// file name part if the input pure file name is too long.
-// The parameter |dir_path| specifies directory part of the specified
-// file path. The parameter |file_name_ext| specifies file extension
-// name part of the specified file path (including start dot). The parameter
-// |max_file_path_len| specifies maximum length of the specified file path.
-// The parameter |pure_file_name| input pure file name part of the specified
-// file path. If the length of specified file path is great than
-// |max_file_path_len|, the |pure_file_name| will output new pure file name
-// part for making sure the length of specified file path is less than
-// specified maximum length of file path. Return false if the function can
-// not get a safe pure file name, otherwise it returns true.
-bool SavePackage::GetSafePureFileName(
+bool SavePackage::TruncateBaseNameToFitPathConstraints(
const base::FilePath& dir_path,
const base::FilePath::StringType& file_name_ext,
uint32_t max_file_path_len,
- base::FilePath::StringType* pure_file_name) {
- DCHECK(!pure_file_name->empty());
+ base::FilePath::StringType* base_name) {
+ DCHECK(!base_name->empty());
int available_length = static_cast<int>(max_file_path_len -
dir_path.value().length() -
file_name_ext.length());
@@ -433,17 +370,17 @@ bool SavePackage::GetSafePureFileName(
--available_length;
// Plenty of room.
- if (static_cast<int>(pure_file_name->length()) <= available_length)
+ if (static_cast<int>(base_name->length()) <= available_length)
return true;
- // Limited room. Truncate |pure_file_name| to fit.
+ // Limited room. Truncate |base_name| to fit.
if (available_length > 0) {
- *pure_file_name = pure_file_name->substr(0, available_length);
+ *base_name = base_name->substr(0, available_length);
return true;
}
- // Not enough room to even use a shortened |pure_file_name|.
- pure_file_name->clear();
+ // Not enough room to even use a shortened |base_name|.
+ base_name->clear();
return false;
}
@@ -462,25 +399,29 @@ bool SavePackage::GenerateFileName(const std::string& disposition,
kDefaultSaveName);
DCHECK(!file_path.empty());
- base::FilePath::StringType pure_file_name =
+ if (need_html_ext)
+ file_path = file_path.ReplaceExtension(kDefaultHtmlExtension);
+
+ DownloadManagerDelegate* delegate = download_manager_->GetDelegate();
+ if (delegate)
+ delegate->SanitizeSavePackageResourceName(&file_path);
+
+ DCHECK_EQ(file_path.value(), file_path.BaseName().value())
+ << "SanitizeSavePackageResourceName should only return a basename.";
+
+ base::FilePath::StringType base_name =
file_path.RemoveExtension().BaseName().value();
base::FilePath::StringType file_name_ext = file_path.Extension();
- // If it is HTML resource, use ".html" as its extension.
- if (need_html_ext) {
- file_name_ext = FILE_PATH_LITERAL(".");
- file_name_ext.append(kDefaultHtmlExtension);
- }
-
// Need to make sure the suggested file name is not too long.
uint32_t max_path = GetMaxPathLengthForDirectory(saved_main_directory_path_);
// Get safe pure file name.
- if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext,
- max_path, &pure_file_name))
+ if (!TruncateBaseNameToFitPathConstraints(
+ saved_main_directory_path_, file_name_ext, max_path, &base_name))
return false;
- base::FilePath::StringType file_name = pure_file_name + file_name_ext;
+ base::FilePath::StringType file_name = base_name + file_name_ext;
// Check whether we already have same name in a case insensitive manner.
FileNameSet::const_iterator iter = file_name_set_.find(file_name);
@@ -488,15 +429,14 @@ bool SavePackage::GenerateFileName(const std::string& disposition,
file_name_set_.insert(file_name);
} else {
// Found same name, increase the ordinal number for the file name.
- pure_file_name =
- base::FilePath(*iter).RemoveExtension().BaseName().value();
- base::FilePath::StringType base_file_name =
- StripOrdinalNumber(pure_file_name);
+ base_name = base::FilePath(*iter).RemoveExtension().BaseName().value();
+ base::FilePath::StringType base_file_name = StripOrdinalNumber(base_name);
// We need to make sure the length of base file name plus maximum ordinal
// number path will be less than or equal to kMaxFilePathLength.
- if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext,
- max_path - kMaxFileOrdinalNumberPartLength, &base_file_name))
+ if (!TruncateBaseNameToFitPathConstraints(
+ saved_main_directory_path_, file_name_ext,
+ max_path - kMaxFileOrdinalNumberPartLength, &base_file_name))
return false;
// Prepare the new ordinal number.
@@ -517,9 +457,9 @@ bool SavePackage::GenerateFileName(const std::string& disposition,
base::CreateTemporaryFile(&temp_file);
file_name = temp_file.RemoveExtension().BaseName().value();
// Get safe pure file name.
- if (!GetSafePureFileName(saved_main_directory_path_,
- base::FilePath::StringType(),
- max_path, &file_name))
+ if (!TruncateBaseNameToFitPathConstraints(saved_main_directory_path_,
+ base::FilePath::StringType(),
+ max_path, &file_name))
return false;
} else {
for (int i = ordinal_number; i < kMaxFileOrdinalNumber; ++i) {
@@ -546,6 +486,7 @@ bool SavePackage::GenerateFileName(const std::string& disposition,
// We have received a message from SaveFileManager about a new saving job. We
// find a SaveItem and store it in our in_progress list.
void SavePackage::StartSave(const SaveFileCreateInfo* info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(info);
SaveItemIdMap::iterator it = in_progress_items_.find(info->save_item_id);
@@ -597,20 +538,10 @@ void SavePackage::StartSave(const SaveFileCreateInfo* info) {
// rename the SaveItem.
base::FilePath final_name =
saved_main_directory_path_.Append(generated_name);
- save_item->Rename(final_name);
+ save_item->SetTargetPath(final_name);
} else {
// It is the main HTML file, use the name chosen by the user.
- save_item->Rename(saved_main_file_path_);
- }
-
- // If the save source is from file system, inform SaveFileManager to copy
- // corresponding file to the file path which this SaveItem specifies.
- if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::SaveLocalFile, file_manager_,
- save_item->url(), save_item->id(), id()));
- return;
+ save_item->SetTargetPath(saved_main_file_path_);
}
// Check whether we begin to require serialized HTML data.
@@ -622,7 +553,8 @@ void SavePackage::StartSave(const SaveFileCreateInfo* info) {
}
}
-SaveItem* SavePackage::LookupSaveItemInProcess(SaveItemId save_item_id) {
+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;
@@ -633,6 +565,7 @@ SaveItem* SavePackage::LookupSaveItemInProcess(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());
DCHECK(it != in_progress_items_.end());
DCHECK_EQ(save_item, it->second);
@@ -648,9 +581,10 @@ void SavePackage::PutInProgressItemToSavedMap(SaveItem* save_item) {
bool SavePackage::UpdateSaveProgress(SaveItemId save_item_id,
int64_t size,
bool write_success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Because we might have canceled this saving job before,
// so we might not find corresponding SaveItem.
- SaveItem* save_item = LookupSaveItemInProcess(save_item_id);
+ SaveItem* save_item = LookupInProgressSaveItem(save_item_id);
if (!save_item)
return false;
@@ -667,6 +601,7 @@ bool SavePackage::UpdateSaveProgress(SaveItemId save_item_id,
// Stop all page saving jobs that are in progress and instruct the FILE thread
// to delete all saved files.
void SavePackage::Stop() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// If we haven't moved out of the initial state, there's nothing to cancel and
// there won't be valid pointers for |file_manager_| or |download_|.
if (wait_state_ == INITIALIZE)
@@ -711,6 +646,7 @@ void SavePackage::Stop() {
}
void SavePackage::CheckFinish() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (in_process_count() || finished_)
return;
@@ -735,6 +671,7 @@ void SavePackage::CheckFinish() {
// Successfully finished all items of this SavePackage.
void SavePackage::Finish() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// User may cancel the job when we're moving files to the final directory.
if (canceled())
return;
@@ -785,9 +722,10 @@ void SavePackage::Finish() {
void SavePackage::SaveFinished(SaveItemId save_item_id,
int64_t size,
bool is_success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Because we might have canceled this saving job before,
// so we might not find corresponding SaveItem. Just ignore it.
- SaveItem* save_item = LookupSaveItemInProcess(save_item_id);
+ SaveItem* save_item = LookupInProgressSaveItem(save_item_id);
if (!save_item)
return;
@@ -835,6 +773,7 @@ void SavePackage::SaveCanceled(const SaveItem* save_item) {
}
void SavePackage::SaveNextFile(bool process_all_remaining_items) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(web_contents());
DCHECK(!waiting_item_queue_.empty());
@@ -847,16 +786,36 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) {
DCHECK(!ContainsKey(in_progress_items_, save_item->id()));
in_progress_items_[save_item->id()] = save_item;
save_item->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();
+ 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);
+ continue;
+ }
+ RenderFrameHostImpl* requester_frame =
+ requester_frame_tree_node->current_frame_host();
+
file_manager_->SaveURL(
save_item->id(), save_item->url(), save_item->referrer(),
- web_contents()->GetRenderProcessHost()->GetID(), routing_id(),
- web_contents()->GetMainFrame()->GetRoutingID(),
- save_item->save_source(), save_item->full_path(),
+ requester_frame->GetProcess()->GetID(),
+ requester_frame->render_view_host()->GetRoutingID(),
+ requester_frame->routing_id(), save_item->save_source(),
+ save_item->full_path(),
web_contents()->GetBrowserContext()->GetResourceContext(), this);
} while (process_all_remaining_items && !waiting_item_queue_.empty());
}
int SavePackage::PercentComplete() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!all_save_items_count_)
return 0;
if (!in_process_count())
@@ -865,12 +824,14 @@ int SavePackage::PercentComplete() {
}
int64_t SavePackage::CurrentSpeed() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::TimeDelta diff = base::TimeTicks::Now() - start_tick_;
int64_t diff_ms = diff.InMilliseconds();
return diff_ms == 0 ? 0 : completed_count() * 1000 / diff_ms;
}
void SavePackage::DoSavingProcess() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML) {
// We guarantee that images and JavaScripts must be downloaded first.
// So when finishing all those sub-resources, we will know which
@@ -931,6 +892,7 @@ bool SavePackage::OnMessageReceived(const IPC::Message& message,
// map:(originalURL:currentLocalPath) to render process (backend).
// Then render process will serialize DOM and send data to us.
void SavePackage::GetSerializedHtmlWithLocalLinks() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (wait_state_ != HTML_DATA)
return;
@@ -979,6 +941,7 @@ void SavePackage::GetSerializedHtmlWithLocalLinks() {
void SavePackage::GetSerializedHtmlWithLocalLinksForFrame(
FrameTreeNode* target_tree_node) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(target_tree_node);
int target_frame_tree_node_id = target_tree_node->frame_tree_node_id();
RenderFrameHostImpl* target = target_tree_node->current_frame_host();
@@ -1005,7 +968,7 @@ void SavePackage::GetSerializedHtmlWithLocalLinksForFrame(
if (target_tree_node->IsMainFrame()) {
local_path = local_path.Append(saved_main_directory_path_.BaseName());
}
- local_path = local_path.Append(save_item->file_name());
+ local_path = local_path.Append(save_item->full_path().BaseName());
// Insert the link into |url_to_local_path| or |routing_id_to_local_path|.
if (save_item->save_source() != SaveFileCreateInfo::SAVE_FILE_FROM_DOM) {
@@ -1042,6 +1005,7 @@ void SavePackage::OnSerializedHtmlWithLocalLinksResponse(
RenderFrameHostImpl* sender,
const std::string& data,
bool end_of_data) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Check current state.
if (wait_state_ != HTML_DATA)
return;
@@ -1100,6 +1064,7 @@ void SavePackage::OnSerializedHtmlWithLocalLinksResponse(
// Ask for all savable resource links from backend, include main frame and
// sub-frame.
void SavePackage::GetSavableResourceLinks() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (wait_state_ != START_PROCESS)
return;
@@ -1125,6 +1090,7 @@ void SavePackage::OnSavableResourceLinksResponse(
const std::vector<GURL>& resources_list,
const Referrer& referrer,
const std::vector<SavableSubframe>& subframes) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (wait_state_ != RESOURCES_LIST)
return;
@@ -1165,9 +1131,11 @@ SaveItem* SavePackage::CreatePendingSaveItem(
const GURL& url,
const Referrer& referrer,
SaveFileCreateInfo::SaveFileSource save_source) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
Referrer sanitized_referrer = Referrer::SanitizeForRequest(url, referrer);
- SaveItem* save_item = new SaveItem(url, sanitized_referrer, this, save_source,
- save_item_frame_tree_node_id);
+ 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);
frame_tree_node_id_to_contained_save_items_[container_frame_tree_node_id]
@@ -1181,6 +1149,7 @@ SaveItem* SavePackage::CreatePendingSaveItemDeduplicatingByUrl(
const GURL& url,
const Referrer& referrer,
SaveFileCreateInfo::SaveFileSource save_source) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(url.is_valid()); // |url| should be validated by the callers.
// Frames should not be deduplicated by URL.
@@ -1205,20 +1174,19 @@ SaveItem* SavePackage::CreatePendingSaveItemDeduplicatingByUrl(
void SavePackage::EnqueueSavableResource(int container_frame_tree_node_id,
const GURL& url,
const Referrer& referrer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!url.is_valid())
return;
- SaveFileCreateInfo::SaveFileSource save_source =
- url.SchemeIsFile() ? SaveFileCreateInfo::SAVE_FILE_FROM_FILE
- : SaveFileCreateInfo::SAVE_FILE_FROM_NET;
CreatePendingSaveItemDeduplicatingByUrl(
container_frame_tree_node_id, FrameTreeNode::kFrameTreeNodeInvalidId, url,
- referrer, save_source);
+ referrer, SaveFileCreateInfo::SAVE_FILE_FROM_NET);
}
void SavePackage::EnqueueFrame(int container_frame_tree_node_id,
int frame_tree_node_id,
const GURL& frame_original_url) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
SaveItem* save_item = CreatePendingSaveItem(
container_frame_tree_node_id, frame_tree_node_id, frame_original_url,
Referrer(), SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
@@ -1227,10 +1195,12 @@ void SavePackage::EnqueueFrame(int container_frame_tree_node_id,
}
void SavePackage::OnSavableResourceLinksError(RenderFrameHostImpl* sender) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
CompleteSavableResourceLinksResponse();
}
void SavePackage::CompleteSavableResourceLinksResponse() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
--number_of_frames_pending_response_;
DCHECK_LE(0, number_of_frames_pending_response_);
if (number_of_frames_pending_response_ != 0)
@@ -1272,6 +1242,7 @@ void SavePackage::CompleteSavableResourceLinksResponse() {
base::FilePath SavePackage::GetSuggestedNameForSaveAs(
bool can_save_as_complete,
const std::string& contents_mime_type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::FilePath name_with_proper_ext = base::FilePath::FromUTF16Unsafe(title_);
// If the page's title matches its URL, use the URL. Try to use the last path
@@ -1348,6 +1319,7 @@ base::FilePath SavePackage::EnsureMimeExtension(const base::FilePath& name,
return name;
}
+// static
const base::FilePath::CharType* SavePackage::ExtensionForMimeType(
const std::string& contents_mime_type) {
static const struct {
@@ -1368,6 +1340,7 @@ const base::FilePath::CharType* SavePackage::ExtensionForMimeType(
}
void SavePackage::GetSaveInfo() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Can't use |web_contents_| in the FILE thread, so get the data that we need
// before calling to it.
base::FilePath website_save_dir;
@@ -1380,17 +1353,23 @@ void SavePackage::GetSaveInfo() {
&download_save_dir, &skip_dir_check);
}
std::string mime_type = web_contents()->GetContentsMimeType();
- BrowserThread::PostTask(
+ bool can_save_as_complete = CanSaveAsComplete(mime_type);
+ base::FilePath suggested_filename =
+ GetSuggestedNameForSaveAs(can_save_as_complete, mime_type);
+ BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&SavePackage::CreateDirectoryOnFileThread, this,
- website_save_dir, download_save_dir, skip_dir_check, mime_type));
+ base::Bind(&SavePackage::CreateDirectoryOnFileThread, website_save_dir,
+ download_save_dir, suggested_filename, skip_dir_check),
+ base::Bind(&SavePackage::ContinueGetSaveInfo, this,
+ can_save_as_complete));
}
-void SavePackage::CreateDirectoryOnFileThread(
+// static
+base::FilePath SavePackage::CreateDirectoryOnFileThread(
const base::FilePath& website_save_dir,
const base::FilePath& download_save_dir,
- bool skip_dir_check,
- const std::string& mime_type) {
+ const base::FilePath& suggested_filename,
+ bool skip_dir_check) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
base::FilePath save_dir;
@@ -1408,34 +1387,26 @@ void SavePackage::CreateDirectoryOnFileThread(
save_dir = website_save_dir;
}
- bool can_save_as_complete = CanSaveAsComplete(mime_type);
- base::FilePath suggested_filename = GetSuggestedNameForSaveAs(
- can_save_as_complete, mime_type);
- base::FilePath::StringType pure_file_name =
+ base::FilePath::StringType base_name =
suggested_filename.RemoveExtension().BaseName().value();
base::FilePath::StringType file_name_ext = suggested_filename.Extension();
// Need to make sure the suggested file name is not too long.
uint32_t max_path = GetMaxPathLengthForDirectory(save_dir);
- if (GetSafePureFileName(save_dir, file_name_ext, max_path, &pure_file_name)) {
- save_dir = save_dir.Append(pure_file_name + file_name_ext);
- } else {
- // Cannot create a shorter filename. This will cause the save as operation
- // to fail unless the user pick a shorter name. Continuing even though it
- // will fail because returning means no save as popup for the user, which
- // is even more confusing. This case should be rare though.
- save_dir = save_dir.Append(suggested_filename);
+ if (TruncateBaseNameToFitPathConstraints(save_dir, file_name_ext, max_path,
+ &base_name)) {
+ return save_dir.Append(base_name + file_name_ext);
}
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SavePackage::ContinueGetSaveInfo, this, save_dir,
- can_save_as_complete));
+ // Cannot create a shorter filename. This will cause the save as operation
+ // to fail unless the user pick a shorter name. Continuing even though it
+ // will fail because returning means no save as popup for the user, which
+ // is even more confusing. This case should be rare though.
+ return save_dir.Append(suggested_filename);
}
-void SavePackage::ContinueGetSaveInfo(const base::FilePath& suggested_path,
- bool can_save_as_complete) {
+void SavePackage::ContinueGetSaveInfo(bool can_save_as_complete,
+ const base::FilePath& suggested_path) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// The WebContents which owns this SavePackage may have disappeared during
@@ -1460,6 +1431,7 @@ void SavePackage::OnPathPicked(
const base::FilePath& final_name,
SavePageType type,
const SavePackageDownloadCreatedCallback& download_created_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK((type == SAVE_PAGE_TYPE_AS_ONLY_HTML) ||
(type == SAVE_PAGE_TYPE_AS_MHTML) ||
(type == SAVE_PAGE_TYPE_AS_COMPLETE_HTML)) << type;
@@ -1482,7 +1454,8 @@ void SavePackage::OnPathPicked(
Init(download_created_callback);
}
-void SavePackage::StopObservation() {
+void SavePackage::RemoveObservers() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(download_);
DCHECK(download_manager_);
@@ -1492,14 +1465,14 @@ void SavePackage::StopObservation() {
}
void SavePackage::OnDownloadDestroyed(DownloadItem* download) {
- StopObservation();
+ RemoveObservers();
}
void SavePackage::FinalizeDownloadEntry() {
DCHECK(download_);
download_manager_->OnSavePackageSuccessfullyFinished(download_);
- StopObservation();
+ RemoveObservers();
}
} // namespace content
diff --git a/chromium/content/browser/download/save_package.h b/chromium/content/browser/download/save_package.h
index d4219814c88..edc54841c8e 100644
--- a/chromium/content/browser/download/save_package.h
+++ b/chromium/content/browser/download/save_package.h
@@ -88,14 +88,6 @@ class CONTENT_EXPORT SavePackage
// in the "Save As" dialog box.
explicit SavePackage(WebContents* web_contents);
- // This contructor is used only for testing. We can bypass the file and
- // directory name generation / sanitization by providing well known paths
- // better suited for tests.
- SavePackage(WebContents* web_contents,
- SavePageType save_type,
- const base::FilePath& file_full_path,
- const base::FilePath& directory_full_path);
-
// Initialize the SavePackage. Returns true if it initializes properly. Need
// to make sure that this method must be called in the UI thread because using
// g_browser_process on a non-UI thread can cause crashes during shutdown.
@@ -133,6 +125,34 @@ class CONTENT_EXPORT SavePackage
private:
friend class base::RefCountedThreadSafe<SavePackage>;
+ // Friends for testing. Needed for accessing the test-only constructor below.
+ friend class SavePackageTest;
+ friend class WebContentsImpl;
+ FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestSuggestedSaveNames);
+ FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestLongSafePureFilename);
+ FRIEND_TEST_ALL_PREFIXES(SavePackageBrowserTest, ImplicitCancel);
+ 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 FileNameSet = std::set<base::FilePath::StringType,
+ bool (*)(base::FilePath::StringPieceType,
+ base::FilePath::StringPieceType)>;
+
+ using FileNameCountMap =
+ std::unordered_map<base::FilePath::StringType, uint32_t>;
+
+ // Used only for testing. Bypasses the file and directory name generation /
+ // sanitization by providing well known paths better suited for tests.
+ SavePackage(WebContents* web_contents,
+ SavePageType save_type,
+ const base::FilePath& file_full_path,
+ const base::FilePath& directory_full_path);
+
void InitWithDownloadItem(
const SavePackageDownloadCreatedCallback& download_created_callback,
DownloadItemImpl* item);
@@ -140,11 +160,6 @@ class CONTENT_EXPORT SavePackage
// Callback for WebContents::GenerateMHTML().
void OnMHTMLGenerated(int64_t size);
- // For testing only.
- SavePackage(WebContents* web_contents,
- const base::FilePath& file_full_path,
- const base::FilePath& directory_full_path);
-
~SavePackage() override;
// Notes from Init() above applies here as well.
@@ -173,7 +188,7 @@ class CONTENT_EXPORT SavePackage
void FinalizeDownloadEntry();
// Detach from DownloadManager.
- void StopObservation();
+ void RemoveObservers();
// Return max length of a path for a specific base directory.
// This is needed on POSIX, which restrict the length of file names in
@@ -181,11 +196,27 @@ class CONTENT_EXPORT SavePackage
// |base_dir| is assumed to be a directory name with no trailing slash.
static uint32_t GetMaxPathLengthForDirectory(const base::FilePath& base_dir);
- static bool GetSafePureFileName(
- const base::FilePath& dir_path,
- const base::FilePath::StringType& file_name_ext,
- uint32_t max_file_path_len,
- base::FilePath::StringType* pure_file_name);
+ // Truncates a filename to fit length constraints.
+ //
+ // |directory| : Directory containing target file.
+ // |extension| : Extension.
+ // |max_path_len| : Maximum size allowed for |len(directory + base_name +
+ // extension|.
+ // |base_name| : Variable portion. The length of this component will be
+ // adjusted to fit the length constraints described at
+ // |max_path_len| above.
+ //
+ // Returns true if |base_name| could be successfully adjusted to fit the
+ // aforementioned constraints, or false otherwise.
+ // TODO(asanka): This function is wrong. |base_name| cannot be truncated
+ // without knowing its encoding and truncation has to be performed on
+ // character boundaries. Also the implementation doesn't look up the actual
+ // path constraints and instead uses hard coded constants. crbug.com/618737
+ static bool TruncateBaseNameToFitPathConstraints(
+ const base::FilePath& directory,
+ const base::FilePath::StringType& extension,
+ uint32_t max_path_len,
+ base::FilePath::StringType* base_name);
// Create a file name based on the response from the server.
bool GenerateFileName(const std::string& disposition,
@@ -263,33 +294,26 @@ class CONTENT_EXPORT SavePackage
bool end_of_data);
// Look up SaveItem by save item id from in progress map.
- SaveItem* LookupSaveItemInProcess(SaveItemId save_item_id);
+ SaveItem* LookupInProgressSaveItem(SaveItemId save_item_id);
// Remove SaveItem from in progress map and put it to saved map.
void PutInProgressItemToSavedMap(SaveItem* save_item);
// Retrieves the URL to be saved from the WebContents.
- GURL GetUrlToBeSaved();
-
- void CreateDirectoryOnFileThread(const base::FilePath& website_save_dir,
- const base::FilePath& download_save_dir,
- bool skip_dir_check,
- const std::string& mime_type);
- void ContinueGetSaveInfo(const base::FilePath& suggested_path,
- bool can_save_as_complete);
+ static GURL GetUrlToBeSaved(WebContents* web_contents);
+
+ static base::FilePath CreateDirectoryOnFileThread(
+ const base::FilePath& website_save_dir,
+ const base::FilePath& download_save_dir,
+ const base::FilePath& suggested_filename,
+ bool skip_dir_check);
+ void ContinueGetSaveInfo(bool can_save_as_complete,
+ const base::FilePath& suggested_path);
void OnPathPicked(
const base::FilePath& final_name,
SavePageType type,
const SavePackageDownloadCreatedCallback& cb);
- // Map from SaveItem::id() (aka save_item_id) into a SaveItem.
- using SaveItemIdMap =
- std::unordered_map<SaveItemId, SaveItem*, SaveItemId::Hasher>;
- // Map of all saving job in in-progress state.
- SaveItemIdMap in_progress_items_;
- // Map of all saving job which are failed.
- SaveItemIdMap saved_failed_items_;
-
// The number of in process SaveItems.
int in_process_count() const {
return static_cast<int>(in_progress_items_.size());
@@ -329,10 +353,15 @@ class CONTENT_EXPORT SavePackage
static const base::FilePath::CharType* ExtensionForMimeType(
const std::string& contents_mime_type);
- using SaveItemQueue = std::deque<SaveItem*>;
// A queue for items we are about to start saving.
SaveItemQueue waiting_item_queue_;
+ // Map of all saving job in in-progress state.
+ SaveItemIdMap in_progress_items_;
+
+ // Map of all saving job which are failed.
+ SaveItemIdMap saved_failed_items_;
+
// Used to de-dupe urls that are being gathered into |waiting_item_queue_|
// and also to find SaveItems to associate with a containing frame.
// Note that |url_to_save_item_| does NOT own SaveItems - they
@@ -354,17 +383,17 @@ class CONTENT_EXPORT SavePackage
frame_tree_node_id_to_contained_save_items_;
// Number of frames that we still need to get a response from.
- int number_of_frames_pending_response_;
+ int number_of_frames_pending_response_ = 0;
// Map of all saving job which are successfully saved.
SaveItemIdMap saved_success_items_;
// Non-owning pointer for handling file writing on the FILE thread.
- SaveFileManager* file_manager_;
+ SaveFileManager* file_manager_ = nullptr;
// DownloadManager owns the DownloadItem and handles history and UI.
- DownloadManagerImpl* download_manager_;
- DownloadItemImpl* download_;
+ DownloadManagerImpl* download_manager_ = nullptr;
+ DownloadItemImpl* download_ = nullptr;
// The URL of the page the user wants to save.
GURL page_url_;
@@ -375,51 +404,41 @@ class CONTENT_EXPORT SavePackage
base::string16 title_;
// Used to calculate package download speed (in files per second).
- base::TimeTicks start_tick_;
+ const base::TimeTicks start_tick_;
// Indicates whether the actual saving job is finishing or not.
- bool finished_;
+ bool finished_ = false;
// Indicates whether user canceled the saving job.
- bool user_canceled_;
+ bool user_canceled_ = false;
// Indicates whether user get disk error.
- bool disk_error_occurred_;
+ bool disk_error_occurred_ = false;
+
+ // Variables to record errors that happened so we can record them via
+ // UMA statistics.
+ bool wrote_to_completed_file_ = false;
+ bool wrote_to_failed_file_ = false;
// Type about saving page as only-html or complete-html.
- SavePageType save_type_;
+ SavePageType save_type_ = SAVE_PAGE_TYPE_UNKNOWN;
// Number of all need to be saved resources.
- size_t all_save_items_count_;
+ size_t all_save_items_count_ = 0;
- using FileNameSet =
- std::set<base::FilePath::StringType,
- bool (*)(base::FilePath::StringPieceType,
- base::FilePath::StringPieceType)>;
// This set is used to eliminate duplicated file names in saving directory.
FileNameSet file_name_set_;
- using FileNameCountMap =
- std::unordered_map<base::FilePath::StringType, uint32_t>;
// This map is used to track serial number for specified filename.
FileNameCountMap file_name_count_map_;
// Indicates current waiting state when SavePackage try to get something
// from outside.
- WaitState wait_state_;
+ WaitState wait_state_ = INITIALIZE;
// Unique ID for this SavePackage.
const SavePackageId unique_id_;
- // Variables to record errors that happened so we can record them via
- // UMA statistics.
- bool wrote_to_completed_file_;
- bool wrote_to_failed_file_;
-
- friend class SavePackageTest;
- FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestSuggestedSaveNames);
- FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestLongSafePureFilename);
-
DISALLOW_COPY_AND_ASSIGN(SavePackage);
};
diff --git a/chromium/content/browser/download/save_package_unittest.cc b/chromium/content/browser/download/save_package_unittest.cc
index c426772a820..c75a28bf6c7 100644
--- a/chromium/content/browser/download/save_package_unittest.cc
+++ b/chromium/content/browser/download/save_package_unittest.cc
@@ -10,10 +10,12 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/browser/download/save_package.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/common/url_constants.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
@@ -42,13 +44,6 @@ const uint32_t kMaxFilePathLength = PATH_MAX - 1;
const uint32_t kMaxFileNameLength = NAME_MAX;
#endif
-// Used to make long filenames.
-std::string long_file_name(
- "EFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz01234567"
- "89ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz012345"
- "6789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz0123"
- "456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789a");
-
bool HasOrdinalNumber(const base::FilePath::StringType& filename) {
base::FilePath::StringType::size_type r_paren_index =
filename.rfind(FPL(')'));
@@ -94,7 +89,7 @@ class SavePackageTest : public RenderViewHostImplTestHarness {
}
GURL GetUrlToBeSaved() {
- return save_package_success_->GetUrlToBeSaved();
+ return SavePackage::GetUrlToBeSaved(save_package_success_->web_contents());
}
protected:
@@ -105,20 +100,43 @@ class SavePackageTest : public RenderViewHostImplTestHarness {
// RenderViewHostImplTestHarness::SetUp.
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- save_package_success_ = new SavePackage(contents(),
- temp_dir_.path().AppendASCII("testfile" HTML_EXTENSION),
- temp_dir_.path().AppendASCII("testfile_files"));
+ save_package_success_ =
+ new SavePackage(contents(), SAVE_PAGE_TYPE_AS_COMPLETE_HTML,
+ temp_dir_.path().AppendASCII("testfile" HTML_EXTENSION),
+ temp_dir_.path().AppendASCII("testfile_files"));
+
+ base::FilePath::StringType long_file_name = GetLongFileName();
+ save_package_fail_ = new SavePackage(
+ contents(), SAVE_PAGE_TYPE_AS_COMPLETE_HTML,
+ temp_dir_.path().Append(long_file_name + FPL_HTML_EXTENSION),
+ temp_dir_.path().Append(long_file_name + FPL("_files")));
+ }
+
+ BrowserContext* CreateBrowserContext() override {
+ // This method is invoked after the browser threads have been created and
+ // obviously before the BrowserContext is created. This is the correct time
+ // to create a ResourceDispatcherHostImpl so that our SavePackage objects
+ // can initialize correctly.
+ rdh_.reset(new ResourceDispatcherHostImpl);
+ return RenderViewHostImplTestHarness::CreateBrowserContext();
+ }
+
+ void TearDown() override {
+ DeleteContents();
+ base::RunLoop().RunUntilIdle();
+
+ save_package_success_ = nullptr;
+ save_package_fail_ = nullptr;
+ rdh_.reset();
- // We need to construct a path that is *almost* kMaxFilePathLength long
- long_file_name.reserve(kMaxFilePathLength + long_file_name.length());
- while (long_file_name.length() < kMaxFilePathLength)
- long_file_name += long_file_name;
- long_file_name.resize(
- kMaxFilePathLength - 9 - temp_dir_.path().value().length());
+ RenderViewHostImplTestHarness::TearDown();
+ }
- save_package_fail_ = new SavePackage(contents(),
- temp_dir_.path().AppendASCII(long_file_name + HTML_EXTENSION),
- temp_dir_.path().AppendASCII(long_file_name + "_files"));
+ // Returns a path that is *almost* kMaxFilePathLength long
+ base::FilePath::StringType GetLongFileName() const {
+ size_t target_length =
+ kMaxFilePathLength - 9 - temp_dir_.path().value().length();
+ return base::FilePath::StringType(target_length, FPL('a'));
}
private:
@@ -128,6 +146,8 @@ class SavePackageTest : public RenderViewHostImplTestHarness {
scoped_refptr<SavePackage> save_package_fail_;
base::ScopedTempDir temp_dir_;
+
+ std::unique_ptr<ResourceDispatcherHostImpl> rdh_;
};
static const struct {
@@ -211,19 +231,21 @@ TEST_F(SavePackageTest, TestUnSuccessfullyGenerateSavePackageFilename) {
#endif
TEST_F(SavePackageTest, MAYBE_TestLongSavePackageFilename) {
const std::string base_url("http://www.google.com/");
- const std::string long_file = long_file_name + ".css";
- const std::string url = base_url + long_file;
+ const base::FilePath::StringType long_file_name =
+ GetLongFileName() + FPL(".css");
+ const std::string url =
+ base_url + base::FilePath(long_file_name).AsUTF8Unsafe();
base::FilePath::StringType filename;
// Test that the filename is successfully shortened to fit.
ASSERT_TRUE(GetGeneratedFilename(true, std::string(), url, false, &filename));
- EXPECT_TRUE(filename.length() < long_file.length());
+ EXPECT_TRUE(filename.length() < long_file_name.length());
EXPECT_FALSE(HasOrdinalNumber(filename));
// Test that the filename is successfully shortened to fit, and gets an
// an ordinal appended.
ASSERT_TRUE(GetGeneratedFilename(true, std::string(), url, false, &filename));
- EXPECT_TRUE(filename.length() < long_file.length());
+ EXPECT_TRUE(filename.length() < long_file_name.length());
EXPECT_TRUE(HasOrdinalNumber(filename));
// Test that the filename is successfully shortened to fit, and gets a
@@ -231,7 +253,7 @@ TEST_F(SavePackageTest, MAYBE_TestLongSavePackageFilename) {
base::FilePath::StringType filename2;
ASSERT_TRUE(
GetGeneratedFilename(true, std::string(), url, false, &filename2));
- EXPECT_TRUE(filename2.length() < long_file.length());
+ EXPECT_TRUE(filename2.length() < long_file_name.length());
EXPECT_TRUE(HasOrdinalNumber(filename2));
EXPECT_NE(filename, filename2);
}
@@ -245,17 +267,12 @@ TEST_F(SavePackageTest, MAYBE_TestLongSavePackageFilename) {
TEST_F(SavePackageTest, MAYBE_TestLongSafePureFilename) {
const base::FilePath save_dir(FPL("test_dir"));
const base::FilePath::StringType ext(FPL_HTML_EXTENSION);
- base::FilePath::StringType filename =
-#if defined(OS_WIN)
- base::ASCIIToUTF16(long_file_name);
-#else
- long_file_name;
-#endif
+ base::FilePath::StringType filename = GetLongFileName();
// Test that the filename + extension doesn't exceed kMaxFileNameLength
uint32_t max_path = SavePackage::GetMaxPathLengthForDirectory(save_dir);
- ASSERT_TRUE(SavePackage::GetSafePureFileName(save_dir, ext, max_path,
- &filename));
+ ASSERT_TRUE(SavePackage::TruncateBaseNameToFitPathConstraints(
+ save_dir, ext, max_path, &filename));
EXPECT_TRUE(filename.length() <= kMaxFileNameLength-ext.length());
}
@@ -399,9 +416,10 @@ static const struct SuggestedSaveNameTestCase {
#define MAYBE_TestSuggestedSaveNames TestSuggestedSaveNames
#endif
TEST_F(SavePackageTest, MAYBE_TestSuggestedSaveNames) {
+ GURL url = net::URLRequestMockHTTPJob::GetMockUrl("save_page/a.htm");
+ NavigateAndCommit(url);
for (size_t i = 0; i < arraysize(kSuggestedSaveNames); ++i) {
- scoped_refptr<SavePackage> save_package(
- new SavePackage(contents(), base::FilePath(), base::FilePath()));
+ scoped_refptr<SavePackage> save_package(new SavePackage(contents()));
save_package->page_url_ = GURL(kSuggestedSaveNames[i].page_url);
save_package->title_ = kSuggestedSaveNames[i].page_title;
diff --git a/chromium/content/browser/download/save_types.h b/chromium/content/browser/download/save_types.h
index 9d61a9a70a0..e8076d27540 100644
--- a/chromium/content/browser/download/save_types.h
+++ b/chromium/content/browser/download/save_types.h
@@ -7,8 +7,8 @@
#include <stdint.h>
-#include <map>
#include <string>
+#include <unordered_map>
#include <utility>
#include <vector>
@@ -25,7 +25,8 @@ class SaveItem;
using SaveItemId = gpu::IdType32<SaveItem>;
// Map from save_item_id into final file path.
-using FinalNamesMap = std::map<SaveItemId, base::FilePath>;
+using FinalNamesMap =
+ std::unordered_map<SaveItemId, base::FilePath, SaveItemId::Hasher>;
// This structure is used to handle and deliver some info
// when processing each save item job.
@@ -38,9 +39,6 @@ struct SaveFileCreateInfo {
// This type indicates the save item needs to be retrieved from serializing
// DOM.
SAVE_FILE_FROM_DOM,
- // This type indicates the save item needs to be retrieved from local file
- // system.
- SAVE_FILE_FROM_FILE
};
// Constructor for SAVE_FILE_FROM_DOM and/or SAVE_FILE_FROM_FILE.
diff --git a/chromium/content/browser/fileapi/file_system_browsertest.cc b/chromium/content/browser/fileapi/file_system_browsertest.cc
index 5c60c28f3a8..ef65b809fac 100644
--- a/chromium/content/browser/fileapi/file_system_browsertest.cc
+++ b/chromium/content/browser/fileapi/file_system_browsertest.cc
@@ -45,8 +45,7 @@ class FileSystemBrowserTest : public ContentBrowserTest {
if (result != "pass") {
std::string js_result;
ASSERT_TRUE(ExecuteScriptAndExtractString(
- the_browser->web_contents(),
- "window.domAutomationController.send(getLog())",
+ the_browser, "window.domAutomationController.send(getLog())",
&js_result));
FAIL() << "Failed: " << js_result;
}
diff --git a/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc b/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
index b8f7d3c84f5..5b533c7a3cc 100644
--- a/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
@@ -14,6 +14,7 @@
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -368,7 +369,8 @@ TEST_F(FileSystemDirURLRequestJobTest, Cancel) {
CreateDirectory("foo");
TestRequestNoRun(CreateFileSystemURL("foo/"));
// Run StartAsync() and only StartAsync().
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release());
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
+ request_.release());
base::RunLoop().RunUntilIdle();
// If we get here, success! we didn't crash!
}
diff --git a/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc b/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
index 98d21c51577..0b4fa751bf3 100644
--- a/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
@@ -17,6 +17,7 @@
#include "base/memory/weak_ptr.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -391,7 +392,8 @@ TEST_F(FileSystemURLRequestJobTest, Cancel) {
TestRequestNoRun(CreateFileSystemURL("file1.dat"));
// Run StartAsync() and only StartAsync().
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release());
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
+ request_.release());
base::RunLoop().RunUntilIdle();
// If we get here, success! we didn't crash!
}
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
index 5c499990507..2da70dc416c 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
@@ -11,8 +11,8 @@
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
-#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
+#include "base/run_loop.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/streams/stream_registry.h"
@@ -78,7 +78,7 @@ class FileAPIMessageFilterTest : public testing::Test {
stream_context_);
// Complete initialization.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
TestBrowserThreadBundle browser_thread_bundle_;
@@ -102,7 +102,7 @@ TEST_F(FileAPIMessageFilterTest, CloseChannelWithInflightRequest) {
filter->OnChannelConnected(0);
// Complete initialization.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
int request_id = 0;
const GURL kUrl("filesystem:http://example.com/temporary/foo");
@@ -113,7 +113,7 @@ TEST_F(FileAPIMessageFilterTest, CloseChannelWithInflightRequest) {
filter->OnChannelClosing();
// This shouldn't cause DCHECK failure.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
TEST_F(FileAPIMessageFilterTest, MultipleFilters) {
@@ -137,7 +137,7 @@ TEST_F(FileAPIMessageFilterTest, MultipleFilters) {
filter2->OnChannelConnected(1);
// Complete initialization.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
int request_id = 0;
const GURL kUrl("filesystem:http://example.com/temporary/foo");
@@ -148,7 +148,7 @@ TEST_F(FileAPIMessageFilterTest, MultipleFilters) {
filter2->OnChannelClosing();
// This shouldn't cause DCHECK failure.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
TEST_F(FileAPIMessageFilterTest, BuildEmptyStream) {
@@ -184,7 +184,7 @@ TEST_F(FileAPIMessageFilterTest, BuildEmptyStream) {
EXPECT_EQ(0, bytes_read);
// Run loop to finish transfer.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(Stream::STREAM_COMPLETE,
stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read));
@@ -214,7 +214,7 @@ TEST_F(FileAPIMessageFilterTest, BuildNonEmptyStream) {
EXPECT_TRUE(filter_->OnMessageReceived(finish_message));
// Run loop to finish transfer and commit finalize command.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kFakeData.size()));
int bytes_read = 0;
@@ -261,7 +261,7 @@ TEST_F(FileAPIMessageFilterTest, BuildStreamWithSharedMemory) {
EXPECT_TRUE(filter_->OnMessageReceived(finish_message));
// Run loop to finish transfer and commit finalize command.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kFakeData.size()));
int bytes_read = 0;
diff --git a/chromium/content/browser/find_request_manager.cc b/chromium/content/browser/find_request_manager.cc
index 915ecf8d9fd..ba97753698a 100644
--- a/chromium/content/browser/find_request_manager.cc
+++ b/chromium/content/browser/find_request_manager.cc
@@ -11,13 +11,90 @@
namespace content {
+namespace {
+
+// Returns the deepest last child frame under |node|/|rfh| in the frame tree.
+FrameTreeNode* GetDeepestLastChild(FrameTreeNode* node) {
+ while (node->child_count())
+ node = node->child_at(node->child_count() - 1);
+ return node;
+}
+RenderFrameHost* GetDeepestLastChild(RenderFrameHost* rfh) {
+ FrameTreeNode* node =
+ static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
+ return GetDeepestLastChild(node)->current_frame_host();
+}
+
+// Returns the FrameTreeNode directly after |node| in the frame tree in search
+// order, or nullptr if one does not exist. If |wrap| is set, then wrapping
+// between the first and last frames is permitted. Note that this traversal
+// follows the same ordering as in blink::FrameTree::traverseNextWithWrap().
+FrameTreeNode* TraverseNext(FrameTreeNode* node, bool wrap) {
+ if (node->child_count())
+ return node->child_at(0);
+
+ FrameTreeNode* sibling = node->NextSibling();
+ while (!sibling) {
+ if (!node->parent())
+ return wrap ? node : nullptr;
+ node = node->parent();
+ sibling = node->NextSibling();
+ }
+ return sibling;
+}
+
+// Returns the FrameTreeNode directly before |node| in the frame tree in search
+// order, or nullptr if one does not exist. If |wrap| is set, then wrapping
+// between the first and last frames is permitted. Note that this traversal
+// follows the same ordering as in blink::FrameTree::traversePreviousWithWrap().
+FrameTreeNode* TraversePrevious(FrameTreeNode* node, bool wrap) {
+ if (FrameTreeNode* previous_sibling = node->PreviousSibling())
+ return GetDeepestLastChild(previous_sibling);
+ if (node->parent())
+ return node->parent();
+ return wrap ? GetDeepestLastChild(node) : nullptr;
+}
+
+// The same as either TraverseNext() or TraversePrevious() depending on
+// |forward|.
+FrameTreeNode* TraverseNode(FrameTreeNode* node, bool forward, bool wrap) {
+ return forward ? TraverseNext(node, wrap) : TraversePrevious(node, wrap);
+}
+
+} // namespace
+
+#if defined(OS_ANDROID)
+FindRequestManager::ActivateNearestFindResultState::
+ActivateNearestFindResultState() = default;
+FindRequestManager::ActivateNearestFindResultState::
+ActivateNearestFindResultState(float x, float y)
+ : current_request_id(GetNextID()),
+ x(x),
+ y(y) {}
+FindRequestManager::ActivateNearestFindResultState::
+~ActivateNearestFindResultState() {}
+
+FindRequestManager::FrameRects::FrameRects() = default;
+FindRequestManager::FrameRects::FrameRects(const std::vector<gfx::RectF>& rects,
+ int version)
+ : rects(rects), version(version) {}
+FindRequestManager::FrameRects::~FrameRects() {}
+
+FindRequestManager::FindMatchRectsState::FindMatchRectsState() = default;
+FindRequestManager::FindMatchRectsState::~FindMatchRectsState() {}
+#endif
+
// static
const int FindRequestManager::kInvalidId = -1;
FindRequestManager::FindRequestManager(WebContentsImpl* web_contents)
- : contents_(web_contents),
+ : WebContentsObserver(web_contents),
+ contents_(web_contents),
current_session_id_(kInvalidId),
+ pending_active_match_ordinal_(false),
number_of_matches_(0),
+ active_frame_(nullptr),
+ relative_active_match_ordinal_(0),
active_match_ordinal_(0) {}
FindRequestManager::~FindRequestManager() {}
@@ -31,28 +108,26 @@ void FindRequestManager::Find(int request_id,
DCHECK_GT(request_id, current_request_.id);
DCHECK_GT(request_id, current_session_id_);
- FindRequest request(request_id, search_text, options);
-
- if (options.findNext) {
- // This is a find next operation.
-
- // This implies that there is an ongoing find session with the same search
- // text.
- DCHECK_GE(current_session_id_, 0);
- DCHECK_EQ(request.search_text, current_request_.search_text);
-
- current_request_ = request;
- } else {
- // This is an initial find operation.
- Reset(request);
- }
+ // If this is a new find session, clear any queued requests from last session.
+ if (!options.findNext)
+ find_request_queue_ = std::queue<FindRequest>();
- SendFindIPC(request, contents_->GetMainFrame());
+ find_request_queue_.emplace(request_id, search_text, options);
+ if (find_request_queue_.size() == 1)
+ FindInternal(find_request_queue_.front());
}
void FindRequestManager::StopFinding(StopFindAction action) {
- SendStopFindingIPC(action, contents_->GetMainFrame());
+ contents_->SendToAllFrames(
+ new FrameMsg_StopFinding(MSG_ROUTING_NONE, action));
+
current_session_id_ = kInvalidId;
+#if defined(OS_ANDROID)
+ // It is important that these pending replies are cleared whenever a find
+ // session ends, so that subsequent replies for the old session are ignored.
+ activate_.pending_replies.clear();
+ match_rects_.pending_replies.clear();
+#endif
}
void FindRequestManager::OnFindReply(RenderFrameHost* rfh,
@@ -64,29 +139,175 @@ void FindRequestManager::OnFindReply(RenderFrameHost* rfh,
// Ignore stale replies from abandoned find sessions.
if (current_session_id_ == kInvalidId || request_id < current_session_id_)
return;
+ DCHECK(CheckFrame(rfh));
+
+ // Update the stored find results.
+
+ DCHECK_GE(number_of_matches, -1);
+ DCHECK_GE(active_match_ordinal, -1);
- // Update the stored results.
- number_of_matches_ = number_of_matches;
- selection_rect_ = selection_rect;
- active_match_ordinal_ = active_match_ordinal;
+ // Check for an update to the number of matches.
+ if (number_of_matches != -1) {
+ DCHECK_GE(number_of_matches, 0);
+ // Increment the global number of matches by the number of additional
+ // matches found for this frame.
+ auto matches_per_frame_it = matches_per_frame_.find(rfh);
+ number_of_matches_ += number_of_matches - matches_per_frame_it->second;
+ matches_per_frame_it->second = number_of_matches;
+ }
+
+ // Check for an update to the selection rect.
+ if (!selection_rect.IsEmpty())
+ selection_rect_ = selection_rect;
+
+ // Check for an update to the active match ordinal.
+ if (active_match_ordinal > 0) {
+ if (rfh == active_frame_) {
+ active_match_ordinal_ +=
+ active_match_ordinal - relative_active_match_ordinal_;
+ relative_active_match_ordinal_ = active_match_ordinal;
+ } else {
+ if (active_frame_) {
+ // The new active match is in a different frame than the previous, so
+ // the previous active frame needs to be informed (to clear its active
+ // match highlighting).
+ active_frame_->Send(new FrameMsg_ClearActiveFindMatch(
+ active_frame_->GetRoutingID()));
+ }
+ active_frame_ = rfh;
+ relative_active_match_ordinal_ = active_match_ordinal;
+ UpdateActiveMatchOrdinal();
+ }
+ if (pending_active_match_ordinal_ && request_id == current_request_.id)
+ pending_active_match_ordinal_ = false;
+ AdvanceQueue(request_id);
+ }
- NotifyFindReply(request_id, final_update);
+ if (!final_update) {
+ NotifyFindReply(request_id, false /* final_update */);
+ return;
+ }
+
+ // This is the final update for this frame for the current find operation.
+
+ pending_replies_.erase(rfh);
+ if (request_id == current_session_id_ && !pending_replies_.empty()) {
+ NotifyFindReply(request_id, false /* final_update */);
+ return;
+ }
+ DCHECK(request_id == current_session_id_ ||
+ current_request_.options.findNext);
+
+ // This is the final update for the current find operation.
+ FinalUpdate(request_id, rfh);
}
+void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) {
+ if (current_session_id_ == kInvalidId || !CheckFrame(rfh))
+ return;
+
+ // If matches are counted for the frame that is being removed, decrement the
+ // match total before erasing that entry.
+ auto it = matches_per_frame_.find(rfh);
+ if (it != matches_per_frame_.end()) {
+ number_of_matches_ -= it->second;
+ matches_per_frame_.erase(it);
+ }
+
+ // Update the active match ordinal, since it may have changed.
+ if (active_frame_ == rfh) {
+ active_frame_ = nullptr;
+ relative_active_match_ordinal_ = 0;
+ }
+ UpdateActiveMatchOrdinal();
+
#if defined(OS_ANDROID)
-void FindRequestManager::ActivateNearestFindResult(float x,
- float y) {
+ // The removed frame may contain the nearest find result known so far. Note
+ // that once all queried frames have responded, if this result was the overall
+ // nearest, then no activation will occur.
+ if (rfh == activate_.nearest_frame)
+ activate_.nearest_frame = nullptr;
+
+ // Match rects in the removed frame are no longer relevant.
+ if (match_rects_.frame_rects.count(rfh)) {
+ match_rects_.frame_rects.erase(rfh);
+ ++match_rects_.known_version;
+ }
+
+ // A reply should not be expected from the removed frame.
+ RemoveNearestFindResultPendingReply(rfh);
+ RemoveFindMatchRectsPendingReply(rfh);
+#endif
+
+ if (pending_replies_.count(rfh)) {
+ // A reply should not be expected from the removed frame.
+ pending_replies_.erase(rfh);
+ if (pending_replies_.empty()) {
+ FinalUpdate(current_request_.id, rfh);
+ return;
+ }
+ }
+
+ NotifyFindReply(current_session_id_,
+ pending_replies_.empty() /* final_update */);
+}
+
+#if defined(OS_ANDROID)
+void FindRequestManager::ActivateNearestFindResult(float x, float y) {
if (current_session_id_ == kInvalidId)
return;
- auto rfh = contents_->GetMainFrame();
- rfh->Send(new InputMsg_ActivateNearestFindResult(
- rfh->GetRoutingID(), current_session_id_, x, y));
+ activate_ = ActivateNearestFindResultState(x, y);
+
+ // Request from each frame the distance to the nearest find result (in that
+ // frame) from the point (x, y), defined in find-in-page coordinates.
+ for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) {
+ RenderFrameHost* rfh = node->current_frame_host();
+
+ if (!CheckFrame(rfh))
+ continue;
+
+ activate_.pending_replies.insert(rfh);
+ rfh->Send(new FrameMsg_GetNearestFindResult(
+ rfh->GetRoutingID(), activate_.current_request_id,
+ activate_.x, activate_.y));
+ }
+}
+
+void FindRequestManager::OnGetNearestFindResultReply(RenderFrameHost* rfh,
+ int request_id,
+ float distance) {
+ if (request_id != activate_.current_request_id ||
+ !activate_.pending_replies.count(rfh)) {
+ return;
+ }
+
+ // Check if this frame has a nearer find result than the current nearest.
+ if (distance < activate_.nearest_distance) {
+ activate_.nearest_frame = rfh;
+ activate_.nearest_distance = distance;
+ }
+
+ RemoveNearestFindResultPendingReply(rfh);
}
void FindRequestManager::RequestFindMatchRects(int current_version) {
+ match_rects_.pending_replies.clear();
match_rects_.request_version = current_version;
- SendFindMatchRectsIPC(contents_->GetMainFrame());
+
+ // Request the latest find match rects from each frame.
+ for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes()) {
+ RenderFrameHost* rfh = node->current_frame_host();
+
+ if (!CheckFrame(rfh))
+ continue;
+
+ match_rects_.pending_replies.insert(rfh);
+ auto it = match_rects_.frame_rects.find(rfh);
+ int version = (it != match_rects_.frame_rects.end())
+ ? it->second.version : kInvalidId;
+ rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), version));
+ }
}
void FindRequestManager::OnFindMatchRectsReply(
@@ -94,32 +315,96 @@ void FindRequestManager::OnFindMatchRectsReply(
int version,
const std::vector<gfx::RectF>& rects,
const gfx::RectF& active_rect) {
- contents_->NotifyFindMatchRectsReply(version, rects, active_rect);
+ auto it = match_rects_.frame_rects.find(rfh);
+ if (it == match_rects_.frame_rects.end() || it->second.version != version) {
+ // New version of rects has been received, so update the data.
+ match_rects_.frame_rects[rfh] = FrameRects(rects, version);
+ ++match_rects_.known_version;
+ }
+ if (!active_rect.IsEmpty())
+ match_rects_.active_rect = active_rect;
+ RemoveFindMatchRectsPendingReply(rfh);
}
#endif
+void FindRequestManager::RenderFrameDeleted(RenderFrameHost* rfh) {
+ RemoveFrame(rfh);
+}
+
+void FindRequestManager::RenderFrameHostChanged(RenderFrameHost* old_host,
+ RenderFrameHost* new_host) {
+ RemoveFrame(old_host);
+}
+
+void FindRequestManager::FrameDeleted(RenderFrameHost* rfh) {
+ RemoveFrame(rfh);
+}
+
void FindRequestManager::Reset(const FindRequest& initial_request) {
current_session_id_ = initial_request.id;
current_request_ = initial_request;
+ pending_replies_.clear();
+ pending_active_match_ordinal_ = true;
+ matches_per_frame_.clear();
number_of_matches_ = 0;
+ active_frame_ = nullptr;
+ relative_active_match_ordinal_ = 0;
active_match_ordinal_ = 0;
selection_rect_ = gfx::Rect();
#if defined(OS_ANDROID)
- match_rects_ = FindMatchRectsState();
+ activate_ = ActivateNearestFindResultState();
+ match_rects_.pending_replies.clear();
#endif
}
+void FindRequestManager::FindInternal(const FindRequest& request) {
+ DCHECK_GT(request.id, current_request_.id);
+ DCHECK_GT(request.id, current_session_id_);
+
+ if (request.options.findNext) {
+ // This is a find next operation.
+
+ // This implies that there is an ongoing find session with the same search
+ // text.
+ DCHECK_GE(current_session_id_, 0);
+ DCHECK_EQ(request.search_text, current_request_.search_text);
+
+ // The find next request will be directed at the focused frame if there is
+ // one, or the first frame with matches otherwise.
+ RenderFrameHost* target_rfh = contents_->GetFocusedFrame();
+ if (!target_rfh || !CheckFrame(target_rfh))
+ target_rfh = GetInitialFrame(request.options.forward);
+
+ SendFindIPC(request, target_rfh);
+ current_request_ = request;
+ pending_active_match_ordinal_ = true;
+ return;
+ }
+
+ // This is an initial find operation.
+ Reset(request);
+ for (FrameTreeNode* node : contents_->GetFrameTree()->Nodes())
+ AddFrame(node->current_frame_host());
+}
+
+void FindRequestManager::AdvanceQueue(int request_id) {
+ if (find_request_queue_.empty() ||
+ request_id != find_request_queue_.front().id) {
+ return;
+ }
+
+ find_request_queue_.pop();
+ if (!find_request_queue_.empty())
+ FindInternal(find_request_queue_.front());
+}
+
void FindRequestManager::SendFindIPC(const FindRequest& request,
RenderFrameHost* rfh) {
+ pending_replies_.insert(rfh);
rfh->Send(new FrameMsg_Find(rfh->GetRoutingID(), request.id,
request.search_text, request.options));
}
-void FindRequestManager::SendStopFindingIPC(StopFindAction action,
- RenderFrameHost* rfh) const {
- rfh->Send(new FrameMsg_StopFinding(rfh->GetRoutingID(), action));
-}
-
void FindRequestManager::NotifyFindReply(int request_id,
bool final_update) const {
if (request_id == kInvalidId) {
@@ -131,10 +416,173 @@ void FindRequestManager::NotifyFindReply(int request_id,
active_match_ordinal_, final_update);
}
+RenderFrameHost* FindRequestManager::GetInitialFrame(bool forward) const {
+ RenderFrameHost* rfh = contents_->GetMainFrame();
+
+ if (!forward)
+ rfh = GetDeepestLastChild(rfh);
+
+ return rfh;
+}
+
+RenderFrameHost* FindRequestManager::Traverse(RenderFrameHost* from_rfh,
+ bool forward,
+ bool matches_only,
+ bool wrap) const {
+ FrameTreeNode* node =
+ static_cast<RenderFrameHostImpl*>(from_rfh)->frame_tree_node();
+
+ while ((node = TraverseNode(node, forward, wrap)) != nullptr) {
+ if (!CheckFrame(node->current_frame_host()))
+ continue;
+ RenderFrameHost* current_rfh = node->current_frame_host();
+ if (!matches_only || matches_per_frame_.find(current_rfh)->second ||
+ pending_replies_.count(current_rfh)) {
+ // Note that if there is still a pending reply expected for this frame,
+ // then it may have unaccounted matches and will not be skipped via
+ // |matches_only|.
+ return node->current_frame_host();
+ }
+ if (wrap && node->current_frame_host() == from_rfh)
+ return nullptr;
+ }
+
+ return nullptr;
+}
+
+void FindRequestManager::AddFrame(RenderFrameHost* rfh) {
+ if (!rfh || !rfh->IsRenderFrameLive())
+ return;
+
+ // A frame that is already being searched should not be added again.
+ DCHECK(!CheckFrame(rfh));
+
+ matches_per_frame_[rfh] = 0;
+
+ FindRequest request = current_request_;
+ request.id = current_session_id_;
+ request.options.findNext = false;
+ SendFindIPC(request, rfh);
+}
+
+bool FindRequestManager::CheckFrame(RenderFrameHost* rfh) const {
+ return rfh && rfh->IsRenderFrameLive() && matches_per_frame_.count(rfh);
+}
+
+void FindRequestManager::UpdateActiveMatchOrdinal() {
+ active_match_ordinal_ = 0;
+
+ if (!active_frame_ || !relative_active_match_ordinal_) {
+ DCHECK(!active_frame_ && !relative_active_match_ordinal_);
+ return;
+ }
+
+ // Traverse the frame tree backwards (in search order) and count all of the
+ // matches in frames before the frame with the active match, in order to
+ // determine the overall active match ordinal.
+ RenderFrameHost* frame = active_frame_;
+ while ((frame = Traverse(frame,
+ false /* forward */,
+ true /* matches_only */,
+ false /* wrap */)) != nullptr) {
+ active_match_ordinal_ += matches_per_frame_[frame];
+ }
+ active_match_ordinal_ += relative_active_match_ordinal_;
+}
+
+void FindRequestManager::FinalUpdate(int request_id, RenderFrameHost* rfh) {
+ if (!number_of_matches_ ||
+ !pending_active_match_ordinal_ ||
+ request_id != current_request_.id) {
+ NotifyFindReply(request_id, true /* final_update */);
+ AdvanceQueue(request_id);
+ return;
+ }
+
+ // There are matches, but no active match was returned, so another find next
+ // request must be sent.
+
+ RenderFrameHost* target_rfh;
+ if (current_request_.options.findNext) {
+ // If this was a find next operation, then the active match will be in the
+ // next frame with matches after this one.
+ target_rfh = Traverse(rfh,
+ current_request_.options.forward,
+ true /* matches_only */,
+ true /* wrap */);
+ } else if ((target_rfh = contents_->GetFocusedFrame()) != nullptr) {
+ // Otherwise, if there is a focused frame, then the active match will be in
+ // the next frame with matches after that one.
+ target_rfh = Traverse(target_rfh,
+ current_request_.options.forward,
+ true /* matches_only */,
+ true /* wrap */);
+ } else {
+ // Otherwise, the first frame with matches will have the active match.
+ target_rfh = GetInitialFrame(current_request_.options.forward);
+ if (!CheckFrame(target_rfh) || !matches_per_frame_[target_rfh]) {
+ target_rfh = Traverse(target_rfh,
+ current_request_.options.forward,
+ true /* matches_only */,
+ false /* wrap */);
+ }
+ }
+ DCHECK(target_rfh);
+
+ // Forward the find reply without |final_update| set because the active match
+ // has not yet been found.
+ NotifyFindReply(request_id, false /* final_update */);
+
+ current_request_.options.findNext = true;
+ SendFindIPC(current_request_, target_rfh);
+}
+
#if defined(OS_ANDROID)
-void FindRequestManager::SendFindMatchRectsIPC(RenderFrameHost* rfh) {
- rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(),
- match_rects_.request_version));
+void FindRequestManager::RemoveNearestFindResultPendingReply(
+ RenderFrameHost* rfh) {
+ auto it = activate_.pending_replies.find(rfh);
+ if (it == activate_.pending_replies.end())
+ return;
+
+ activate_.pending_replies.erase(it);
+ if (activate_.pending_replies.empty() &&
+ CheckFrame(activate_.nearest_frame)) {
+ activate_.nearest_frame->Send(new FrameMsg_ActivateNearestFindResult(
+ activate_.nearest_frame->GetRoutingID(),
+ current_session_id_, activate_.x, activate_.y));
+ }
+}
+
+void FindRequestManager::RemoveFindMatchRectsPendingReply(
+ RenderFrameHost* rfh) {
+ auto it = match_rects_.pending_replies.find(rfh);
+ if (it == match_rects_.pending_replies.end())
+ return;
+
+ match_rects_.pending_replies.erase(it);
+ if (match_rects_.pending_replies.empty()) {
+ // All replies are in.
+ std::vector<gfx::RectF> aggregate_rects;
+ if (match_rects_.request_version != match_rects_.known_version) {
+ // Request version is stale, so aggregate and report the newer find
+ // match rects. The rects should be aggregated in search order.
+ for (RenderFrameHost* frame = GetInitialFrame(true /* forward */); frame;
+ frame = Traverse(frame,
+ true /* forward */,
+ true /* matches_only */,
+ false /* wrap */)) {
+ auto it = match_rects_.frame_rects.find(frame);
+ if (it == match_rects_.frame_rects.end())
+ continue;
+
+ std::vector<gfx::RectF>& frame_rects = it->second.rects;
+ aggregate_rects.insert(
+ aggregate_rects.end(), frame_rects.begin(), frame_rects.end());
+ }
+ }
+ contents_->NotifyFindMatchRectsReply(
+ match_rects_.known_version, aggregate_rects, match_rects_.active_rect);
+ }
}
#endif
diff --git a/chromium/content/browser/find_request_manager.h b/chromium/content/browser/find_request_manager.h
index 0fa037eb79d..59713ffec27 100644
--- a/chromium/content/browser/find_request_manager.h
+++ b/chromium/content/browser/find_request_manager.h
@@ -5,9 +5,14 @@
#ifndef CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_
#define CONTENT_BROWSER_FIND_REQUEST_MANAGER_H_
-#include <set>
+#include <queue>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
#include <vector>
+#include "content/common/content_export.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/stop_find_action.h"
#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "ui/gfx/geometry/rect.h"
@@ -23,13 +28,10 @@ class WebContentsImpl;
// multiple (potentially out-of-process) frames, handles the aggregation of find
// results from each frame, and facilitates active match traversal. It is
// instantiated once per WebContents, and is owned by that WebContents.
-//
-// TODO(paulmeyer): FindRequestManager is currently incomplete and does not do
-// all of these things yet, but will soon.
-class FindRequestManager {
+class CONTENT_EXPORT FindRequestManager : public WebContentsObserver {
public:
explicit FindRequestManager(WebContentsImpl* web_contents);
- ~FindRequestManager();
+ ~FindRequestManager() override;
// Initiates a find operation for |search_text| with the options specified in
// |options|. |request_id| uniquely identifies the find request.
@@ -51,16 +53,26 @@ class FindRequestManager {
int active_match_ordinal,
bool final_update);
+ // Removes a frame from the set of frames being searched. This should be
+ // called whenever a frame is discovered to no longer exist.
+ void RemoveFrame(RenderFrameHost* rfh);
+
#if defined(OS_ANDROID)
- // Selects and zooms to the find result nearest to the point (x,y) defined in
- // find-in-page coordinates.
+ // Selects and zooms to the find result nearest to the point (x, y), defined
+ // in find-in-page coordinates.
void ActivateNearestFindResult(float x, float y);
+ // Called when a reply is received from a frame in response to the
+ // GetNearestFindResult IPC.
+ void OnGetNearestFindResultReply(RenderFrameHost* rfh,
+ int nearest_find_result_request_id,
+ float distance);
+
// Requests the rects of the current find matches from the renderer process.
void RequestFindMatchRects(int current_version);
- // Called when a reply is received in response to a request for find match
- // rects.
+ // Called when a reply is received from a frame in response to a request for
+ // find match rects.
void OnFindMatchRectsReply(RenderFrameHost* rfh,
int version,
const std::vector<gfx::RectF>& rects,
@@ -69,7 +81,7 @@ class FindRequestManager {
private:
// An invalid ID. This value is invalid for any render process ID, render
- // frame ID, or find request ID.
+ // frame ID, find request ID, or find match rects version number.
static const int kInvalidId;
// The request data for a single find request.
@@ -90,27 +102,140 @@ class FindRequestManager {
: id(id), search_text(search_text), options(options) {}
};
- // Send a find IPC containing the find request |request| to the RenderFrame
+ // WebContentsObserver implementation.
+ void RenderFrameDeleted(RenderFrameHost* rfh) override;
+ void RenderFrameHostChanged(RenderFrameHost* old_host,
+ RenderFrameHost* new_host) override;
+ void FrameDeleted(RenderFrameHost* rfh) override;
+
+ // Resets all of the per-session state for a new find-in-page session.
+ void Reset(const FindRequest& initial_request);
+
+ // Called internally as find requests come up in the queue.
+ void FindInternal(const FindRequest& request);
+
+ // Called when an informative response (a response with enough information to
+ // be able to route subsequent find requests) comes in for the find request
+ // with ID |request_id|. Advances the |find_request_queue_| if appropriate.
+ void AdvanceQueue(int request_id);
+
+ // Sends a find IPC containing the find request |request| to the RenderFrame
// associated with |rfh|.
void SendFindIPC(const FindRequest& request, RenderFrameHost* rfh);
- // Send a stop finding IPC to the RenderFrame associated with |rfh|.
- void SendStopFindingIPC(StopFindAction action, RenderFrameHost* rfh) const;
+ // Sends the find results (as they currently are) to the WebContents.
+ void NotifyFindReply(int request_id, bool final_update) const;
- // Reset all of the per-session state for a new find-in-page session.
- void Reset(const FindRequest& initial_request);
+ // Returns the initial frame in search order. This will be either the first
+ // frame, if searching forward, or the last frame, if searching backward.
+ RenderFrameHost* GetInitialFrame(bool forward) const;
- // Send the find results (as they currently are) to the WebContents.
- void NotifyFindReply(int request_id, bool final_update) const;
+ // Traverses the frame tree to find and return the next RenderFrameHost after
+ // |from_rfh| in search order. |forward| indicates whether the frame tree
+ // should be traversed forward (if true) or backward (if false). If
+ // |matches_only| is set, then the frame tree will be traversed until the
+ // first frame is found for which matches have been found. If |wrap| is set,
+ // then the traversal can wrap around past the last frame to the first one (or
+ // vice-versa, if |forward| == false). If no frame can be found under these
+ // conditions, nullptr is returned.
+ RenderFrameHost* Traverse(RenderFrameHost* from_rfh,
+ bool forward,
+ bool matches_only,
+ bool wrap) const;
+
+ // Adds a frame to the set of frames that are being searched. The new frame
+ // will automatically be searched when added, using the same options (stored
+ // in |current_request_.options|).
+ void AddFrame(RenderFrameHost* rfh);
+
+ // Returns whether |rfh| is in the set of frames being searched in the current
+ // find session.
+ bool CheckFrame(RenderFrameHost* rfh) const;
+
+ // Computes and updates |active_match_ordinal_| based on |active_frame_| and
+ // |relative_active_match_ordinal_|.
+ void UpdateActiveMatchOrdinal();
+
+ // Called when all pending find replies have been received for the find
+ // request with ID |request_id|. The final update was received from |rfh|.
+ void FinalUpdate(int request_id, RenderFrameHost* rfh);
#if defined(OS_ANDROID)
- // Request the latest find match rects from a frame.
- void SendFindMatchRectsIPC(RenderFrameHost* rfh);
+ // Called when a nearest find result reply is no longer pending for a frame.
+ void RemoveNearestFindResultPendingReply(RenderFrameHost* rfh);
+
+ // Called when a find match rects reply is no longer pending for a frame.
+ void RemoveFindMatchRectsPendingReply(RenderFrameHost* rfh);
+
+ // State related to ActivateNearestFindResult requests.
+ struct ActivateNearestFindResultState {
+ // An ID to uniquely identify the current nearest find result request and
+ // its replies.
+ int current_request_id = kInvalidId;
+
+ // The x value of the requested point, in find-in-page coordinates.
+ float x = 0.0f;
+
+ // The y value of the requested point, in find-in-page coordinates.
+ float y = 0.0f;
+
+ // The distance to the nearest result found so far.
+ float nearest_distance = FLT_MAX;
+
+ // The frame containing the nearest result found so far.
+ RenderFrameHost* nearest_frame = nullptr;
+
+ // Nearest find result replies are still pending for these frames.
+ std::unordered_set<RenderFrameHost*> pending_replies;
+
+ ActivateNearestFindResultState();
+ ActivateNearestFindResultState(float x, float y);
+ ~ActivateNearestFindResultState();
+
+ static int GetNextID() {
+ static int next_id = 0;
+ return next_id++;
+ }
+ } activate_;
+
+ // Data for find match rects in a single frame.
+ struct FrameRects {
+ // The rects contained in a single frame.
+ std::vector<gfx::RectF> rects;
+
+ // The version number for these rects, as reported by their containing
+ // frame. This version is incremented independently in each frame.
+ int version = kInvalidId;
+
+ FrameRects();
+ FrameRects(const std::vector<gfx::RectF>& rects, int version);
+ ~FrameRects();
+ };
// State related to FindMatchRects requests.
struct FindMatchRectsState {
- // The latest find match rects version known by the requester.
+ // The latest find match rects version known by the requester. This will be
+ // compared to |known_version_| after polling frames for updates to their
+ // match rects, in order to determine if the requester already has the
+ // latest version of rects or not.
int request_version = kInvalidId;
+
+ // The current overall find match rects version known by
+ // FindRequestManager. This version should be incremented whenever
+ // |frame_rects| is updated.
+ int known_version = 0;
+
+ // A map from each frame to its find match rects.
+ std::unordered_map<RenderFrameHost*, FrameRects> frame_rects;
+
+ // The active find match rect.
+ gfx::RectF active_rect;
+
+ // Find match rects replies are still pending for these frames.
+ std::unordered_set<RenderFrameHost*> pending_replies;
+
+ FindMatchRectsState();
+ ~FindMatchRectsState();
} match_rects_;
#endif
@@ -127,14 +252,42 @@ class FindRequestManager {
// The current find request.
FindRequest current_request_;
- // The total number of matches found in the current find-in-page session.
+ // The set of frames that are still expected to reply to a pending find
+ // request. Frames are removed from |pending_replies_| when their reply with
+ // |final_update| set to true is received.
+ std::unordered_set<RenderFrameHost*> pending_replies_;
+
+ // Indicates whether an update to the active match ordinal is expected. Once
+ // set, |pending_active_match_ordinal_| will not reset until an update to the
+ // active match ordinal is received in response to the find request with ID
+ // |current_request_.id| (the latest request).
+ bool pending_active_match_ordinal_;
+
+ // The number of matches found in each frame. There will necessarily be
+ // entries in this map for every frame that is being (or has been) searched in
+ // the current find session, and no other frames.
+ std::unordered_map<RenderFrameHost*, int> matches_per_frame_;
+
+ // The total number of matches found in the current find-in-page session. This
+ // should always be equal to the sum of all the entries in
+ // |matches_per_frame_|.
int number_of_matches_;
+ // The frame containing the active match, if one exists, or nullptr otherwise.
+ RenderFrameHost* active_frame_;
+
+ // The active match ordinal relative to the matches found in its own frame.
+ int relative_active_match_ordinal_;
+
// The overall active match ordinal for the current find-in-page session.
int active_match_ordinal_;
// The rectangle around the active match, in screen coordinates.
gfx::Rect selection_rect_;
+
+ // Find requests are queued here when previous requests need to be handled
+ // before these ones can be properly routed.
+ std::queue<FindRequest> find_request_queue_;
};
} // namespace content
diff --git a/chromium/content/browser/find_request_manager_browsertest.cc b/chromium/content/browser/find_request_manager_browsertest.cc
index c8ac858f4bd..0ce93a6d6f0 100644
--- a/chromium/content/browser/find_request_manager_browsertest.cc
+++ b/chromium/content/browser/find_request_manager_browsertest.cc
@@ -12,6 +12,7 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
#include "third_party/WebKit/public/web/WebFindOptions.h"
@@ -52,6 +53,31 @@ class TestWebContentsDelegate : public WebContentsDelegate {
return current_results_;
}
+#if defined(OS_ANDROID)
+ // Waits for the next find reply. This is useful for waiting for a single
+ // match to be activated, which results in a single find reply (without a
+ // unique request ID).
+ void WaitForNextReply() {
+ waiting_request_id_ = 0;
+ find_message_loop_runner_ = new content::MessageLoopRunner;
+ find_message_loop_runner_->Run();
+ }
+
+ // Waits for all of the find match rects to be received.
+ void WaitForMatchRects() {
+ match_rects_message_loop_runner_ = new content::MessageLoopRunner;
+ match_rects_message_loop_runner_->Run();
+ }
+
+ const std::vector<gfx::RectF>& find_match_rects() const {
+ return find_match_rects_;
+ }
+
+ const gfx::RectF& active_match_rect() const {
+ return active_match_rect_;
+ }
+#endif
+
private:
// WebContentsDelegate override.
void FindReply(WebContents* web_contents,
@@ -78,6 +104,25 @@ class TestWebContentsDelegate : public WebContentsDelegate {
}
}
+#if defined(OS_ANDROID)
+ void FindMatchRectsReply(WebContents* web_contents,
+ int version,
+ const std::vector<gfx::RectF>& rects,
+ const gfx::RectF& active_rect) override {
+ // Update the current rects.
+ find_match_rects_ = rects;
+ active_match_rect_ = active_rect;
+
+ // If we are waiting for match rects, stop waiting.
+ if (match_rects_message_loop_runner_.get())
+ match_rects_message_loop_runner_->Quit();
+ }
+
+ std::vector<gfx::RectF> find_match_rects_;
+
+ gfx::RectF active_match_rect_;
+#endif
+
// The latest known results from the current find request.
FindResults current_results_;
@@ -89,11 +134,13 @@ class TestWebContentsDelegate : public WebContentsDelegate {
int waiting_request_id_;
scoped_refptr<content::MessageLoopRunner> find_message_loop_runner_;
+ scoped_refptr<content::MessageLoopRunner> match_rects_message_loop_runner_;
DISALLOW_COPY_AND_ASSIGN(TestWebContentsDelegate);
};
-class FindRequestManagerTest : public ContentBrowserTest {
+class FindRequestManagerTest : public ContentBrowserTest,
+ public testing::WithParamInterface<bool> {
public:
FindRequestManagerTest()
: normal_delegate_(nullptr),
@@ -114,18 +161,49 @@ class FindRequestManagerTest : public ContentBrowserTest {
contents()->SetDelegate(normal_delegate_);
}
+#if !defined(OS_ANDROID)
void SetUpCommandLine(base::CommandLine* command_line) override {
IsolateAllSitesForTesting(command_line);
}
+#endif
protected:
- // Navigate to |url| and wait for it to finish loading.
+ // Navigates to |url| and waits for it to finish loading.
void LoadAndWait(const std::string& url) {
TestNavigationObserver navigation_observer(contents());
NavigateToURL(shell(), embedded_test_server()->GetURL("a.com", url));
EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
}
+ // Loads a multi-frame page. The page will have a full binary frame tree of
+ // height |height|. If |cross_process| is true, child frames will be loaded
+ // cross-process.
+ void LoadMultiFramePage(int height, bool cross_process) {
+ LoadAndWait("/find_in_page_multi_frame.html");
+
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->
+ GetFrameTree()->root();
+
+ LoadMultiFramePageChildFrames(height, cross_process, root);
+ }
+
+ // Reloads the child frame cross-process.
+ void MakeChildFrameCrossProcess() {
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->
+ GetFrameTree()->root();
+
+ TestNavigationObserver observer(shell()->web_contents());
+
+ FrameTreeNode* child = root->child_at(0);
+ GURL url(embedded_test_server()->GetURL("b.com",
+ child->current_url().path()));
+ NavigateFrameToURL(child, url);
+ EXPECT_EQ(url, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ }
+
void Find(const std::string& search_text,
const blink::WebFindOptions& options) {
contents()->Find(++last_request_id_,
@@ -150,6 +228,33 @@ class FindRequestManagerTest : public ContentBrowserTest {
}
private:
+ // Helper function for LoadMultiFramePage. Loads child frames until the frame
+ // tree rooted at |root| is a full binary tree of height |height|.
+ void LoadMultiFramePageChildFrames(int height,
+ bool cross_process,
+ FrameTreeNode* root) {
+ if (height == 0)
+ return;
+
+ std::string hostname = root->current_origin().host();
+ if (cross_process)
+ hostname.insert(0, 1, 'a');
+ GURL url(embedded_test_server()->GetURL(hostname,
+ "/find_in_page_multi_frame.html"));
+
+ TestNavigationObserver observer(shell()->web_contents());
+
+ FrameTreeNode* child = root->child_at(0);
+ NavigateFrameToURL(child, url);
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ LoadMultiFramePageChildFrames(height - 1, cross_process, child);
+
+ child = root->child_at(1);
+ NavigateFrameToURL(child, url);
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ LoadMultiFramePageChildFrames(height - 1, cross_process, child);
+ }
+
TestWebContentsDelegate test_delegate_;
WebContentsDelegate* normal_delegate_;
@@ -159,14 +264,43 @@ class FindRequestManagerTest : public ContentBrowserTest {
DISALLOW_COPY_AND_ASSIGN(FindRequestManagerTest);
};
-// TODO(paulmeyer): These tests currently fail on the linux_android_rel_ng
-// trybot. Remove this guard once that problem is figured out.
-#if !defined(OS_ANDROID)
-
-// Test basic find-in-page functionality (such as searching forward and
+// Frames are made cross-process when the test param is set to
+// true. Cross-process frames are not used on android.
+#if defined(OS_ANDROID)
+INSTANTIATE_TEST_CASE_P(
+ FindRequestManagerTests, FindRequestManagerTest, testing::Values(false));
+#else
+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)
+#define MAYBE_Basic DISABLED_Basic
+#define MAYBE_CharacterByCharacter DISABLED_CharacterByCharacter
+#define MAYBE_RapidFire DISABLED_RapidFire
+#define MAYBE_RemoveFrame DISABLED_RemoveFrame
+#define MAYBE_HiddenFrame DISABLED_HiddenFrame
+#define MAYBE_FindMatchRects DISABLED_FindMatchRects
+#define MAYBE_ActivateNearestFindMatch DISABLED_ActivateNearestFindMatch
+#else
+#define MAYBE_Basic Basic
+#define MAYBE_CharacterByCharacter CharacterByCharacter
+#define MAYBE_RapidFire RapidFire
+#define MAYBE_RemoveFrame RemoveFrame
+#define MAYBE_HiddenFrame HiddenFrame
+#define MAYBE_FindMatchRects FindMatchRects
+#define MAYBE_ActivateNearestFindMatch ActivateNearestFindMatch
+#endif
+
+
+// Tests basic find-in-page functionality (such as searching forward and
// backward) and check for correct results at each step.
-IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, Basic) {
+IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_Basic) {
LoadAndWait("/find_in_page.html");
+ if (GetParam())
+ MakeChildFrameCrossProcess();
blink::WebFindOptions options;
Find("result", options);
@@ -202,8 +336,10 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, Basic) {
// Tests searching for a word character-by-character, as would typically be done
// by a user typing into the find bar.
-IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, CharacterByCharacter) {
+IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_CharacterByCharacter) {
LoadAndWait("/find_in_page.html");
+ if (GetParam())
+ MakeChildFrameCrossProcess();
blink::WebFindOptions default_options;
Find("r", default_options);
@@ -220,9 +356,11 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, CharacterByCharacter) {
EXPECT_EQ(1, results.active_match_ordinal);
}
-// Test sending a large number of find requests subsequently.
-IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, RapidFire) {
+// Tests sending a large number of find requests subsequently.
+IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_RapidFire) {
LoadAndWait("/find_in_page.html");
+ if (GetParam())
+ MakeChildFrameCrossProcess();
blink::WebFindOptions options;
Find("result", options);
@@ -239,6 +377,165 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, RapidFire) {
results.active_match_ordinal);
}
-#endif // OS_ANDROID
+// Tests removing a frame during a find session.
+IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE_RemoveFrame) {
+ LoadMultiFramePage(2 /* height */, GetParam() /* cross_process */);
+
+ blink::WebFindOptions options;
+ Find("result", options);
+ options.findNext = true;
+ options.forward = false;
+ Find("result", options);
+ Find("result", options);
+ Find("result", options);
+ Find("result", options);
+ Find("result", options);
+ WaitForFinalReply();
+
+ FindResults results = delegate()->GetFindResults();
+ EXPECT_EQ(last_request_id(), results.request_id);
+ EXPECT_EQ(21, results.number_of_matches);
+ EXPECT_EQ(17, results.active_match_ordinal);
+
+ // Remove a frame.
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->
+ GetFrameTree()->root();
+ root->RemoveChild(root->child_at(0));
+
+ // The number of matches and active match ordinal should update automatically
+ // to exclude the matches from the removed frame.
+ results = delegate()->GetFindResults();
+ EXPECT_EQ(last_request_id(), results.request_id);
+ EXPECT_EQ(12, results.number_of_matches);
+ EXPECT_EQ(8, results.active_match_ordinal);
+
+ // TODO(paulemeyer): Once adding frames mid-session is handled, test that too.
+}
+
+// Tests Searching in a hidden frame. Matches in the hidden frame should be
+// ignored.
+IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_HiddenFrame) {
+ LoadAndWait("/find_in_hidden_frame.html");
+
+ blink::WebFindOptions default_options;
+ Find("hello", default_options);
+ WaitForFinalReply();
+ FindResults results = delegate()->GetFindResults();
+
+ EXPECT_EQ(last_request_id(), results.request_id);
+ EXPECT_EQ(1, results.number_of_matches);
+ EXPECT_EQ(1, results.active_match_ordinal);
+}
+
+#if defined(OS_ANDROID)
+// Tests requesting find match rects.
+IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_FindMatchRects) {
+ LoadAndWait("/find_in_page.html");
+
+ blink::WebFindOptions default_options;
+ Find("result", default_options);
+ WaitForFinalReply();
+ EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);
+
+ // Request the find match rects.
+ contents()->RequestFindMatchRects(-1);
+ delegate()->WaitForMatchRects();
+ const std::vector<gfx::RectF>& rects = delegate()->find_match_rects();
+
+ // The first match should be active.
+ EXPECT_EQ(rects[0], delegate()->active_match_rect());
+
+ // All results after the first two should be between them in find-in-page
+ // coordinates. This is because results 2 to 19 are inside an iframe located
+ // between results 0 and 1. This applies to the fixed div too.
+ EXPECT_LT(rects[0].y(), rects[1].y());
+ for (int i = 2; i < 19; ++i) {
+ EXPECT_LT(rects[0].y(), rects[i].y());
+ EXPECT_GT(rects[1].y(), rects[i].y());
+ }
+
+ // Result 3 should be below results 2 and 4. This is caused by the CSS
+ // transform in the containing div. If the transform doesn't work then result
+ // 3 will be between results 2 and 4.
+ EXPECT_GT(rects[3].y(), rects[2].y());
+ EXPECT_GT(rects[3].y(), rects[4].y());
+
+ // Results 6, 7, 8 and 9 should be one below the other in that same order. If
+ // overflow:scroll is not properly handled then result 8 would be below result
+ // 9 or result 7 above result 6 depending on the scroll.
+ EXPECT_LT(rects[6].y(), rects[7].y());
+ EXPECT_LT(rects[7].y(), rects[8].y());
+ EXPECT_LT(rects[8].y(), rects[9].y());
+
+ // Results 11, 12, 13 and 14 should be between results 10 and 15, as they are
+ // inside the table.
+ EXPECT_GT(rects[11].y(), rects[10].y());
+ EXPECT_GT(rects[12].y(), rects[10].y());
+ EXPECT_GT(rects[13].y(), rects[10].y());
+ EXPECT_GT(rects[14].y(), rects[10].y());
+ EXPECT_LT(rects[11].y(), rects[15].y());
+ EXPECT_LT(rects[12].y(), rects[15].y());
+ EXPECT_LT(rects[13].y(), rects[15].y());
+ EXPECT_LT(rects[14].y(), rects[15].y());
+
+ // Result 11 should be above results 12, 13 and 14 as it's in the table
+ // header.
+ EXPECT_LT(rects[11].y(), rects[12].y());
+ EXPECT_LT(rects[11].y(), rects[13].y());
+ EXPECT_LT(rects[11].y(), rects[14].y());
+
+ // Result 11 should also be right of results 12, 13 and 14 because of the
+ // colspan.
+ EXPECT_GT(rects[11].x(), rects[12].x());
+ EXPECT_GT(rects[11].x(), rects[13].x());
+ EXPECT_GT(rects[11].x(), rects[14].x());
+
+ // Result 12 should be left of results 11, 13 and 14 in the table layout.
+ EXPECT_LT(rects[12].x(), rects[11].x());
+ EXPECT_LT(rects[12].x(), rects[13].x());
+ EXPECT_LT(rects[12].x(), rects[14].x());
+
+ // Results 13, 12 and 14 should be one above the other in that order because
+ // of the rowspan and vertical-align: middle by default.
+ EXPECT_LT(rects[13].y(), rects[12].y());
+ EXPECT_LT(rects[12].y(), rects[14].y());
+
+ // Result 16 should be below result 15.
+ EXPECT_GT(rects[15].y(), rects[14].y());
+
+ // Result 18 should be normalized with respect to the position:relative div,
+ // and not it's immediate containing div. Consequently, result 18 should be
+ // above result 17.
+ EXPECT_GT(rects[17].y(), rects[18].y());
+}
+
+// Tests activating the find match nearest to a given point.
+IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_ActivateNearestFindMatch) {
+ LoadAndWait("/find_in_page.html");
+
+ blink::WebFindOptions default_options;
+ Find("result", default_options);
+ WaitForFinalReply();
+ EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);
+
+ // Get the find match rects.
+ contents()->RequestFindMatchRects(-1);
+ delegate()->WaitForMatchRects();
+ const std::vector<gfx::RectF>& rects = delegate()->find_match_rects();
+
+ // Activate matches via points inside each of the find match rects, in an
+ // arbitrary order. Check that the correct match becomes active after each
+ // activation.
+ int order[19] =
+ {11, 13, 2, 0, 16, 5, 7, 10, 6, 1, 15, 14, 9, 17, 18, 3, 8, 12, 4};
+ for (int i = 0; i < 19; ++i) {
+ contents()->ActivateNearestFindResult(
+ rects[order[i]].CenterPoint().x(), rects[order[i]].CenterPoint().y());
+ delegate()->WaitForNextReply();
+ EXPECT_EQ(order[i] + 1, delegate()->GetFindResults().active_match_ordinal);
+ }
+}
+#endif // defined(OS_ANDROID)
} // namespace content
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 6002fcaa6b1..1b5dafd2ba4 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -172,7 +172,10 @@ void CrossProcessFrameConnector::BubbleScrollEvent(
memcpy(&resent_wheel_event, &event, sizeof(resent_wheel_event));
resent_wheel_event.x += offset_from_parent.x();
resent_wheel_event.y += offset_from_parent.y();
- parent_view->ProcessMouseWheelEvent(resent_wheel_event);
+ // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
+ // https://crbug.com/613628
+ ui::LatencyInfo latency_info;
+ parent_view->ProcessMouseWheelEvent(resent_wheel_event, latency_info);
} else {
NOTIMPLEMENTED();
}
@@ -191,6 +194,19 @@ void CrossProcessFrameConnector::FocusRootView() {
root_view->Focus();
}
+bool CrossProcessFrameConnector::LockMouse() {
+ RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView();
+ if (root_view)
+ return root_view->LockMouse();
+ return false;
+}
+
+void CrossProcessFrameConnector::UnlockMouse() {
+ RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView();
+ if (root_view)
+ root_view->UnlockMouse();
+}
+
void CrossProcessFrameConnector::OnForwardInputEvent(
const blink::WebInputEvent* event) {
if (!view_)
@@ -217,23 +233,26 @@ void CrossProcessFrameConnector::OnForwardInputEvent(
}
if (blink::WebInputEvent::isMouseEventType(event->type)) {
- view_->ProcessMouseEvent(*static_cast<const blink::WebMouseEvent*>(event));
+ // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
+ // https://crbug.com/613628
+ ui::LatencyInfo latency_info;
+ view_->ProcessMouseEvent(*static_cast<const blink::WebMouseEvent*>(event),
+ latency_info);
return;
}
if (event->type == blink::WebInputEvent::MouseWheel) {
+ // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
+ // https://crbug.com/613628
+ ui::LatencyInfo latency_info;
view_->ProcessMouseWheelEvent(
- *static_cast<const blink::WebMouseWheelEvent*>(event));
+ *static_cast<const blink::WebMouseWheelEvent*>(event), latency_info);
return;
}
}
void CrossProcessFrameConnector::OnFrameRectChanged(
const gfx::Rect& frame_rect) {
- // TODO(wjmaclean) When changing the zoom of a WebView child without also
- // changing the zoom of the embedder (e.g. using WebView.setZoom()), we
- // shouldn't propagate this change in the frame rect. We need to find a way
- // to detect when this happens. http://crbug.com/607978
if (!frame_rect.size().IsEmpty())
SetRect(frame_rect);
}
@@ -277,7 +296,7 @@ void CrossProcessFrameConnector::SetRect(const gfx::Rect& frame_rect) {
if (view_) {
view_->SetBounds(frame_rect);
- // Out-of-process iframes nested underneath this one implicitly have their
+ // Other local root frames nested underneath this one implicitly have their
// view rects changed when their ancestor is repositioned, and therefore
// need to have their screen rects updated.
FrameTreeNode* proxy_node =
@@ -286,8 +305,7 @@ void CrossProcessFrameConnector::SetRect(const gfx::Rect& frame_rect) {
old_rect.y() != child_frame_rect_.y()) {
for (FrameTreeNode* node :
proxy_node->frame_tree()->SubtreeNodes(proxy_node)) {
- if (node != proxy_node &&
- node->current_frame_host()->GetRenderWidgetHost())
+ if (node != proxy_node && node->current_frame_host()->is_local_root())
node->current_frame_host()->GetRenderWidgetHost()->SendScreenRects();
}
}
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 b913399ccbc..51251fd394a 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -19,7 +19,7 @@ struct WebScreenInfo;
}
namespace cc {
-struct SurfaceId;
+class SurfaceId;
struct SurfaceSequence;
}
@@ -110,6 +110,12 @@ class CONTENT_EXPORT CrossProcessFrameConnector {
// Focuses the root RenderWidgetHostView.
void FocusRootView();
+ // Locks the mouse. Returns true if mouse is locked.
+ bool LockMouse();
+
+ // Unlocks the mouse if the mouse is locked.
+ void UnlockMouse();
+
// Returns the parent RenderWidgetHostView or nullptr it it doesn't have one.
virtual RenderWidgetHostViewBase* GetParentRenderWidgetHostView();
diff --git a/chromium/content/browser/frame_host/debug_urls.cc b/chromium/content/browser/frame_host/debug_urls.cc
index 833b0063ab4..69a61ab0521 100644
--- a/chromium/content/browser/frame_host/debug_urls.cc
+++ b/chromium/content/browser/frame_host/debug_urls.cc
@@ -171,7 +171,9 @@ bool HandleAsanDebugURL(const GURL& url) {
void HangCurrentThread() {
ScopedAllowWaitForDebugURL allow_wait;
- base::WaitableEvent(false, false).Wait();
+ base::WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED)
+ .Wait();
}
} // namespace
diff --git a/chromium/content/browser/frame_host/frame_mojo_shell.cc b/chromium/content/browser/frame_host/frame_mojo_shell.cc
index d40ec40139d..0aa58160778 100644
--- a/chromium/content/browser/frame_host/frame_mojo_shell.cc
+++ b/chromium/content/browser/frame_host/frame_mojo_shell.cc
@@ -8,13 +8,12 @@
#include "build/build_config.h"
#include "content/browser/mojo/mojo_shell_context.h"
-#include "content/common/mojo/service_registry_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/common/content_client.h"
-#include "mojo/common/url_type_converters.h"
+#include "services/shell/public/cpp/interface_registry.h"
#if defined(OS_ANDROID) && defined(ENABLE_MOJO_CDM)
#include "content/browser/media/android/provision_fetcher_impl.h"
@@ -24,10 +23,10 @@ namespace content {
namespace {
-void RegisterFrameMojoShellServices(ServiceRegistry* registry,
- RenderFrameHost* render_frame_host) {
+void RegisterFrameMojoShellInterfaces(shell::InterfaceRegistry* registry,
+ RenderFrameHost* render_frame_host) {
#if defined(OS_ANDROID) && defined(ENABLE_MOJO_CDM)
- registry->AddService(
+ registry->AddInterface(
base::Bind(&ProvisionFetcherImpl::Create, render_frame_host));
#endif
}
@@ -45,41 +44,42 @@ void FrameMojoShell::BindRequest(shell::mojom::ConnectorRequest request) {
connectors_.AddBinding(this, std::move(request));
}
-// TODO(xhwang): Currently no callers are exposing |exposed_services|. So we
-// drop it and replace it with services we provide in the browser. In the
+// TODO(xhwang): Currently no callers are exposing |exposed_interfaces|. So we
+// drop it and replace it with interfaces we provide in the browser. In the
// future we may need to support both.
void FrameMojoShell::Connect(
shell::mojom::IdentityPtr target,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr /* exposed_services */,
+ shell::mojom::InterfaceProviderRequest interfaces,
+ shell::mojom::InterfaceProviderPtr /* exposed_interfaces */,
shell::mojom::ClientProcessConnectionPtr client_process_connection,
const shell::mojom::Connector::ConnectCallback& callback) {
- shell::mojom::InterfaceProviderPtr frame_services;
- service_provider_bindings_.AddBinding(GetServiceRegistry(),
- GetProxy(&frame_services));
+ shell::mojom::InterfaceProviderPtr frame_interfaces;
+ interface_provider_bindings_.AddBinding(GetInterfaceRegistry(),
+ GetProxy(&frame_interfaces));
MojoShellContext::ConnectToApplication(
shell::mojom::kRootUserID, target->name,
- frame_host_->GetSiteInstance()->GetSiteURL().spec(), std::move(services),
- std::move(frame_services), callback);
+ frame_host_->GetSiteInstance()->GetSiteURL().spec(),
+ std::move(interfaces),
+ std::move(frame_interfaces), callback);
}
void FrameMojoShell::Clone(shell::mojom::ConnectorRequest request) {
connectors_.AddBinding(this, std::move(request));
}
-ServiceRegistryImpl* FrameMojoShell::GetServiceRegistry() {
- if (!service_registry_) {
- service_registry_.reset(new ServiceRegistryImpl());
+shell::InterfaceRegistry* FrameMojoShell::GetInterfaceRegistry() {
+ if (!interface_registry_) {
+ interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
// TODO(rockot/xhwang): Currently all applications connected share the same
- // set of services registered in the |registry|. We may want to provide
- // different services for different apps for better isolation.
- RegisterFrameMojoShellServices(service_registry_.get(), frame_host_);
- GetContentClient()->browser()->RegisterFrameMojoShellServices(
- service_registry_.get(), frame_host_);
+ // set of interfaces registered in the |registry|. We may want to provide
+ // different interfaces for different apps for better isolation.
+ RegisterFrameMojoShellInterfaces(interface_registry_.get(), frame_host_);
+ GetContentClient()->browser()->RegisterFrameMojoShellInterfaces(
+ interface_registry_.get(), frame_host_);
}
- return service_registry_.get();
+ return interface_registry_.get();
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_mojo_shell.h b/chromium/content/browser/frame_host/frame_mojo_shell.h
index 63d386d00ff..8481f0894a2 100644
--- a/chromium/content/browser/frame_host/frame_mojo_shell.h
+++ b/chromium/content/browser/frame_host/frame_mojo_shell.h
@@ -12,14 +12,16 @@
#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/shell/public/interfaces/connector.mojom.h"
-namespace content {
+namespace shell {
+class InterfaceRegistry;
+}
+namespace content {
class RenderFrameHost;
-class ServiceRegistryImpl;
-// This provides the |shell::mojom::Shell| service interface to each
-// frame's ServiceRegistry, giving frames the ability to connect to Mojo
-// applications.
+// This provides the |shell::mojom::Connector| interface interface to each
+// frame's shell::InterfaceRegistry, giving frames the ability to connect to
+// Mojo services.
class FrameMojoShell : public shell::mojom::Connector {
public:
explicit FrameMojoShell(RenderFrameHost* frame_host);
@@ -37,14 +39,16 @@ class FrameMojoShell : public shell::mojom::Connector {
const shell::mojom::Connector::ConnectCallback& callback) override;
void Clone(shell::mojom::ConnectorRequest request) override;
- ServiceRegistryImpl* GetServiceRegistry();
+ shell::InterfaceRegistry* GetInterfaceRegistry();
RenderFrameHost* frame_host_;
mojo::BindingSet<shell::mojom::Connector> connectors_;
- // ServiceRegistry providing browser services to connected applications.
- std::unique_ptr<ServiceRegistryImpl> service_registry_;
- mojo::BindingSet<shell::mojom::InterfaceProvider> service_provider_bindings_;
+ // shell::InterfaceRegistry providing browser interfaces to connected
+ // applications.
+ std::unique_ptr<shell::InterfaceRegistry> interface_registry_;
+ mojo::BindingSet<shell::mojom::InterfaceProvider>
+ interface_provider_bindings_;
DISALLOW_COPY_AND_ASSIGN(FrameMojoShell);
};
diff --git a/chromium/content/browser/frame_host/frame_navigation_entry.cc b/chromium/content/browser/frame_host/frame_navigation_entry.cc
index a788c45b8b3..26671f7df44 100644
--- a/chromium/content/browser/frame_host/frame_navigation_entry.cc
+++ b/chromium/content/browser/frame_host/frame_navigation_entry.cc
@@ -6,6 +6,9 @@
#include <utility>
+#include "content/common/page_state_serialization.h"
+#include "content/common/site_isolation_policy.h"
+
namespace content {
FrameNavigationEntry::FrameNavigationEntry()
@@ -80,4 +83,18 @@ void FrameNavigationEntry::set_document_sequence_number(
document_sequence_number_ = document_sequence_number;
}
+scoped_refptr<ResourceRequestBodyImpl> FrameNavigationEntry::GetPostData()
+ const {
+ DCHECK(SiteIsolationPolicy::UseSubframeNavigationEntries());
+ if (method_ != "POST")
+ return nullptr;
+
+ // Generate the body from the PageState.
+ ExplodedPageState exploded_state;
+ if (!DecodePageState(page_state_.ToEncodedData(), &exploded_state))
+ return nullptr;
+
+ return exploded_state.top.http_body.request_body;
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_navigation_entry.h b/chromium/content/browser/frame_host/frame_navigation_entry.h
index 5470c484fbb..39965e2e025 100644
--- a/chromium/content/browser/frame_host/frame_navigation_entry.h
+++ b/chromium/content/browser/frame_host/frame_navigation_entry.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/browser/site_instance_impl.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/public/common/page_state.h"
#include "content/public/common/referrer.h"
@@ -121,6 +122,10 @@ class CONTENT_EXPORT FrameNavigationEntry
int64_t post_id() const { return post_id_; }
void set_post_id(int64_t post_id) { post_id_ = post_id; }
+ // The data sent during a POST navigation. Returns nullptr if the navigation
+ // is not a POST.
+ scoped_refptr<ResourceRequestBodyImpl> GetPostData() const;
+
private:
friend class base::RefCounted<FrameNavigationEntry>;
virtual ~FrameNavigationEntry();
diff --git a/chromium/content/browser/frame_host/frame_tree.cc b/chromium/content/browser/frame_host/frame_tree.cc
index a85c7fa3a5a..fd78babe87e 100644
--- a/chromium/content/browser/frame_host/frame_tree.cc
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -21,6 +21,7 @@
#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/common/content_switches_internal.h"
#include "content/common/input_messages.h"
#include "content/common/site_isolation_policy.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
@@ -371,16 +372,36 @@ void FrameTree::FrameRemoved(FrameTreeNode* frame) {
void FrameTree::UpdateLoadProgress() {
double progress = 0.0;
+ ProgressBarCompletion completion = GetProgressBarCompletionPolicy();
int frame_count = 0;
-
- for (FrameTreeNode* node : Nodes()) {
- // Ignore the current frame if it has not started loading.
- if (!node->has_started_loading())
- continue;
-
- // Collect progress.
- progress += node->loading_progress();
- frame_count++;
+ switch (completion) {
+ case ProgressBarCompletion::DOM_CONTENT_LOADED:
+ case ProgressBarCompletion::RESOURCES_BEFORE_DCL:
+ if (root_->has_started_loading())
+ progress = root_->loading_progress();
+ break;
+ case ProgressBarCompletion::LOAD_EVENT:
+ for (FrameTreeNode* node : Nodes()) {
+ // Ignore the current frame if it has not started loading.
+ if (!node->has_started_loading())
+ continue;
+ progress += node->loading_progress();
+ frame_count++;
+ }
+ break;
+ case ProgressBarCompletion::RESOURCES_BEFORE_DCL_AND_SAME_ORIGIN_IFRAMES:
+ for (FrameTreeNode* node : Nodes()) {
+ // 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))
+ continue;
+ progress += node->loading_progress();
+ frame_count++;
+ }
+ break;
+ default:
+ NOTREACHED();
}
if (frame_count != 0)
diff --git a/chromium/content/browser/frame_host/frame_tree_browsertest.cc b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
index 396ab05ab2a..0fd2ac04c43 100644
--- a/chromium/content/browser/frame_host/frame_tree_browsertest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
@@ -45,8 +45,8 @@ class FrameTreeBrowserTest : public ContentBrowserTest {
std::string GetOriginFromRenderer(FrameTreeNode* node) {
std::string origin;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- node->current_frame_host(),
- "window.domAutomationController.send(document.origin);", &origin));
+ node, "window.domAutomationController.send(document.origin);",
+ &origin));
return origin;
}
@@ -320,7 +320,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateGrandchildToBlob) {
std::string blob_url_string;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->current_frame_host(),
+ root,
"function receiveMessage(event) {"
" document.body.appendChild(document.createTextNode(event.data));"
" domAutomationController.send(event.source.location.href);"
@@ -341,7 +341,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateGrandchildToBlob) {
std::string document_body;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- target->current_frame_host(),
+ target,
"domAutomationController.send(document.body.children[0].innerHTML);",
&document_body));
EXPECT_EQ("This is blob content.", document_body);
@@ -362,13 +362,12 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateChildToAboutBlank) {
FrameTreeNode* initiator = target->parent();
// Give the target a name.
- EXPECT_TRUE(
- ExecuteScript(target->current_frame_host(), "window.name = 'target';"));
+ EXPECT_TRUE(ExecuteScript(target, "window.name = 'target';"));
// Use window.open(about:blank), then poll the document for access.
std::string about_blank_origin;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- initiator->current_frame_host(),
+ initiator,
"var didNavigate = false;"
"var intervalID = setInterval(function() {"
" if (!didNavigate) {"
@@ -392,8 +391,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateChildToAboutBlank) {
std::string document_body;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- target->current_frame_host(),
- "domAutomationController.send(document.body.innerHTML);",
+ target, "domAutomationController.send(document.body.innerHTML);",
&document_body));
EXPECT_EQ("Hi from b.com", document_body);
}
@@ -416,13 +414,12 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest,
FrameTreeNode* initiator = target->parent()->parent();
// Give the target a name.
- EXPECT_TRUE(
- ExecuteScript(target->current_frame_host(), "window.name = 'target';"));
+ EXPECT_TRUE(ExecuteScript(target, "window.name = 'target';"));
// Use window.open(about:blank), then poll the document for access.
std::string about_blank_origin;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- initiator->current_frame_host(),
+ initiator,
"var didNavigate = false;"
"var intervalID = setInterval(function() {"
" if (!didNavigate) {"
@@ -444,8 +441,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest,
std::string document_body;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- target->current_frame_host(),
- "domAutomationController.send(document.body.innerHTML);",
+ target, "domAutomationController.send(document.body.innerHTML);",
&document_body));
EXPECT_EQ("Hi from a.com", document_body);
}
@@ -464,8 +460,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
FrameTreeNode* child = root->child_at(0);
std::string frame_origin;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- child->current_frame_host(),
- "domAutomationController.send(document.origin);", &frame_origin));
+ child, "domAutomationController.send(document.origin);", &frame_origin));
EXPECT_TRUE(
child->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
url::Origin(GURL(frame_origin))));
@@ -480,14 +475,14 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
"f.srcdoc = 'some content';"
"document.body.appendChild(f)");
TestNavigationObserver observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
EXPECT_EQ(2U, root->child_count());
observer.Wait();
EXPECT_EQ(GURL(url::kAboutBlankURL), root->child_at(1)->current_url());
EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(1)->current_frame_host(),
- "domAutomationController.send(document.origin);", &frame_origin));
+ root->child_at(1), "domAutomationController.send(document.origin);",
+ &frame_origin));
EXPECT_EQ(root->current_frame_host()->GetLastCommittedURL().GetOrigin(),
GURL(frame_origin));
EXPECT_NE(child->current_frame_host()->GetLastCommittedURL().GetOrigin(),
@@ -500,13 +495,13 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
std::string script("var f = document.getElementById('child-0');"
"f.srcdoc = 'some content';");
TestNavigationObserver observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
observer.Wait();
EXPECT_EQ(GURL(url::kAboutBlankURL), child->current_url());
EXPECT_TRUE(ExecuteScriptAndExtractString(
- child->current_frame_host(),
- "domAutomationController.send(document.origin);", &frame_origin));
+ child, "domAutomationController.send(document.origin);",
+ &frame_origin));
EXPECT_EQ(root->current_frame_host()->GetLastCommittedURL().GetOrigin(),
GURL(frame_origin));
}
@@ -565,7 +560,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, SubframeOpenerSetForNewWindow) {
// Open a new window from a subframe.
ShellAddedObserver new_shell_observer;
GURL popup_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
"window.open('" + popup_url.spec() + "');"));
Shell* new_shell = new_shell_observer.GetShell();
WebContents* new_contents = new_shell->web_contents();
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
index fc06a2f114a..ab3b794c66f 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -16,7 +16,6 @@
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/frame_host/traced_frame_tree_node.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/common/frame_messages.h"
#include "content/common/site_isolation_policy.h"
@@ -107,18 +106,17 @@ FrameTreeNode::FrameTreeNode(
false /* is a potentially trustworthy unique origin */),
pending_sandbox_flags_(blink::WebSandboxFlags::None),
frame_owner_properties_(frame_owner_properties),
- loading_progress_(kLoadingProgressNotStarted) {
+ loading_progress_(kLoadingProgressNotStarted),
+ blame_context_(frame_tree_node_id_, parent) {
std::pair<FrameTreeNodeIdMap::iterator, bool> result =
g_frame_tree_node_id_map.Get().insert(
std::make_pair(frame_tree_node_id_, this));
CHECK(result.second);
RecordUniqueNameLength(unique_name.size());
- TRACE_EVENT_OBJECT_CREATED_WITH_ID(
- "navigation", "FrameTreeNode",
- TRACE_ID_WITH_SCOPE("FrameTreeNode", frame_tree_node_id_));
- // Don't TraceSnapshot() until the RenderFrameHostManager is initialized and
- // calls SetCurrentURL().
+
+ // Note: this should always be done last in the constructor.
+ blame_context_.Initialize();
}
FrameTreeNode::~FrameTreeNode() {
@@ -130,10 +128,6 @@ FrameTreeNode::~FrameTreeNode() {
opener_->RemoveObserver(opener_observer_.get());
g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
-
- TRACE_EVENT_OBJECT_DELETED_WITH_ID(
- "navigation", "FrameTreeNode",
- TRACE_ID_WITH_SCOPE("FrameTreeNode", frame_tree_node_id_));
}
void FrameTreeNode::AddObserver(Observer* observer) {
@@ -189,7 +183,7 @@ void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
void FrameTreeNode::ResetForNewProcess() {
current_frame_host()->set_last_committed_url(GURL());
- TraceSnapshot();
+ blame_context_.TakeSnapshot();
// Remove child nodes from the tree, then delete them. This destruction
// operation will notify observers.
@@ -215,7 +209,7 @@ void FrameTreeNode::SetCurrentURL(const GURL& url) {
if (!has_committed_real_load_ && url != GURL(url::kAboutBlankURL))
has_committed_real_load_ = true;
current_frame_host()->set_last_committed_url(url);
- TraceSnapshot();
+ blame_context_.TakeSnapshot();
}
void FrameTreeNode::SetCurrentOrigin(
@@ -256,14 +250,12 @@ void FrameTreeNode::ResetContentSecurityPolicy() {
render_manager_.OnDidResetContentSecurityPolicy();
}
-void FrameTreeNode::SetEnforceStrictMixedContentChecking(bool should_enforce) {
- if (should_enforce ==
- replication_state_.should_enforce_strict_mixed_content_checking) {
+void FrameTreeNode::SetInsecureRequestPolicy(
+ blink::WebInsecureRequestPolicy policy) {
+ if (policy == replication_state_.insecure_request_policy)
return;
- }
- render_manager_.OnEnforceStrictMixedContentChecking(should_enforce);
- replication_state_.should_enforce_strict_mixed_content_checking =
- should_enforce;
+ render_manager_.OnEnforceInsecureRequestPolicy(policy);
+ replication_state_.insecure_request_policy = policy;
}
void FrameTreeNode::SetPendingSandboxFlags(
@@ -491,15 +483,6 @@ void FrameTreeNode::BeforeUnloadCanceled() {
}
}
-void FrameTreeNode::TraceSnapshot() const {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
- "navigation", "FrameTreeNode",
- TRACE_ID_WITH_SCOPE("FrameTreeNode", frame_tree_node_id_),
- std::unique_ptr<base::trace_event::ConvertableToTraceFormat>(
- new TracedFrameTreeNode(*this)));
-}
-
FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
if (!parent_ || !parent_->child_count())
return nullptr;
diff --git a/chromium/content/browser/frame_host/frame_tree_node.h b/chromium/content/browser/frame_host/frame_tree_node.h
index c6ab2b38d6e..35da0f83de6 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.h
+++ b/chromium/content/browser/frame_host/frame_tree_node.h
@@ -13,10 +13,12 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "content/browser/frame_host/frame_tree_node_blame_context.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/common/content_export.h"
#include "content/common/frame_replication_state.h"
+#include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
#include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -155,9 +157,9 @@ class CONTENT_EXPORT FrameTreeNode {
// new document comes with a fresh set of CSP http headers).
void ResetContentSecurityPolicy();
- // Sets the current enforcement of strict mixed content checking and
- // notifies proxies about the update.
- void SetEnforceStrictMixedContentChecking(bool should_enforce);
+ // Sets the current insecure request policy, and notifies proxies about the
+ // update.
+ void SetInsecureRequestPolicy(blink::WebInsecureRequestPolicy policy);
// Returns the currently active sandbox flags for this frame. This includes
// flags inherited from parent frames and the currently active flags from the
@@ -283,11 +285,12 @@ class CONTENT_EXPORT FrameTreeNode {
// FrameTreeNode.
void BeforeUnloadCanceled();
+ // Returns the BlameContext associated with this node.
+ FrameTreeNodeBlameContext& blame_context() { return blame_context_; }
+
private:
class OpenerDestroyedObserver;
- void TraceSnapshot() const;
-
FrameTreeNode* GetSibling(int relative_offset) const;
// The next available browser-global FrameTreeNode ID.
@@ -364,6 +367,11 @@ class CONTENT_EXPORT FrameTreeNode {
base::TimeTicks last_focus_time_;
+ // A helper for tracing the snapshots of this FrameTreeNode and attributing
+ // browser process activities to this node (when possible). It is unrelated
+ // to the core logic of FrameTreeNode.
+ FrameTreeNodeBlameContext blame_context_;
+
DISALLOW_COPY_AND_ASSIGN(FrameTreeNode);
};
diff --git a/chromium/content/browser/frame_host/frame_tree_node_blame_context.cc b/chromium/content/browser/frame_host/frame_tree_node_blame_context.cc
new file mode 100644
index 00000000000..bae5f2a0368
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_tree_node_blame_context.cc
@@ -0,0 +1,71 @@
+// 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/frame_host/frame_tree_node_blame_context.h"
+
+#include "base/strings/stringprintf.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+const char kFrameTreeNodeBlameContextCategory[] = "navigation";
+const char kFrameTreeNodeBlameContextName[] = "FrameTreeNodeBlameContext";
+const char kFrameTreeNodeBlameContextType[] = "FrameTreeNode";
+const char kFrameTreeNodeBlameContextScope[] = "FrameTreeNode";
+const char kRenderFrameBlameContextScope[] = "RenderFrame";
+
+} // namespace
+
+FrameTreeNodeBlameContext::FrameTreeNodeBlameContext(int node_id,
+ FrameTreeNode* parent)
+ : base::trace_event::BlameContext(kFrameTreeNodeBlameContextCategory,
+ kFrameTreeNodeBlameContextName,
+ kFrameTreeNodeBlameContextType,
+ kFrameTreeNodeBlameContextScope,
+ node_id,
+ parent ? &parent->blame_context()
+ : nullptr) {}
+
+FrameTreeNodeBlameContext::~FrameTreeNodeBlameContext() {}
+
+void FrameTreeNodeBlameContext::AsValueInto(
+ base::trace_event::TracedValue* value) {
+ BlameContext::AsValueInto(value);
+
+ // id() is equal to the owner FrameTreeNode's id, as set in the constructor.
+ FrameTreeNode* owner = FrameTreeNode::GloballyFindByID(id());
+ DCHECK(owner);
+
+ RenderFrameHostImpl* current_frame_host = owner->current_frame_host();
+ if (!current_frame_host)
+ return;
+
+ // On Windows, |rph->GetHandle()| does not duplicate ownership of the
+ // process handle and the render host still retains it. Therefore, we
+ // cannot create a base::Process object, which provides a proper way to get
+ // a process id, from the handle. For a stopgap, we use this deprecated
+ // function that does not require the ownership (http://crbug.com/417532).
+ int process_id = base::GetProcId(
+ current_frame_host->GetProcess()->GetHandle());
+ if (process_id >= 0) {
+ int routing_id = current_frame_host->GetRoutingID();
+ DCHECK_NE(routing_id, MSG_ROUTING_NONE);
+
+ value->BeginDictionary("renderFrame");
+ value->SetInteger("pid_ref", process_id);
+ value->SetString("id_ref", base::StringPrintf("0x%x", routing_id));
+ value->SetString("scope", kRenderFrameBlameContextScope);
+ value->EndDictionary();
+ }
+
+ GURL url = current_frame_host->last_committed_url();
+ if (url.is_valid())
+ value->SetString("url", url.spec());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_tree_node_blame_context.h b/chromium/content/browser/frame_host/frame_tree_node_blame_context.h
new file mode 100644
index 00000000000..6573f7cf6ab
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_tree_node_blame_context.h
@@ -0,0 +1,39 @@
+// 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_FRAME_HOST_FRAME_TREE_NODE_BLAME_CONTEXT_H
+#define CONTENT_BROWSER_FRAME_HOST_FRAME_TREE_NODE_BLAME_CONTEXT_H
+
+#include "base/macros.h"
+#include "base/trace_event/blame_context.h"
+#include "url/gurl.h"
+
+namespace base {
+namespace trace_event {
+class TracedValue;
+}
+}
+
+namespace content {
+
+class FrameTreeNode;
+
+// FrameTreeNodeBlameContext is a helper class for tracing snapshots of each
+// FrameTreeNode and attributing browser activities to frames (when possible),
+// in the framework of FrameBlamer (crbug.com/546021). This class is unrelated
+// to the core logic of FrameTreeNode.
+class FrameTreeNodeBlameContext : public base::trace_event::BlameContext {
+ public:
+ FrameTreeNodeBlameContext(int node_id, FrameTreeNode* parent);
+ ~FrameTreeNodeBlameContext() override;
+
+ private:
+ void AsValueInto(base::trace_event::TracedValue* value) override;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameTreeNodeBlameContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_FRAME_TREE_NODE_BLAME_CONTEXT_H
diff --git a/chromium/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc b/chromium/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
new file mode 100644
index 00000000000..6f76b92ebe2
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
@@ -0,0 +1,263 @@
+// 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/frame_host/frame_tree_node_blame_context.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/test/trace_event_analyzer.h"
+#include "base/trace_event/trace_buffer.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/test/test_render_view_host.h"
+#include "content/test/test_web_contents.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebSandboxFlags.h"
+
+namespace content {
+
+namespace {
+
+bool EventPointerCompare(const trace_analyzer::TraceEvent* lhs,
+ const trace_analyzer::TraceEvent* rhs) {
+ CHECK(lhs);
+ CHECK(rhs);
+ return *lhs < *rhs;
+}
+
+void OnTraceDataCollected(base::Closure quit_closure,
+ base::trace_event::TraceResultBuffer* buffer,
+ const scoped_refptr<base::RefCountedString>& json,
+ bool has_more_events) {
+ buffer->AddFragment(json->data());
+ if (!has_more_events)
+ quit_closure.Run();
+}
+
+void ExpectFrameTreeNodeObject(const trace_analyzer::TraceEvent* event) {
+ EXPECT_EQ("navigation", event->category);
+ EXPECT_EQ("FrameTreeNode", event->name);
+}
+
+void ExpectFrameTreeNodeSnapshot(const trace_analyzer::TraceEvent* event) {
+ ExpectFrameTreeNodeObject(event);
+ EXPECT_TRUE(event->HasArg("snapshot"));
+ EXPECT_TRUE(event->arg_values.at("snapshot")
+ ->IsType(base::Value::Type::TYPE_DICTIONARY));
+}
+
+std::string GetParentNodeID(const trace_analyzer::TraceEvent* event) {
+ const base::Value* arg_snapshot = event->arg_values.at("snapshot").get();
+ const base::DictionaryValue* snapshot;
+ EXPECT_TRUE(arg_snapshot->GetAsDictionary(&snapshot));
+ if (!snapshot->HasKey("parent"))
+ return std::string();
+ const base::DictionaryValue* parent;
+ EXPECT_TRUE(snapshot->GetDictionary("parent", &parent));
+ std::string parent_id;
+ EXPECT_TRUE(parent->GetString("id_ref", &parent_id));
+ return parent_id;
+}
+
+std::string GetSnapshotURL(const trace_analyzer::TraceEvent* event) {
+ const base::Value* arg_snapshot = event->arg_values.at("snapshot").get();
+ const base::DictionaryValue* snapshot;
+ EXPECT_TRUE(arg_snapshot->GetAsDictionary(&snapshot));
+ if (!snapshot->HasKey("url"))
+ return std::string();
+ std::string url;
+ EXPECT_TRUE(snapshot->GetString("url", &url));
+ return url;
+}
+
+} // namespace
+
+class FrameTreeNodeBlameContextTest : public RenderViewHostImplTestHarness {
+ public:
+ FrameTree* tree() { return contents()->GetFrameTree(); }
+ FrameTreeNode* root() { return tree()->root(); }
+ int process_id() {
+ return root()->current_frame_host()->GetProcess()->GetID();
+ }
+
+ // Creates a frame tree specified by |shape|, which is a string of paired
+ // parentheses. Each pair of parentheses represents a FrameTreeNode, and the
+ // nesting of parentheses represents the parent-child relation between nodes.
+ // Nodes represented by outer-most parentheses are children of the root node.
+ // NOTE: Each node can have at most 9 child nodes, and the tree height (i.e.,
+ // max # of edges in any root-to-leaf path) must be at most 9.
+ // See the test cases for sample usage.
+ void CreateFrameTree(const char* shape) {
+ main_test_rfh()->InitializeRenderFrameIfNeeded();
+ CreateSubframes(root(), 1, shape);
+ }
+
+ void RemoveAllNonRootFrames() {
+ while (root()->child_count())
+ tree()->RemoveFrame(root()->child_at(0));
+ }
+
+ void StartTracing() {
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(
+ base::trace_event::TraceConfig("*"),
+ base::trace_event::TraceLog::RECORDING_MODE);
+ }
+
+ void StopTracing() {
+ base::trace_event::TraceLog::GetInstance()->SetDisabled();
+ }
+
+ std::unique_ptr<trace_analyzer::TraceAnalyzer> CreateTraceAnalyzer() {
+ base::trace_event::TraceResultBuffer buffer;
+ base::trace_event::TraceResultBuffer::SimpleOutput trace_output;
+ buffer.SetOutputCallback(trace_output.GetCallback());
+ base::RunLoop run_loop;
+ buffer.Start();
+ base::trace_event::TraceLog::GetInstance()->Flush(
+ base::Bind(&OnTraceDataCollected, run_loop.QuitClosure(),
+ base::Unretained(&buffer)));
+ run_loop.Run();
+ buffer.Finish();
+
+ return base::WrapUnique(
+ trace_analyzer::TraceAnalyzer::Create(trace_output.json_output));
+ }
+
+ private:
+ int CreateSubframes(FrameTreeNode* node, int self_id, const char* shape) {
+ int consumption = 0;
+ for (int child_num = 1; shape[consumption++] == '('; ++child_num) {
+ int child_id = self_id * 10 + child_num;
+ tree()->AddFrame(
+ node, process_id(), child_id, blink::WebTreeScopeType::Document,
+ std::string(), base::StringPrintf("uniqueName%d", child_id),
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
+ FrameTreeNode* child = node->child_at(child_num - 1);
+ consumption += CreateSubframes(child, child_id, shape + consumption);
+ }
+ return consumption;
+ }
+};
+
+// Creates a frame tree, tests if (i) the creation of each new frame is
+// correctly traced, and (ii) the topology given by the snapshots is correct.
+TEST_F(FrameTreeNodeBlameContextTest, FrameCreation) {
+ /* Shape of the frame tree to be created:
+ * ()
+ * / \
+ * () ()
+ * / \ |
+ * () () ()
+ * |
+ * ()
+ */
+ const char* tree_shape = "(()())((()))";
+
+ StartTracing();
+ CreateFrameTree(tree_shape);
+ StopTracing();
+
+ std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer =
+ CreateTraceAnalyzer();
+ trace_analyzer::TraceEventVector events;
+ trace_analyzer::Query q =
+ trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_CREATE_OBJECT) ||
+ trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT);
+ analyzer->FindEvents(q, &events);
+
+ // Two events for each new node: creation and snapshot.
+ EXPECT_EQ(12u, events.size());
+
+ std::set<FrameTreeNode*> creation_traced;
+ std::set<FrameTreeNode*> snapshot_traced;
+ for (auto event : events) {
+ ExpectFrameTreeNodeObject(event);
+ FrameTreeNode* node =
+ tree()->FindByID(strtol(event->id.c_str(), nullptr, 16));
+ EXPECT_NE(nullptr, node);
+ if (event->HasArg("snapshot")) {
+ ExpectFrameTreeNodeSnapshot(event);
+ EXPECT_FALSE(ContainsValue(snapshot_traced, node));
+ snapshot_traced.insert(node);
+ std::string parent_id = GetParentNodeID(event);
+ EXPECT_FALSE(parent_id.empty());
+ EXPECT_EQ(node->parent(),
+ tree()->FindByID(strtol(parent_id.c_str(), nullptr, 16)));
+ } else {
+ EXPECT_EQ(TRACE_EVENT_PHASE_CREATE_OBJECT, event->phase);
+ EXPECT_FALSE(ContainsValue(creation_traced, node));
+ creation_traced.insert(node);
+ }
+ }
+}
+
+// Deletes frames from a frame tree, tests if the destruction of each frame is
+// correctly traced.
+TEST_F(FrameTreeNodeBlameContextTest, FrameDeletion) {
+ /* Shape of the frame tree to be created:
+ * ()
+ * / \
+ * () ()
+ * / \ |
+ * () () ()
+ * |
+ * ()
+ */
+ const char* tree_shape = "(()())((()))";
+
+ CreateFrameTree(tree_shape);
+ std::set<int> node_ids;
+ for (FrameTreeNode* node : tree()->Nodes())
+ node_ids.insert(node->frame_tree_node_id());
+
+ StartTracing();
+ RemoveAllNonRootFrames();
+ StopTracing();
+
+ std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer =
+ CreateTraceAnalyzer();
+ trace_analyzer::TraceEventVector events;
+ trace_analyzer::Query q =
+ trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_DELETE_OBJECT);
+ analyzer->FindEvents(q, &events);
+
+ // The removal of all non-root nodes should be traced.
+ EXPECT_EQ(6u, events.size());
+ for (auto event : events) {
+ ExpectFrameTreeNodeObject(event);
+ int id = strtol(event->id.c_str(), nullptr, 16);
+ EXPECT_TRUE(ContainsValue(node_ids, id));
+ node_ids.erase(id);
+ }
+}
+
+// Changes URL of the root node. Tests if URL change is correctly traced.
+TEST_F(FrameTreeNodeBlameContextTest, URLChange) {
+ main_test_rfh()->InitializeRenderFrameIfNeeded();
+ GURL url1("http://a.com/");
+ GURL url2("https://b.net/");
+
+ StartTracing();
+ root()->SetCurrentURL(url1);
+ root()->SetCurrentURL(url2);
+ root()->ResetForNewProcess();
+ StopTracing();
+
+ std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer =
+ CreateTraceAnalyzer();
+ trace_analyzer::TraceEventVector events;
+ trace_analyzer::Query q =
+ trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT);
+ analyzer->FindEvents(q, &events);
+ std::sort(events.begin(), events.end(), EventPointerCompare);
+
+ // Three snapshots are traced, one for each URL change.
+ EXPECT_EQ(3u, events.size());
+ EXPECT_EQ(url1.spec(), GetSnapshotURL(events[0]));
+ EXPECT_EQ(url2.spec(), GetSnapshotURL(events[1]));
+ EXPECT_EQ("", GetSnapshotURL(events[2]));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index 2d20802c43b..47e0c483709 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -29,6 +29,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_view_base.h"
+#include "content/browser/renderer_host/text_input_manager.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
@@ -42,6 +43,7 @@
#include "content/public/browser/invalidate_type.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/storage_partition.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents_delegate.h"
@@ -61,7 +63,7 @@ class InterstitialPageImpl::InterstitialPageRVHDelegateView
explicit InterstitialPageRVHDelegateView(InterstitialPageImpl* page);
// RenderViewHostDelegateView implementation:
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
void ShowPopupMenu(RenderFrameHost* render_frame_host,
const gfx::Rect& bounds,
int item_height,
@@ -759,19 +761,22 @@ void InterstitialPageImpl::CreateNewFullscreenWidget(int32_t render_process_id,
<< "InterstitialPage does not support showing full screen popups.";
}
-void InterstitialPageImpl::ShowCreatedWindow(int route_id,
+void InterstitialPageImpl::ShowCreatedWindow(int process_id,
+ int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) {
NOTREACHED() << "InterstitialPage does not support showing popups yet.";
}
-void InterstitialPageImpl::ShowCreatedWidget(int route_id,
+void InterstitialPageImpl::ShowCreatedWidget(int process_id,
+ int route_id,
const gfx::Rect& initial_rect) {
NOTREACHED() << "InterstitialPage does not support showing drop-downs yet.";
}
-void InterstitialPageImpl::ShowCreatedFullscreenWidget(int route_id) {
+void InterstitialPageImpl::ShowCreatedFullscreenWidget(int process_id,
+ int route_id) {
NOTREACHED()
<< "InterstitialPage does not support showing full screen popups.";
}
@@ -866,7 +871,7 @@ InterstitialPageImpl::InterstitialPageRVHDelegateView::
: interstitial_page_(page) {
}
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
void InterstitialPageImpl::InterstitialPageRVHDelegateView::ShowPopupMenu(
RenderFrameHost* render_frame_host,
const gfx::Rect& bounds,
@@ -937,4 +942,9 @@ void InterstitialPageImpl::UnderlyingContentObserver::WebContentsDestroyed() {
interstitial_->OnNavigatingAwayOrTabClosing();
}
+TextInputManager* InterstitialPageImpl::GetTextInputManager() {
+ return !web_contents_ ? nullptr : static_cast<WebContentsImpl*>(web_contents_)
+ ->GetTextInputManager();
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index cbefe14f18f..9d3ed241ec0 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -30,6 +30,7 @@ class NavigationEntry;
class NavigationControllerImpl;
class RenderViewHostImpl;
class RenderWidgetHostView;
+class TextInputManager;
class WebContentsView;
enum ResourceRequestAction {
@@ -140,12 +141,15 @@ class CONTENT_EXPORT InterstitialPageImpl
blink::WebPopupType popup_type) override;
void CreateNewFullscreenWidget(int32_t render_process_id,
int32_t route_id) override;
- void ShowCreatedWindow(int route_id,
+ void ShowCreatedWindow(int process_id,
+ int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) override;
- void ShowCreatedWidget(int route_id, const gfx::Rect& initial_rect) override;
- void ShowCreatedFullscreenWidget(int route_id) override;
+ void ShowCreatedWidget(int process_id,
+ int route_id,
+ const gfx::Rect& initial_rect) override;
+ void ShowCreatedFullscreenWidget(int process_id, int route_id) override;
SessionStorageNamespace* GetSessionStorageNamespace(
SiteInstance* instance) override;
@@ -157,6 +161,7 @@ class CONTENT_EXPORT InterstitialPageImpl
bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
bool* is_keyboard_shortcut) override;
void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override;
+ TextInputManager* GetTextInputManager() override;
bool enabled() const { return enabled_; }
WebContents* web_contents() const;
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc b/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc
index 00a5bec3d21..2fbdda35c98 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc
@@ -4,6 +4,8 @@
#include "content/browser/frame_host/interstitial_page_impl.h"
+#include <tuple>
+
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
@@ -105,7 +107,7 @@ class InterstitialTitleUpdateWatcher : public BrowserMessageFilter {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&InterstitialTitleUpdateWatcher::OnTitleUpdateReceived,
- this, base::get<0>(params)));
+ this, std::get<0>(params)));
}
}
return false;
@@ -160,7 +162,7 @@ class ClipboardMessageWatcher : public IPC::MessageFilter {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&ClipboardMessageWatcher::OnWriteText, this,
- base::UTF16ToUTF8(base::get<1>(params))));
+ base::UTF16ToUTF8(std::get<1>(params))));
}
return true;
}
@@ -326,7 +328,9 @@ class InterstitialPageImplTest : public ContentBrowserTest {
private:
void RunTaskOnIOThreadAndWait(const base::Closure& task) {
- base::WaitableEvent completion(false, false);
+ base::WaitableEvent completion(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&InterstitialPageImplTest::RunTask, this,
task, &completion));
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.cc b/chromium/content/browser/frame_host/navigation_controller_android.cc
index 840771550f4..905757c65ff 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_android.cc
@@ -7,12 +7,12 @@
#include <stdint.h>
#include "base/android/jni_android.h"
-#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/ssl_host_state_delegate.h"
+#include "content/public/common/resource_request_body.h"
#include "jni/NavigationControllerImpl_jni.h"
#include "net/base/data_url.h"
#include "ui/gfx/android/java_bitmap.h"
@@ -202,7 +202,7 @@ void NavigationControllerAndroid::LoadUrl(
jint referrer_policy,
jint ua_override_option,
const JavaParamRef<jstring>& extra_headers,
- const JavaParamRef<jbyteArray>& post_data,
+ const JavaParamRef<jobject>& j_post_data,
const JavaParamRef<jstring>& base_url_for_data_url,
const JavaParamRef<jstring>& virtual_url_for_data_url,
const JavaParamRef<jstring>& data_url_as_string,
@@ -226,12 +226,7 @@ void NavigationControllerAndroid::LoadUrl(
if (extra_headers)
params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
- if (post_data) {
- std::vector<uint8_t> http_body_vector;
- base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
- params.browser_initiated_post_data =
- base::RefCountedBytes::TakeVector(&http_body_vector);
- }
+ params.post_data = ResourceRequestBody::FromJavaObject(env, j_post_data);
if (base_url_for_data_url) {
params.base_url_for_data_url =
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.h b/chromium/content/browser/frame_host/navigation_controller_android.h
index 701bc9a5211..fb2af84a19a 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.h
+++ b/chromium/content/browser/frame_host/navigation_controller_android.h
@@ -80,7 +80,7 @@ class CONTENT_EXPORT NavigationControllerAndroid {
jint referrer_policy,
jint ua_override_option,
const base::android::JavaParamRef<jstring>& extra_headers,
- const base::android::JavaParamRef<jbyteArray>& post_data,
+ const base::android::JavaParamRef<jobject>& j_post_data,
const base::android::JavaParamRef<jstring>& base_url_for_data_url,
const base::android::JavaParamRef<jstring>& virtual_url_for_data_url,
const base::android::JavaParamRef<jstring>& data_url_as_string,
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index 0cadcfc0281..4179c2d32c6 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -256,11 +256,6 @@ BrowserContext* NavigationControllerImpl::GetBrowserContext() const {
return browser_context_;
}
-void NavigationControllerImpl::SetBrowserContext(
- BrowserContext* browser_context) {
- browser_context_ = browser_context;
-}
-
void NavigationControllerImpl::Restore(
int selected_navigation,
RestoreType type,
@@ -669,7 +664,10 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
switch (params.load_type) {
case LOAD_TYPE_DEFAULT:
break;
- case LOAD_TYPE_BROWSER_INITIATED_HTTP_POST:
+ case LOAD_TYPE_HTTP_POST:
+ // TODO(lukasza): This assertion is false - it is also possible to POST to
+ // an chrome-extension://... URI. This might be more common when
+ // allowing renderer-initiated POST after fixing https://crbug.com/344348.
if (!params.url.SchemeIs(url::kHttpScheme) &&
!params.url.SchemeIs(url::kHttpsScheme)) {
NOTREACHED() << "Http post load must use http(s) scheme.";
@@ -768,10 +766,9 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
switch (params.load_type) {
case LOAD_TYPE_DEFAULT:
break;
- case LOAD_TYPE_BROWSER_INITIATED_HTTP_POST:
+ case LOAD_TYPE_HTTP_POST:
entry->SetHasPostData(true);
- entry->SetBrowserInitiatedPostData(
- params.browser_initiated_post_data.get());
+ entry->SetPostData(params.post_data);
break;
case LOAD_TYPE_DATA:
entry->SetBaseURLForDataURL(params.base_url_for_data_url);
@@ -1682,7 +1679,8 @@ int NavigationControllerImpl::GetPendingEntryIndex() const {
void NavigationControllerImpl::InsertOrReplaceEntry(
std::unique_ptr<NavigationEntryImpl> entry,
bool replace) {
- DCHECK(entry->GetTransitionType() != ui::PAGE_TRANSITION_AUTO_SUBFRAME);
+ DCHECK(!ui::PageTransitionCoreTypeIs(entry->GetTransitionType(),
+ ui::PAGE_TRANSITION_AUTO_SUBFRAME));
// If the pending_entry_index_ is -1, the navigation was to a new page, and we
// need to keep continuity with the pending entry, so copy the pending entry's
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index b7b59e56dea..06d609c45cb 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -42,7 +42,6 @@ class CONTENT_EXPORT NavigationControllerImpl
// NavigationController implementation:
WebContents* GetWebContents() const override;
BrowserContext* GetBrowserContext() const override;
- void SetBrowserContext(BrowserContext* browser_context) override;
void Restore(int selected_navigation,
RestoreType type,
std::vector<std::unique_ptr<NavigationEntry>>* entries) override;
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 8197d571ca6..3e2512042c6 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -29,6 +29,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/renderer_preferences.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -131,6 +132,69 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, LoadDataWithBaseURL) {
EXPECT_EQ(data_url, reload_entry->GetURL());
}
+// Verify which page loads when going back to a LoadDataWithBaseURL entry.
+// See https://crbug.com/612196.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ LoadDataWithBaseURLTitleAfterBack) {
+ const GURL base_url("http://baseurl");
+ const GURL history_url(
+ embedded_test_server()->GetURL("/navigation_controller/form.html"));
+ const std::string data1 = "<html><title>One</title><body>foo</body></html>";
+ const GURL data_url1 = GURL("data:text/html;charset=utf-8," + data1);
+
+ NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+
+ {
+ TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
+ shell()->LoadDataWithBaseURL(history_url, data1, base_url);
+ same_tab_observer.Wait();
+ }
+
+ // Verify the last committed NavigationEntry.
+ NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
+ EXPECT_EQ(base_url, entry->GetBaseURLForDataURL());
+ EXPECT_EQ(history_url, entry->GetVirtualURL());
+ EXPECT_EQ(history_url, entry->GetHistoryURLForDataURL());
+ EXPECT_EQ(data_url1, entry->GetURL());
+
+ // Navigate again to a different data URL.
+ const std::string data2 = "<html><title>Two</title><body>bar</body></html>";
+ const GURL data_url2 = GURL("data:text/html;charset=utf-8," + data2);
+ {
+ TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
+ // Load data, not loaddatawithbaseurl.
+ EXPECT_TRUE(NavigateToURL(shell(), data_url2));
+ same_tab_observer.Wait();
+ }
+
+ // Go back.
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ controller.GoBack();
+ back_load_observer.Wait();
+
+ // Check title.
+ // TODO(creis): The default navigation path incorrectly loads the history_url
+ // and claims it loaded the data_url (due to a bug where GoToEntry does not
+ // handle this case). This is confusing. When using subframe
+ // FrameNavigationEntries, we load the data URL when going back, as expected.
+ if (SiteIsolationPolicy::UseSubframeNavigationEntries())
+ EXPECT_EQ("One", base::UTF16ToUTF8(shell()->web_contents()->GetTitle()));
+ else
+ EXPECT_EQ("form", base::UTF16ToUTF8(shell()->web_contents()->GetTitle()));
+
+ // Verify the last committed NavigationEntry.
+ NavigationEntryImpl* back_entry = controller.GetLastCommittedEntry();
+ EXPECT_EQ(base_url, back_entry->GetBaseURLForDataURL());
+ EXPECT_EQ(history_url, back_entry->GetVirtualURL());
+ EXPECT_EQ(history_url, back_entry->GetHistoryURLForDataURL());
+ EXPECT_EQ(data_url1, back_entry->GetOriginalRequestURL());
+ EXPECT_EQ(data_url1, back_entry->GetURL());
+
+ EXPECT_EQ(data_url1,
+ shell()->web_contents()->GetMainFrame()->GetLastCommittedURL());
+}
+
#if defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadDataWithInvalidBaseURL) {
@@ -193,7 +257,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "document.location = '" +
navigate_url.spec() + "';";
TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+ EXPECT_TRUE(ExecuteScript(shell(), script));
same_tab_observer.Wait();
EXPECT_EQ(2, controller.GetEntryCount());
NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
@@ -240,8 +304,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(data_url, entry->GetURL());
// Passes if renderer is still alive.
- EXPECT_TRUE(
- ExecuteScript(shell()->web_contents(), "console.log('Success');"));
+ EXPECT_TRUE(ExecuteScript(shell(), "console.log('Success');"));
}
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, UniqueIDs) {
@@ -256,7 +319,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, UniqueIDs) {
// Use JavaScript to click the link and load the iframe.
std::string script = "document.getElementById('link').click()";
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+ EXPECT_TRUE(ExecuteScript(shell(), script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
ASSERT_EQ(2, controller.GetEntryCount());
@@ -361,9 +424,7 @@ namespace {
int RendererHistoryLength(Shell* shell) {
int value = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- shell->web_contents(),
- "domAutomationController.send(history.length)",
- &value));
+ shell, "domAutomationController.send(history.length)", &value));
return value;
}
@@ -440,8 +501,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
ShellAddedObserver observer;
std::string page_url = embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html").spec();
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.open('" + page_url + "', '_blank')"));
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "window.open('" + page_url + "', '_blank')"));
Shell* shell2 = observer.GetShell();
EXPECT_TRUE(WaitForLoadStop(shell2->web_contents()));
@@ -677,7 +738,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, SubframeOnEmptyPage) {
ShellAddedObserver new_shell_observer;
{
std::string script = "window.open()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
}
Shell* new_shell = new_shell_observer.GetShell();
ASSERT_NE(new_shell->web_contents(), shell()->web_contents());
@@ -695,7 +756,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, SubframeOnEmptyPage) {
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = 'data:text/html,<p>some page</p>';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(new_root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(new_root, script));
capturer.Wait();
}
ASSERT_EQ(1U, new_root->child_count());
@@ -707,8 +768,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, SubframeOnEmptyPage) {
{
LoadCommittedCapturer capturer(new_shell->web_contents());
std::string script = "location.assign('" + frame_url.spec() + "')";
- EXPECT_TRUE(
- ExecuteScript(new_root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(new_root->child_at(0), script));
capturer.Wait();
}
@@ -724,14 +784,94 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, SubframeOnEmptyPage) {
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + grandchild_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(
- ExecuteScript(new_root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(new_root->child_at(0), script));
capturer.Wait();
}
ASSERT_EQ(1U, new_root->child_at(0)->child_count());
EXPECT_EQ(grandchild_url, new_root->child_at(0)->child_at(0)->current_url());
}
+// Test that the renderer is not killed after an auto subframe navigation if the
+// main frame appears to change its origin due to a document.write on an
+// about:blank page. See https://crbug.com/613732.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ OriginChangeAfterDocumentWrite) {
+ GURL url1 = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html");
+ EXPECT_TRUE(NavigateToURL(shell(), url1));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Pop open a new window to about:blank.
+ ShellAddedObserver new_shell_observer;
+ EXPECT_TRUE(ExecuteScript(root, "var w = window.open('about:blank')"));
+ Shell* new_shell = new_shell_observer.GetShell();
+ ASSERT_NE(new_shell->web_contents(), shell()->web_contents());
+ FrameTreeNode* new_root =
+ static_cast<WebContentsImpl*>(new_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+ GURL blank_url(url::kAboutBlankURL);
+ EXPECT_EQ(blank_url, new_root->current_url());
+
+ // Make a new iframe in it using document.write from the opener.
+ {
+ LoadCommittedCapturer capturer(new_shell->web_contents());
+ std::string script = "w.document.write("
+ "\"<iframe src='" + url1.spec() + "'></iframe>\");"
+ "w.document.close();";
+ EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ capturer.Wait();
+ }
+ ASSERT_EQ(1U, new_root->child_count());
+ EXPECT_EQ(blank_url, new_root->current_url());
+ EXPECT_EQ(url1, new_root->child_at(0)->current_url());
+
+ // Navigate the subframe.
+ GURL url2 = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_2.html");
+ {
+ LoadCommittedCapturer capturer(new_root->child_at(0));
+ std::string script = "location.href = '" + url2.spec() + "';";
+ EXPECT_TRUE(ExecuteScript(new_root->child_at(0), script));
+ capturer.Wait();
+ }
+ EXPECT_EQ(blank_url, new_root->current_url());
+ EXPECT_EQ(url2, new_root->child_at(0)->current_url());
+ EXPECT_EQ(2, new_shell->web_contents()->GetController().GetEntryCount());
+
+ // Do a replace state in the main frame, which changes the URL from
+ // about:blank to the opener's origin, due to the document.write() call.
+ {
+ LoadCommittedCapturer capturer(new_root);
+ std::string script = "history.replaceState({}, 'foo', 'foo');";
+ EXPECT_TRUE(ExecuteScript(new_root, script));
+ capturer.Wait();
+ }
+ EXPECT_EQ(embedded_test_server()->GetURL("/navigation_controller/foo"),
+ new_root->current_url());
+ EXPECT_EQ(url2, new_root->child_at(0)->current_url());
+
+ // Go back in the subframe. Note that the main frame's URL looks like a
+ // cross-origin change from a web URL to about:blank.
+ {
+ TestNavigationObserver observer(new_shell->web_contents(), 1);
+ new_shell->web_contents()->GetController().GoBack();
+ observer.Wait();
+ }
+ EXPECT_TRUE(new_root->current_frame_host()->IsRenderFrameLive());
+
+ // Go forward in the subframe. Note that the main frame's URL looks like a
+ // cross-origin change from about:blank to a web URL.
+ {
+ TestNavigationObserver observer(new_shell->web_contents(), 1);
+ new_shell->web_contents()->GetController().GoForward();
+ observer.Wait();
+ }
+ EXPECT_TRUE(new_root->current_frame_host()->IsRenderFrameLive());
+}
+
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
ErrorPageReplacement) {
NavigationController& controller = shell()->web_contents()->GetController();
@@ -833,7 +973,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
capturer.Wait();
// TODO(avi,creis): Why is this (and quite a few others below) a "link"
// transition? Lots of these transitions should be cleaned up.
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_LINK));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -842,9 +983,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Load via a fragment link click.
FrameNavigateParamsCapturer capturer(root);
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_LINK));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
@@ -853,9 +995,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Load via link click.
FrameNavigateParamsCapturer capturer(root);
std::string script = "document.getElementById('thelink').click()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_LINK));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -866,10 +1009,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
GURL frame_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_2.html"));
std::string script = "location.assign('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -879,10 +1024,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
std::string script =
"history.pushState({}, 'page 1', 'simple_page_1.html')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
@@ -893,10 +1040,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
GURL frame_url(embedded_test_server()->GetURL(
"foo.com", "/navigation_controller/simple_page_1.html"));
std::string script = "location.replace('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -922,10 +1071,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
shell()->web_contents()->GetController().GoBack();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED
- | ui::PAGE_TRANSITION_FORWARD_BACK
- | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_FORWARD_BACK |
+ ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -935,10 +1085,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
shell()->web_contents()->GetController().GoForward();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED
- | ui::PAGE_TRANSITION_FORWARD_BACK
- | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_FORWARD_BACK |
+ ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -946,12 +1097,13 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Back from the renderer side.
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "history.back()"));
+ EXPECT_TRUE(ExecuteScript(root, "history.back()"));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED
- | ui::PAGE_TRANSITION_FORWARD_BACK
- | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_FORWARD_BACK |
+ ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -959,12 +1111,13 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Forward from the renderer side.
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "history.forward()"));
+ EXPECT_TRUE(ExecuteScript(root, "history.forward()"));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED
- | ui::PAGE_TRANSITION_FORWARD_BACK
- | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_FORWARD_BACK |
+ ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -972,12 +1125,13 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Back from the renderer side via history.go().
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "history.go(-1)"));
+ EXPECT_TRUE(ExecuteScript(root, "history.go(-1)"));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED
- | ui::PAGE_TRANSITION_FORWARD_BACK
- | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_FORWARD_BACK |
+ ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -985,12 +1139,13 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Forward from the renderer side via history.go().
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "history.go(1)"));
+ EXPECT_TRUE(ExecuteScript(root, "history.go(1)"));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED
- | ui::PAGE_TRANSITION_FORWARD_BACK
- | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_FORWARD_BACK |
+ ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -1000,7 +1155,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
shell()->web_contents()->GetController().Reload(false);
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_RELOAD, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_RELOAD));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -1008,10 +1164,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// Reload from the renderer side.
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "location.reload()"));
+ EXPECT_TRUE(ExecuteScript(root, "location.reload()"));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -1024,10 +1182,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
GURL frame_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
std::string script = "location.replace('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -1039,10 +1199,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
std::string script =
"history.replaceState({}, 'page 2', 'simple_page_2.html')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
@@ -1053,7 +1215,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"/navigation_controller/page_with_links.html"));
NavigateToURL(shell(), url_links);
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
{
@@ -1061,10 +1223,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
shell()->web_contents()->GetController().GoBack();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED
- | ui::PAGE_TRANSITION_FORWARD_BACK
- | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_FORWARD_BACK |
+ ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
@@ -1074,8 +1237,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
shell()->web_contents()->GetController().GoForward();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FORWARD_BACK,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_FORWARD_BACK)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
@@ -1084,7 +1249,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
NavigateToURL(shell(), url1);
script = "history.pushState({}, 'page 2', 'simple_page_2.html')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
{
@@ -1092,10 +1257,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
shell()->web_contents()->GetController().GoBack();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED
- | ui::PAGE_TRANSITION_FORWARD_BACK
- | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+ ui::PAGE_TRANSITION_FORWARD_BACK |
+ ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
@@ -1105,8 +1271,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
shell()->web_contents()->GetController().GoForward();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FORWARD_BACK,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_FORWARD_BACK)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
@@ -1131,7 +1299,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"/navigation_controller/simple_page_1.html"));
NavigateFrameToURL(root, frame_url);
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_LINK));
EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, capturer.details().type);
}
}
@@ -1154,7 +1323,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
NavigateFrameToURL(root, GURL());
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_LINK));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
}
}
@@ -1182,7 +1352,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"/navigation_controller/simple_page_1.html"));
NavigateFrameToURL(root->child_at(0), frame_url);
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
{
@@ -1192,8 +1363,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"/navigation_controller/simple_page_2.html"));
NavigateFrameToURL(root->child_at(0), frame_url);
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
}
@@ -1202,7 +1373,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
shell()->web_contents()->GetController().GoBack();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
}
@@ -1211,7 +1383,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
shell()->web_contents()->GetController().GoForward();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
}
@@ -1222,8 +1395,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"/navigation_controller/page_with_links.html"));
NavigateFrameToURL(root->child_at(0), frame_url);
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
}
@@ -1231,10 +1404,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Load via a fragment link click.
FrameNavigateParamsCapturer capturer(root->child_at(0));
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
}
@@ -1244,10 +1417,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
GURL frame_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
std::string script = "location.assign('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
}
@@ -1257,9 +1430,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
GURL frame_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_2.html"));
std::string script = "location.replace('" + frame_url.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
{
@@ -1267,10 +1441,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
std::string script =
"history.pushState({}, 'page 1', 'simple_page_1.html')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
}
@@ -1279,18 +1453,19 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(root->child_at(0));
std::string script =
"history.replaceState({}, 'page 2', 'simple_page_2.html')";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
{
// Reload.
LoadCommittedCapturer capturer(root->child_at(0));
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
- "location.reload()"));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), "location.reload()"));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
{
@@ -1301,9 +1476,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
}
@@ -1331,10 +1507,13 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::vector<LoadCommittedDetails> details = capturer.all_details();
ASSERT_EQ(2U, params.size());
ASSERT_EQ(2U, details.size());
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, params[0].transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ params[0].transition, ui::PAGE_TRANSITION_LINK));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, details[0].type);
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT,
- params[1].transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ params[1].transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, details[1].type);
}
}
@@ -1357,9 +1536,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a fragment link click.
FrameNavigateParamsCapturer capturer(root);
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_LINK));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
@@ -1368,9 +1548,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a non-fragment link click.
FrameNavigateParamsCapturer capturer(root);
std::string script = "document.getElementById('thelink').click()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_LINK));
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -1394,10 +1575,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a fragment link click.
FrameNavigateParamsCapturer capturer(root->child_at(0));
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
@@ -1406,10 +1587,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Do a non-fragment link click.
FrameNavigateParamsCapturer capturer(root->child_at(0));
std::string script = "document.getElementById('thelink').click()";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -1435,9 +1616,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(shell()->web_contents());
std::string script = "var iframe = document.createElement('iframe');"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// Check last committed NavigationEntry.
@@ -1467,9 +1649,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(shell()->web_contents());
std::string script = "var iframe = document.createElement('iframe');"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// Verify subframe entries if they're enabled (e.g. in --site-per-process).
@@ -1492,9 +1675,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = 'about:blank';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// Check last committed NavigationEntry.
@@ -1522,9 +1706,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(root->child_at(0)->child_at(0));
std::string script = "var frames = document.getElementsByTagName('iframe');"
"frames[0].src = '" + frame_url.spec() + "';";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// Check last committed NavigationEntry. It should have replaced the previous
@@ -1554,9 +1739,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(root->child_at(1));
std::string script = "var frames = document.getElementsByTagName('iframe');"
"frames[1].src = '" + foo_url.spec() + "';";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// Check last committed NavigationEntry.
@@ -1585,9 +1771,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(root->child_at(0)->child_at(0));
std::string script = "var frames = document.getElementsByTagName('iframe');"
"frames[0].src = 'about:blank';";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
}
// This should have created a new NavigationEntry.
@@ -1643,7 +1830,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + slow_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
}
subframe_delayer.WaitForWillStartRequest();
@@ -1658,7 +1845,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
WaitForLoadStopWithoutSuccessCheck(shell()->web_contents());
}
@@ -1686,7 +1873,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + no_commit_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
}
EXPECT_EQ(GURL(), root->child_at(0)->current_url());
@@ -1698,9 +1885,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// TODO(creis): Check subframe entries once we create them in this case.
@@ -1724,7 +1912,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
FrameNavigateParamsCapturer capturer(root);
std::string script = "history.pushState({}, 'foo', 'foo')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
@@ -1738,9 +1926,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + child_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// 3. Go back in-page.
@@ -1758,9 +1947,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + grandchild_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// TODO(creis): Check subframe entries once we create them in this case.
@@ -1788,14 +1978,14 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + child_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// 2. Change the iframe's name.
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
- "window.name = 'foo';"));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), "window.name = 'foo';"));
// 3. A nested iframe with a cross-site URL should be able to commit.
GURL bar_url(embedded_test_server()->GetURL(
@@ -1805,10 +1995,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + bar_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// TODO(creis): Check subframe entries once we create them in this case.
@@ -1839,9 +2030,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// Check last committed NavigationEntry.
@@ -1873,9 +2065,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// The last committed NavigationEntry shouldn't have changed.
@@ -1905,9 +2098,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(1)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(1), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// The last committed NavigationEntry shouldn't have changed.
@@ -1937,9 +2131,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// The last committed NavigationEntry shouldn't have changed.
@@ -1968,9 +2163,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
FrameTreeNode* child = root->child_at(2);
- EXPECT_TRUE(ExecuteScript(child->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(child, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// The last committed NavigationEntry shouldn't have changed.
@@ -2030,7 +2226,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
}
NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
@@ -2042,8 +2238,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
NavigateFrameToURL(root->child_at(0), frame_url2);
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
}
@@ -2074,7 +2270,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
}
@@ -2085,7 +2281,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + foo_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(1)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(1), script));
capturer.Wait();
}
GURL bar_url(embedded_test_server()->GetURL(
@@ -2094,8 +2290,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(1)->child_at(0));
NavigateFrameToURL(root->child_at(1)->child_at(0), bar_url);
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
}
@@ -2130,10 +2326,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(1));
std::string script = "var frames = document.getElementsByTagName('iframe');"
"frames[1].src = '" + baz_url.spec() + "';";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
}
@@ -2194,12 +2390,13 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
LoadCommittedCapturer capturer(root->child_at(0));
NavigateFrameToURL(root->child_at(0), subframe_url);
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// 2. In-page navigation in the main frame.
std::string push_script = "history.pushState({}, 'page 2', 'page_2.html')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), push_script));
+ EXPECT_TRUE(ExecuteScript(root, push_script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
// TODO(creis): Verify subframe entries. https://crbug.com/522193.
@@ -2210,9 +2407,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + subframe_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// TODO(creis): Verify subframe entries. https://crbug.com/522193.
@@ -2240,7 +2438,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + frame_url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
}
NavigationEntryImpl* entry1 = controller.GetLastCommittedEntry();
@@ -2274,7 +2472,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
shell()->web_contents()->GetController().GoBack();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
}
EXPECT_EQ(3, controller.GetEntryCount());
@@ -2296,7 +2495,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
shell()->web_contents()->GetController().GoBack();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
}
EXPECT_EQ(3, controller.GetEntryCount());
@@ -2318,7 +2518,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
shell()->web_contents()->GetController().GoForward();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
}
EXPECT_EQ(3, controller.GetEntryCount());
@@ -2340,7 +2541,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root->child_at(0));
shell()->web_contents()->GetController().GoForward();
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
}
EXPECT_EQ(3, controller.GetEntryCount());
@@ -2513,7 +2715,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
}
// Inject a JS value so that we can check for it later.
- EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), "foo=3;"));
+ EXPECT_TRUE(content::ExecuteScript(root, "foo=3;"));
// 7. Go back again, to the data URL in the nested iframe.
{
@@ -2549,9 +2751,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify that we did not reload the main frame. See https://crbug.com/586234.
{
int value = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(root->current_frame_host(),
- "domAutomationController.send(foo)",
- &value));
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(
+ root, "domAutomationController.send(foo)", &value));
EXPECT_EQ(3, value);
}
@@ -2886,9 +3087,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// The root FrameNavigationEntry hasn't changed.
@@ -2911,9 +3113,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"iframe.src = '" + url.spec() + "';"
"iframe.name = 'foo';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// The new subframe should have the specified name.
@@ -2960,7 +3163,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, CloneNamedWindow) {
EXPECT_TRUE(NavigateToURL(shell(), url_1));
// Name the window.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "window.name = 'foo';"));
+ EXPECT_TRUE(ExecuteScript(shell(), "window.name = 'foo';"));
// Navigate it.
GURL url_2(embedded_test_server()->GetURL(
@@ -2991,7 +3194,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url_1));
// Name the window.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "window.name = 'foo';"));
+ EXPECT_TRUE(ExecuteScript(shell(), "window.name = 'foo';"));
// Navigate it.
GURL url_2(embedded_test_server()->GetURL(
@@ -2999,7 +3202,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url_2));
// Clear the name.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "window.name = '';"));
+ EXPECT_TRUE(ExecuteScript(shell(), "window.name = '';"));
// Navigate it again.
EXPECT_TRUE(NavigateToURL(shell(), url_1));
@@ -3055,9 +3258,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"document.body.appendChild(iframe);";
{
LoadCommittedCapturer capturer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
FrameTreeNode* subframe = root->child_at(0);
@@ -3076,7 +3280,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
controller.Reload(false);
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_RELOAD, capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition, ui::PAGE_TRANSITION_RELOAD));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
EXPECT_FALSE(capturer.details().is_in_page);
}
@@ -3084,9 +3289,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// 4. Add the iframe again.
{
LoadCommittedCapturer capturer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
if (AreAllSitesIsolatedForTesting()) {
EXPECT_NE(main_site_instance,
@@ -3119,7 +3325,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// 2. Do an in-page fragment navigation.
std::string script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
frame_entry = controller.GetLastCommittedEntry()->GetFrameEntry(root);
@@ -3139,9 +3345,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
std::string add_script = "var iframe = document.createElement('iframe');"
"iframe.src = '" + url.spec() + "';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), add_script));
+ EXPECT_TRUE(ExecuteScript(root, add_script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.transition_type(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
}
// The root FrameNavigationEntry hasn't changed.
@@ -3159,7 +3366,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_NE(dsn_2, dsn_3);
// 4. Do an in-page fragment navigation in the subframe.
- EXPECT_TRUE(ExecuteScript(subframe->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(subframe, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
subframe_entry = controller.GetLastCommittedEntry()->GetFrameEntry(subframe);
@@ -3306,7 +3513,7 @@ void DoReplaceStateWhilePending(Shell* shell,
capturer.set_wait_for_load(false);
std::string script =
"history.replaceState({}, '', '" + replace_state_filename + "')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
// The fact that there was a pending entry shouldn't interfere with the
@@ -3395,7 +3602,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
capturer.set_wait_for_load(false);
std::string script = "history.pushState({}, '', 'pushed')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
@@ -3432,25 +3639,21 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Go to the second page.
std::string script = "document.getElementById('thelink').click()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
// Go back to the first page, which never completes. The attempt to unload the
// second page, though, causes it to do a replaceState().
- NavigationStallDelegate stall_delegate(start_url);
- ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
- TestNavigationObserver back_load_observer(shell()->web_contents());
+ TestNavigationManager manager(shell()->web_contents(), start_url);
controller.GoBack();
- back_load_observer.Wait();
+ manager.WaitForWillStartRequest();
// The navigation that just happened was the replaceState(), which should not
// have changed the position into the navigation entry list. Make sure that
// the pending navigation didn't confuse anything.
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
-
- ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
// Ensure the renderer process does not get confused about the current entry
@@ -3505,7 +3708,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// location.replace() to cause an inert commit.
TestNavigationObserver replace_load_observer(shell()->web_contents());
std::string script = "location.replace('" + url3.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
replace_load_observer.Wait();
}
@@ -3587,7 +3790,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FrameNavigateParamsCapturer capturer(root);
std::string script =
"history.replaceState({}, 'replaced', 'replaced')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
capturer.Wait();
}
@@ -3744,10 +3947,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, ReloadOriginalRequest) {
{
std::string script = "location.replace('" + redirect_url.spec() + "');";
FrameNavigateParamsCapturer capturer(root);
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+ EXPECT_TRUE(ExecuteScript(shell(), script));
capturer.Wait();
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT,
- capturer.params().transition);
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ capturer.params().transition,
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
+ ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
}
@@ -3782,8 +3987,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, ReloadOriginalRequest) {
}
// Make sure the renderer is still alive.
- EXPECT_TRUE(
- ExecuteScript(shell()->web_contents(), "console.log('Success');"));
+ EXPECT_TRUE(ExecuteScript(shell(), "console.log('Success');"));
}
// This test shows that the initial "about:blank" URL is elided from the
@@ -3814,7 +4018,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"var iframe = document.createElement('iframe');"
"iframe.id = 'frame';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(1, controller.GetEntryCount());
@@ -3832,7 +4036,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// "about:blank" as the URL in the iframe.
script = "history.pushState({}, '', 'notarealurl.html')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
@@ -3912,7 +4116,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// TODO(creis): This actually goes to frame_url in some cases when subframe
// FrameNavigationEntries are enabled, due to a mismatch between PageState and
// the entry's URL. That should be fixed in https://crbug.com/617239.
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
+ if (!SiteIsolationPolicy::UseSubframeNavigationEntries())
EXPECT_EQ(blank_url, frame->current_url());
}
@@ -3944,7 +4148,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"iframe.src = '" + frame_url_1.spec() + "';"
"iframe.id = 'frame';"
"document.body.appendChild(iframe);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(1, controller.GetEntryCount());
@@ -3961,7 +4165,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// old navigation entry has frame_url_1 as the URL in the iframe.
script = "document.getElementById('fraglink').click()";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(2, controller.GetEntryCount());
@@ -4042,15 +4246,19 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// TODO(creis): This actually goes to frame_url_2 in some cases when subframe
// FrameNavigationEntries are enabled, due to a mismatch between PageState and
// the entry's URL. That should be fixed in https://crbug.com/617239.
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
+ if (!SiteIsolationPolicy::UseSubframeNavigationEntries())
EXPECT_EQ(frame_url_1, frame->current_url());
}
// Test for in-page navigation kills due to using the wrong history item in
// HistoryController::RecursiveGoToEntry and NavigationControllerImpl::
// FindFramesToNavigate. See https://crbug.com/612713.
+//
+// TODO(creis): Enable this test when https://crbug.com/618100 is fixed.
+// Disabled for now while we switch to the new navigation path, since this kill
+// is exceptionally rare in practice.
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
- BackTwiceToIframeWithContent) {
+ DISABLED_BackTwiceToIframeWithContent) {
GURL links_url(embedded_test_server()->GetURL(
"/navigation_controller/page_with_links.html"));
NavigateToURL(shell(), links_url);
@@ -4165,7 +4373,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// TODO(creis): This actually goes to frame_url_2 in some cases when subframe
// FrameNavigationEntries are enabled, due to a mismatch between PageState and
// the entry's URL. That should be fixed in https://crbug.com/617239.
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
+ if (!SiteIsolationPolicy::UseSubframeNavigationEntries())
EXPECT_EQ(frame_url_1, frame->current_url());
}
@@ -4392,6 +4600,179 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
GURL(exploded_state.top.children.at(0).url_string.string()));
}
+// Ensure that we do not corrupt a NavigationEntry's PageState if two forward
+// navigations compete in different frames. See https://crbug.com/623319.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ PageStateAfterForwardInCompetingFrames) {
+ // Navigate to a page with an iframe.
+ GURL url_a(embedded_test_server()->GetURL(
+ "/navigation_controller/page_with_data_iframe.html"));
+ GURL frame_url_a1("data:text/html,Subframe");
+ EXPECT_TRUE(NavigateToURL(shell(), url_a));
+
+ NavigationController& controller = shell()->web_contents()->GetController();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_EQ(url_a, root->current_url());
+ EXPECT_EQ(frame_url_a1, root->child_at(0)->current_url());
+
+ // Navigate the iframe to a second page.
+ GURL frame_url_a2 = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html");
+ NavigateFrameToURL(root->child_at(0), frame_url_a2);
+
+ // Navigate the iframe to about:blank.
+ GURL blank_url(url::kAboutBlankURL);
+ NavigateFrameToURL(root->child_at(0), blank_url);
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_a, root->current_url());
+ EXPECT_EQ(blank_url, root->child_at(0)->current_url());
+
+ // Go back to the middle entry.
+ controller.GoBack();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+
+ // Replace the entry with a cross-site top-level page. By doing a
+ // replacement, the main frame pages before and after have the same item
+ // sequence number, and thus going between them only requires loads in the
+ // subframe.
+ GURL url_b(embedded_test_server()->GetURL(
+ "b.com", "/navigation_controller/simple_page_2.html"));
+ std::string replace_script = "location.replace('" + url_b.spec() + "')";
+ TestNavigationObserver replace_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), replace_script));
+ replace_observer.Wait();
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_b, root->current_url());
+
+ // Go back to the original page.
+ controller.GoBack();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ // Navigate forward twice using script. In https://crbug.com/623319, this
+ // caused a mismatch between the NavigationEntry's URL and PageState.
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "history.forward(); history.forward();"));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_b, root->current_url());
+ NavigationEntry* entry = controller.GetLastCommittedEntry();
+ EXPECT_EQ(url_b, entry->GetURL());
+ ExplodedPageState exploded_state;
+ EXPECT_TRUE(
+ DecodePageState(entry->GetPageState().ToEncodedData(), &exploded_state));
+ EXPECT_EQ(url_b, GURL(exploded_state.top.url_string.string()));
+ // TODO(creis): Clear subframe FNEs after location.replace in
+ // --isolate-extensions mode. See https://crbug.com/596707.
+ if (!SiteIsolationPolicy::UseSubframeNavigationEntries())
+ EXPECT_EQ(0U, exploded_state.top.children.size());
+
+ // Go back and then forward to see if the PageState loads correctly.
+ controller.GoBack();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ controller.GoForward();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ // We should be on url_b, and the renderer process shouldn't be killed.
+ ASSERT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_b, shell()->web_contents()->GetVisibleURL());
+ EXPECT_EQ(url_b, root->current_url());
+ EXPECT_EQ(0U, root->child_count());
+}
+
+// Ensure that we do not corrupt a NavigationEntry's PageState if two forward
+// navigations compete in different frames, and the main frame entry contains an
+// iframe of its own. See https://crbug.com/623319.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ PageStateWithIframeAfterForwardInCompetingFrames) {
+ // Navigate to a page with an iframe.
+ GURL url_a(embedded_test_server()->GetURL(
+ "/navigation_controller/page_with_data_iframe.html"));
+ GURL data_url("data:text/html,Subframe");
+ EXPECT_TRUE(NavigateToURL(shell(), url_a));
+
+ NavigationController& controller = shell()->web_contents()->GetController();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_EQ(url_a, root->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->current_url());
+
+ // Navigate the iframe to a first real page.
+ GURL frame_url_a1 = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html");
+ NavigateFrameToURL(root->child_at(0), frame_url_a1);
+
+ // Navigate the iframe to a second real page.
+ GURL frame_url_a2 = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_2.html");
+ NavigateFrameToURL(root->child_at(0), frame_url_a2);
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_a, root->current_url());
+ EXPECT_EQ(frame_url_a2, root->child_at(0)->current_url());
+
+ // Go back to the middle entry.
+ controller.GoBack();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+
+ // Replace the entry with a cross-site top-level page with an iframe. By
+ // doing a replacement, the main frame pages before and after have the same
+ // item sequence number, and thus going between them only requires loads in
+ // the subframe.
+ GURL url_b(embedded_test_server()->GetURL(
+ "b.com", "/navigation_controller/page_with_data_iframe.html"));
+ std::string replace_script = "location.replace('" + url_b.spec() + "')";
+ TestNavigationObserver replace_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), replace_script));
+ replace_observer.Wait();
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_b, root->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->current_url());
+
+ // Go back to the original page.
+ controller.GoBack();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ // Navigate forward twice using script. This will race, but in either outcome
+ // we want to ensure that the subframes target entry index 1 and not 2. In
+ // https://crbug.com/623319, the subframes targeted the wrong entry, leading
+ // to a URL spoof and renderer kill.
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "history.forward(); history.forward();"));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_EQ(url_b, root->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->current_url());
+ NavigationEntry* entry = controller.GetLastCommittedEntry();
+ EXPECT_EQ(url_b, entry->GetURL());
+ ExplodedPageState exploded_state;
+ EXPECT_TRUE(
+ DecodePageState(entry->GetPageState().ToEncodedData(), &exploded_state));
+ EXPECT_EQ(url_b, GURL(exploded_state.top.url_string.string()));
+
+ // Go back and then forward to see if the PageState loads correctly.
+ controller.GoBack();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ controller.GoForward();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ // We should be on url_b, and the renderer process shouldn't be killed.
+ ASSERT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_b, shell()->web_contents()->GetVisibleURL());
+ EXPECT_EQ(url_b, root->current_url());
+ EXPECT_EQ(data_url, root->child_at(0)->current_url());
+}
+
// Ensure that forward navigations in cloned tabs can commit if they redirect to
// a different site than before. This causes the navigation's item sequence
// number to change, meaning that we can't use it for determining whether the
@@ -4424,7 +4805,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
TestNavigationObserver observer(shell()->web_contents());
std::string script =
"history.replaceState({}, '', '/server-redirect?" + url_3.spec() + "')";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
observer.Wait();
}
@@ -4488,8 +4869,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Submit the form.
TestNavigationObserver observer(shell()->web_contents(), 1);
EXPECT_TRUE(ExecuteScript(
- shell()->web_contents(),
- "window.domAutomationController.send(submitForm('isubmit'))"));
+ shell(), "window.domAutomationController.send(submitForm('isubmit'))"));
observer.Wait();
EXPECT_EQ(2, controller.GetEntryCount());
@@ -4511,4 +4891,41 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
}
}
+// Tests that POST body is not lost when decidePolicyForNavigation tells the
+// renderer to route the request via FrameHostMsg_OpenURL sent to the browser.
+// See also https://crbug.com/344348.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, PostViaOpenUrlMsg) {
+ GURL main_url(
+ embedded_test_server()->GetURL("/form_that_posts_to_echoall.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Ask the renderer to go through OpenURL FrameHostMsg_OpenURL IPC message.
+ // Without this, the test wouldn't repro https://crbug.com/344348.
+ shell()
+ ->web_contents()
+ ->GetMutableRendererPrefs()
+ ->browser_handles_all_top_level_requests = true;
+ shell()->web_contents()->GetRenderViewHost()->SyncRendererPrefs();
+
+ // Submit the form.
+ TestNavigationObserver form_post_observer(shell()->web_contents(), 1);
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "document.getElementById('form').submit();"));
+ form_post_observer.Wait();
+
+ // Verify that we arrived at the expected location.
+ GURL target_url(embedded_test_server()->GetURL("/echoall"));
+ EXPECT_EQ(target_url, shell()->web_contents()->GetLastCommittedURL());
+
+ // Verify that POST body was correctly passed to the server and ended up in
+ // the body of the page.
+ std::string body;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell()->web_contents(),
+ "window.domAutomationController.send("
+ "document.getElementsByTagName('pre')[0].innerText);",
+ &body));
+ EXPECT_EQ("text=value\n", body);
+}
+
} // 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 92e18746d78..a2c74bd9624 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <memory>
+#include <tuple>
#include <utility>
#include "base/bind.h"
@@ -41,6 +42,7 @@
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/page_state.h"
#include "content/public/common/page_type.h"
+#include "content/public/common/resource_request_body.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_notification_tracker.h"
@@ -247,10 +249,11 @@ class NavigationControllerTest
const IPC::Message* message =
process()->sink().GetFirstMessageMatching(FrameMsg_Navigate::ID);
CHECK(message);
- base::Tuple<CommonNavigationParams, StartNavigationParams,
- RequestNavigationParams> nav_params;
+ std::tuple<CommonNavigationParams, StartNavigationParams,
+ RequestNavigationParams>
+ nav_params;
FrameMsg_Navigate::Read(message, &nav_params);
- return base::get<0>(nav_params).url;
+ return std::get<0>(nav_params).url;
}
protected:
@@ -665,7 +668,8 @@ void CheckNavigationEntryMatchLoadParams(
EXPECT_EQ(load_params.url, entry->GetURL());
EXPECT_EQ(load_params.referrer.url, entry->GetReferrer().url);
EXPECT_EQ(load_params.referrer.policy, entry->GetReferrer().policy);
- EXPECT_EQ(load_params.transition_type, entry->GetTransitionType());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ entry->GetTransitionType(), load_params.transition_type));
EXPECT_EQ(load_params.extra_headers, entry->extra_headers());
EXPECT_EQ(load_params.is_renderer_initiated, entry->is_renderer_initiated());
@@ -682,8 +686,7 @@ void CheckNavigationEntryMatchLoadParams(
load_params.override_user_agent);
EXPECT_EQ(should_override, entry->GetIsOverridingUserAgent());
}
- EXPECT_EQ(load_params.browser_initiated_post_data.get(),
- entry->GetBrowserInitiatedPostData());
+ EXPECT_EQ(load_params.post_data, entry->GetPostData());
EXPECT_EQ(load_params.transferred_global_request_id,
entry->transferred_global_request_id());
}
@@ -755,18 +758,13 @@ TEST_F(NavigationControllerTest, LoadURLWithExtraParams_HttpPost) {
NavigationController::LoadURLParams load_params(GURL("https://posturl"));
load_params.transition_type = ui::PAGE_TRANSITION_TYPED;
- load_params.load_type =
- NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST;
+ load_params.load_type = NavigationController::LOAD_TYPE_HTTP_POST;
load_params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
-
- const unsigned char* raw_data =
- reinterpret_cast<const unsigned char*>("d\n\0a2");
+ const char* raw_data = "d\n\0a2";
const int length = 5;
- std::vector<unsigned char> post_data_vector(raw_data, raw_data+length);
- scoped_refptr<base::RefCountedBytes> data =
- base::RefCountedBytes::TakeVector(&post_data_vector);
- load_params.browser_initiated_post_data = data.get();
+ load_params.post_data =
+ ResourceRequestBody::CreateFromBytes(raw_data, length);
controller.LoadURLWithParams(load_params);
NavigationEntryImpl* entry = controller.GetPendingEntry();
@@ -1576,22 +1574,19 @@ TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
entry_id = controller.GetPendingEntry()->GetUniqueID();
// Set up some sample values.
- const unsigned char* raw_data =
- reinterpret_cast<const unsigned char*>("post\n\n\0data");
+ const char* raw_data = "post\n\n\0data";
const int length = 11;
- std::vector<unsigned char> post_data_vector(raw_data, raw_data+length);
- scoped_refptr<base::RefCountedBytes> post_data =
- base::RefCountedBytes::TakeVector(&post_data_vector);
GlobalRequestID transfer_id(3, 4);
// Set non-persisted values on the pending entry.
NavigationEntryImpl* pending_entry = controller.GetPendingEntry();
- pending_entry->SetBrowserInitiatedPostData(post_data.get());
+ pending_entry->SetPostData(
+ ResourceRequestBody::CreateFromBytes(raw_data, length));
pending_entry->set_is_renderer_initiated(true);
pending_entry->set_transferred_global_request_id(transfer_id);
pending_entry->set_should_replace_entry(true);
pending_entry->set_should_clear_history_list(true);
- EXPECT_EQ(post_data.get(), pending_entry->GetBrowserInitiatedPostData());
+ EXPECT_TRUE(pending_entry->GetPostData());
EXPECT_TRUE(pending_entry->is_renderer_initiated());
EXPECT_EQ(transfer_id, pending_entry->transferred_global_request_id());
EXPECT_TRUE(pending_entry->should_replace_entry());
@@ -1604,7 +1599,7 @@ TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
// Certain values that are only used for pending entries get reset after
// commit.
NavigationEntryImpl* committed_entry = controller.GetLastCommittedEntry();
- EXPECT_FALSE(committed_entry->GetBrowserInitiatedPostData());
+ EXPECT_FALSE(committed_entry->GetPostData());
EXPECT_FALSE(committed_entry->is_renderer_initiated());
EXPECT_EQ(GlobalRequestID(-1, -1),
committed_entry->transferred_global_request_id());
@@ -4008,21 +4003,24 @@ TEST_F(NavigationControllerTest, LazyReload) {
const GURL url("http://foo");
NavigateAndCommit(url);
ASSERT_FALSE(controller.NeedsReload());
- EXPECT_NE(ui::PAGE_TRANSITION_RELOAD,
- controller.GetLastCommittedEntry()->GetTransitionType());
+ EXPECT_FALSE(ui::PageTransitionTypeIncludingQualifiersIs(
+ controller.GetLastCommittedEntry()->GetTransitionType(),
+ ui::PAGE_TRANSITION_RELOAD));
// Request a reload to happen when the controller becomes active (e.g. after
// the renderer gets killed in background on Android).
controller.SetNeedsReload();
ASSERT_TRUE(controller.NeedsReload());
- EXPECT_EQ(ui::PAGE_TRANSITION_RELOAD,
- controller.GetLastCommittedEntry()->GetTransitionType());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ controller.GetLastCommittedEntry()->GetTransitionType(),
+ ui::PAGE_TRANSITION_RELOAD));
// Set the controller as active, triggering the requested reload.
controller.SetActive(true);
ASSERT_FALSE(controller.NeedsReload());
- EXPECT_EQ(ui::PAGE_TRANSITION_RELOAD,
- controller.GetPendingEntry()->GetTransitionType());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ controller.GetPendingEntry()->GetTransitionType(),
+ ui::PAGE_TRANSITION_RELOAD));
}
// Test requesting and triggering a lazy reload without any committed entry nor
@@ -4046,21 +4044,24 @@ TEST_F(NavigationControllerTest, LazyReloadWithOnlyPendingEntry) {
const GURL url("http://foo");
controller.LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
ASSERT_FALSE(controller.NeedsReload());
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED,
- controller.GetPendingEntry()->GetTransitionType());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ controller.GetPendingEntry()->GetTransitionType(),
+ ui::PAGE_TRANSITION_TYPED));
// Request a reload to happen when the controller becomes active (e.g. after
// the renderer gets killed in background on Android).
controller.SetNeedsReload();
ASSERT_TRUE(controller.NeedsReload());
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED,
- controller.GetPendingEntry()->GetTransitionType());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ controller.GetPendingEntry()->GetTransitionType(),
+ ui::PAGE_TRANSITION_TYPED));
// Set the controller as active, triggering the requested reload.
controller.SetActive(true);
ASSERT_FALSE(controller.NeedsReload());
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED,
- controller.GetPendingEntry()->GetTransitionType());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ controller.GetPendingEntry()->GetTransitionType(),
+ ui::PAGE_TRANSITION_TYPED));
}
// Tests a subframe navigation while a toplevel navigation is pending.
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index 092281a6e51..d6e07afff55 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -18,7 +18,9 @@
#include "content/common/content_constants_internal.h"
#include "content/common/navigation_params.h"
#include "content/common/page_state_serialization.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/common/site_isolation_policy.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/url_constants.h"
#include "ui/gfx/text_elider.h"
@@ -417,14 +419,13 @@ int64_t NavigationEntryImpl::GetPostID() const {
return frame_tree_->frame_entry->post_id();
}
-void NavigationEntryImpl::SetBrowserInitiatedPostData(
- const base::RefCountedMemory* data) {
- browser_initiated_post_data_ = data;
+void NavigationEntryImpl::SetPostData(
+ const scoped_refptr<ResourceRequestBody>& data) {
+ post_data_ = static_cast<ResourceRequestBodyImpl*>(data.get());
}
-const base::RefCountedMemory*
-NavigationEntryImpl::GetBrowserInitiatedPostData() const {
- return browser_initiated_post_data_.get();
+scoped_refptr<ResourceRequestBody> NavigationEntryImpl::GetPostData() const {
+ return post_data_.get();
}
@@ -548,7 +549,7 @@ std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::CloneAndReplace(
copy->is_overriding_user_agent_ = is_overriding_user_agent_;
copy->timestamp_ = timestamp_;
copy->http_status_code_ = http_status_code_;
- // ResetForCommit: browser_initiated_post_data_
+ // ResetForCommit: post_data_
copy->screenshot_ = screenshot_;
copy->extra_headers_ = extra_headers_;
copy->base_url_for_data_url_ = base_url_for_data_url_;
@@ -569,6 +570,8 @@ std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::CloneAndReplace(
}
CommonNavigationParams NavigationEntryImpl::ConstructCommonNavigationParams(
+ const FrameNavigationEntry& frame_entry,
+ const scoped_refptr<ResourceRequestBodyImpl>& post_body,
const GURL& dest_url,
const Referrer& dest_referrer,
FrameMsg_Navigate_Type::Value navigation_type,
@@ -583,24 +586,25 @@ CommonNavigationParams NavigationEntryImpl::ConstructCommonNavigationParams(
ui_timestamp = intent_received_timestamp();
#endif
+ std::string method;
+
+ // TODO(clamy): Consult the FrameNavigationEntry in all modes that use
+ // subframe navigation entries.
+ if (IsBrowserSideNavigationEnabled())
+ method = frame_entry.method();
+ else
+ method = (post_body.get() || GetHasPostData()) ? "POST" : "GET";
+
return CommonNavigationParams(
dest_url, dest_referrer, GetTransitionType(), navigation_type,
!IsViewSourceMode(), should_replace_entry(), ui_timestamp, report_type,
GetBaseURLForDataURL(), GetHistoryURLForDataURL(), lofi_state,
- navigation_start, GetHasPostData() ? "POST" : "GET");
+ navigation_start, method, post_body ? post_body : post_data_);
}
StartNavigationParams NavigationEntryImpl::ConstructStartNavigationParams()
const {
- std::vector<unsigned char> browser_initiated_post_data;
- if (GetBrowserInitiatedPostData()) {
- browser_initiated_post_data.assign(
- GetBrowserInitiatedPostData()->front(),
- GetBrowserInitiatedPostData()->front() +
- GetBrowserInitiatedPostData()->size());
- }
-
- return StartNavigationParams(extra_headers(), browser_initiated_post_data,
+ return StartNavigationParams(extra_headers(),
#if defined(OS_ANDROID)
has_user_gesture(),
#endif
@@ -664,7 +668,7 @@ void NavigationEntryImpl::ResetForCommit(FrameNavigationEntry* frame_entry) {
// cleared here.
// TODO(creis): This state should be moved to NavigationRequest once
// PlzNavigate is enabled.
- SetBrowserInitiatedPostData(nullptr);
+ SetPostData(nullptr);
set_is_renderer_initiated(false);
set_transferred_global_request_id(GlobalRequestID());
set_should_replace_entry(false);
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index 8b5066e3e5d..8209b980c7d 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -16,6 +16,7 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/frame_message_enums.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/navigation_entry.h"
@@ -23,6 +24,7 @@
#include "content/public/common/ssl_status.h"
namespace content {
+class ResourceRequestBodyImpl;
struct CommonNavigationParams;
struct RequestNavigationParams;
struct StartNavigationParams;
@@ -117,8 +119,8 @@ class CONTENT_EXPORT NavigationEntryImpl
bool GetHasPostData() const override;
void SetPostID(int64_t post_id) override;
int64_t GetPostID() const override;
- void SetBrowserInitiatedPostData(const base::RefCountedMemory* data) override;
- const base::RefCountedMemory* GetBrowserInitiatedPostData() const override;
+ void SetPostData(const scoped_refptr<ResourceRequestBody>& data) override;
+ scoped_refptr<ResourceRequestBody> GetPostData() const override;
const FaviconStatus& GetFavicon() const override;
FaviconStatus& GetFavicon() override;
const SSLStatus& GetSSL() const override;
@@ -160,6 +162,8 @@ class CONTENT_EXPORT NavigationEntryImpl
// Helper functions to construct NavigationParameters for a navigation to this
// NavigationEntry.
CommonNavigationParams ConstructCommonNavigationParams(
+ const FrameNavigationEntry& frame_entry,
+ const scoped_refptr<ResourceRequestBodyImpl>& post_body,
const GURL& dest_url,
const Referrer& dest_referrer,
FrameMsg_Navigate_Type::Value navigation_type,
@@ -407,10 +411,9 @@ class CONTENT_EXPORT NavigationEntryImpl
// This member is not persisted with session restore because it is transient.
// If the post request succeeds, this field is cleared since the same
- // information is stored in |content_state_| above. It is also only shallow
- // copied with compiler provided copy constructor.
- // Cleared in |ResetForCommit|.
- scoped_refptr<const base::RefCountedMemory> browser_initiated_post_data_;
+ // information is stored in PageState. It is also only shallow copied with
+ // compiler provided copy constructor. Cleared in |ResetForCommit|.
+ scoped_refptr<ResourceRequestBodyImpl> post_data_;
// This is also a transient member (i.e. is not persisted with session
// restore). The screenshot of a page is taken when navigating away from the
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 0b239e08ed8..f44e6e8525c 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -173,10 +173,13 @@ TEST_F(NavigationEntryTest, NavigationEntryAccessors) {
EXPECT_EQ(2, entry2_->GetPageID());
// Transition type
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, entry1_->GetTransitionType());
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED, entry2_->GetTransitionType());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ entry1_->GetTransitionType(), ui::PAGE_TRANSITION_LINK));
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ entry2_->GetTransitionType(), ui::PAGE_TRANSITION_TYPED));
entry2_->SetTransitionType(ui::PAGE_TRANSITION_RELOAD);
- EXPECT_EQ(ui::PAGE_TRANSITION_RELOAD, entry2_->GetTransitionType());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ entry2_->GetTransitionType(), ui::PAGE_TRANSITION_RELOAD));
// Is renderer initiated
EXPECT_FALSE(entry1_->is_renderer_initiated());
@@ -213,18 +216,15 @@ TEST_F(NavigationEntryTest, NavigationEntryAccessors) {
entry2_->SetIsOverridingUserAgent(true);
EXPECT_TRUE(entry2_->GetIsOverridingUserAgent());
- // Browser initiated post data
- EXPECT_EQ(NULL, entry1_->GetBrowserInitiatedPostData());
- EXPECT_EQ(NULL, entry2_->GetBrowserInitiatedPostData());
+ // Post data
+ EXPECT_FALSE(entry1_->GetPostData());
+ EXPECT_FALSE(entry2_->GetPostData());
const int length = 11;
- const unsigned char* raw_data =
- reinterpret_cast<const unsigned char*>("post\n\n\0data");
- std::vector<unsigned char> post_data_vector(raw_data, raw_data+length);
- scoped_refptr<base::RefCountedBytes> post_data =
- base::RefCountedBytes::TakeVector(&post_data_vector);
- entry2_->SetBrowserInitiatedPostData(post_data.get());
- EXPECT_EQ(post_data->front(),
- entry2_->GetBrowserInitiatedPostData()->front());
+ const char* raw_data = "post\n\n\0data";
+ scoped_refptr<ResourceRequestBody> post_data =
+ ResourceRequestBody::CreateFromBytes(raw_data, length);
+ entry2_->SetPostData(post_data);
+ EXPECT_EQ(post_data, entry2_->GetPostData());
}
// Test basic Clone behavior.
@@ -242,7 +242,8 @@ TEST_F(NavigationEntryTest, NavigationEntryClone) {
EXPECT_EQ(entry2_->GetTitle(), clone->GetTitle());
// Value set after constructor.
- EXPECT_EQ(entry2_->GetTransitionType(), clone->GetTransitionType());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ clone->GetTransitionType(), entry2_->GetTransitionType()));
// Value not copied due to ResetForCommit.
EXPECT_NE(entry2_->should_replace_entry(), clone->should_replace_entry());
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index 240eba74161..d7dcbefabbf 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -6,16 +6,19 @@
#include <utility>
+#include "base/logging.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/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/public/browser/content_browser_client.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
#include "net/url_request/redirect_info.h"
+#include "url/gurl.h"
+#include "url/url_constants.h"
namespace content {
@@ -179,9 +182,12 @@ net::Error NavigationHandleImpl::GetNetErrorCode() {
}
RenderFrameHostImpl* NavigationHandleImpl::GetRenderFrameHost() {
- CHECK(state_ >= READY_TO_COMMIT)
- << "This accessor should only be called "
- "after the navigation is ready to commit.";
+ // TODO(mkwst): Change this to check against 'READY_TO_COMMIT' once
+ // ReadyToCommitNavigation is available whether or not PlzNavigate is
+ // enabled. https://crbug.com/621856
+ CHECK_GE(state_, WILL_PROCESS_RESPONSE)
+ << "This accessor should only be called after a response has been "
+ "delivered for processing.";
return render_frame_host_;
}
@@ -250,7 +256,18 @@ NavigationHandleImpl::CallWillStartRequestForTesting(
ui::PageTransition transition,
bool is_external_protocol) {
NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::DEFER;
- WillStartRequest(is_post ? "POST" : "GET", sanitized_referrer,
+
+ scoped_refptr<ResourceRequestBodyImpl> resource_request_body;
+ std::string method = "GET";
+ if (is_post) {
+ method = "POST";
+
+ std::string body = "test=body";
+ resource_request_body = new ResourceRequestBodyImpl();
+ resource_request_body->AppendBytes(body.data(), body.size());
+ }
+
+ WillStartRequest(method, resource_request_body, sanitized_referrer,
has_user_gesture, transition, is_external_protocol,
base::Bind(&UpdateThrottleCheckResult, &result));
@@ -280,22 +297,24 @@ NavigationData* NavigationHandleImpl::GetNavigationData() {
return navigation_data_.get();
}
-void NavigationHandleImpl::InitServiceWorkerHandle(
- ServiceWorkerContextWrapper* service_worker_context) {
- DCHECK(IsBrowserSideNavigationEnabled());
- service_worker_handle_.reset(
- new ServiceWorkerNavigationHandle(service_worker_context));
-}
-
void NavigationHandleImpl::WillStartRequest(
const std::string& method,
+ scoped_refptr<content::ResourceRequestBodyImpl> resource_request_body,
const Referrer& sanitized_referrer,
bool has_user_gesture,
ui::PageTransition transition,
bool is_external_protocol,
const ThrottleChecksFinishedCallback& callback) {
+ // |method != "POST"| should imply absence of |resource_request_body|.
+ if (method != "POST" && resource_request_body) {
+ NOTREACHED();
+ resource_request_body = nullptr;
+ }
+
// Update the navigation parameters.
method_ = method;
+ if (method_ == "POST")
+ resource_request_body_ = resource_request_body;
sanitized_referrer_ = sanitized_referrer;
has_user_gesture_ = has_user_gesture;
transition_ = transition;
@@ -339,6 +358,8 @@ void NavigationHandleImpl::WillRedirectRequest(
is_external_protocol_ = new_is_external_protocol;
response_headers_ = response_headers;
was_redirected_ = true;
+ if (new_method != "POST")
+ resource_request_body_ = nullptr;
state_ = WILL_REDIRECT_REQUEST;
complete_callback_ = callback;
@@ -416,6 +437,7 @@ NavigationHandleImpl::CheckWillStartRequest() {
case NavigationThrottle::CANCEL:
case NavigationThrottle::CANCEL_AND_IGNORE:
+ case NavigationThrottle::BLOCK_REQUEST:
state_ = CANCELING;
return result;
@@ -423,9 +445,6 @@ NavigationHandleImpl::CheckWillStartRequest() {
state_ = DEFERRING_START;
next_index_ = i + 1;
return result;
-
- default:
- NOTREACHED();
}
}
next_index_ = 0;
@@ -455,7 +474,7 @@ NavigationHandleImpl::CheckWillRedirectRequest() {
next_index_ = i + 1;
return result;
- default:
+ case NavigationThrottle::BLOCK_REQUEST:
NOTREACHED();
}
}
@@ -490,6 +509,9 @@ NavigationHandleImpl::CheckWillProcessResponse() {
state_ = DEFERRING_RESPONSE;
next_index_ = i + 1;
return result;
+
+ case NavigationThrottle::BLOCK_REQUEST:
+ NOTREACHED();
}
}
next_index_ = 0;
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.h b/chromium/content/browser/frame_host/navigation_handle_impl.h
index 56a07b13626..cee19438d46 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.h
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.h
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -24,8 +25,7 @@ struct FrameHostMsg_DidCommitProvisionalLoad_Params;
namespace content {
class NavigatorDelegate;
-class ServiceWorkerContextWrapper;
-class ServiceWorkerNavigationHandle;
+class ResourceRequestBodyImpl;
struct NavigationRequestInfo;
// This class keeps track of a single navigation. It is created upon receipt of
@@ -156,11 +156,11 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
render_frame_host_ = render_frame_host;
}
- // PlzNavigate
- void InitServiceWorkerHandle(
- ServiceWorkerContextWrapper* service_worker_context);
- ServiceWorkerNavigationHandle* service_worker_handle() const {
- return service_worker_handle_.get();
+ // Returns the POST body associated with this navigation. This will be
+ // null for GET and/or other non-POST requests (or if a response to a POST
+ // request was a redirect that changed the method to GET - for example 302).
+ const scoped_refptr<ResourceRequestBodyImpl>& resource_request_body() const {
+ return resource_request_body_;
}
typedef base::Callback<void(NavigationThrottle::ThrottleCheckResult)>
@@ -169,12 +169,14 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// Called when the URLRequest will start in the network stack. |callback|
// will be called when all throttle checks have completed. This will allow
// the caller to cancel the navigation or let it proceed.
- void WillStartRequest(const std::string& method,
- const Referrer& sanitized_referrer,
- bool has_user_gesture,
- ui::PageTransition transition,
- bool is_external_protocol,
- const ThrottleChecksFinishedCallback& callback);
+ void WillStartRequest(
+ const std::string& method,
+ scoped_refptr<content::ResourceRequestBodyImpl> resource_request_body,
+ const Referrer& sanitized_referrer,
+ bool has_user_gesture,
+ ui::PageTransition transition,
+ bool is_external_protocol,
+ const ThrottleChecksFinishedCallback& callback);
// Called when the URLRequest will be redirected in the network stack.
// |callback| will be called when all throttles check have completed. This
@@ -277,6 +279,11 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// The HTTP method used for the navigation.
std::string method_;
+ // The POST body associated with this navigation. This will be null for GET
+ // and/or other non-POST requests (or if a response to a POST request was a
+ // redirect that changed the method to GET - for example 302).
+ scoped_refptr<ResourceRequestBodyImpl> resource_request_body_;
+
// The state the navigation is in.
State state_;
@@ -302,11 +309,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// This callback will be run when all throttle checks have been performed.
ThrottleChecksFinishedCallback complete_callback_;
- // PlzNavigate
- // Manages the lifetime of a pre-created ServiceWorkerProviderHost until a
- // corresponding ServiceWorkerNetworkProvider is created in the renderer.
- std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle_;
-
// Embedder data tied to this navigation.
std::unique_ptr<NavigationData> navigation_data_;
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 cd9a533a550..d9ab400ec2e 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -12,6 +12,7 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
#include "ui/base/page_transition_types.h"
#include "url/url_constants.h"
@@ -295,7 +296,8 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifyPageTransition) {
EXPECT_TRUE(observer.has_committed());
EXPECT_FALSE(observer.is_error());
EXPECT_EQ(url, observer.last_committed_url());
- EXPECT_EQ(expected_transition, observer.page_transition());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ observer.page_transition(), expected_transition));
}
{
@@ -315,7 +317,8 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifyPageTransition) {
EXPECT_FALSE(observer.is_error());
EXPECT_EQ(embedded_test_server()->GetURL("baz.com", "/title1.html"),
observer.last_committed_url());
- EXPECT_EQ(expected_transition, observer.page_transition());
+ EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+ observer.page_transition(), expected_transition));
EXPECT_FALSE(observer.is_main_frame());
}
}
@@ -450,7 +453,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
NavigationHandleObserver observer(
shell()->web_contents(),
embedded_test_server()->GetURL("a.com", "/bar"));
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
"window.history.pushState({}, '', 'bar');"));
EXPECT_TRUE(observer.has_committed());
@@ -486,7 +489,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifySynchronous) {
NavigationHandleObserver observer(
shell()->web_contents(), embedded_test_server()->GetURL("a.com", "/bar"));
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
"window.history.pushState({}, '', 'bar');"));
EXPECT_TRUE(observer.has_committed());
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 74eccc3db2f..f77bbdf0123 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -102,7 +102,7 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
// It's safe to use base::Unretained since the NavigationHandle is owned by
// the NavigationHandleImplTest.
test_handle_->WillStartRequest(
- "GET", Referrer(), false, ui::PAGE_TRANSITION_LINK, false,
+ "GET", nullptr, Referrer(), false, ui::PAGE_TRANSITION_LINK, false,
base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult,
base::Unretained(this)));
}
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index 7ec5d78638d..47c945d30d6 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -16,9 +16,8 @@
#include "content/browser/frame_host/navigator_impl.h"
#include "content/browser/loader/navigation_url_loader.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"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_data.h"
@@ -41,6 +40,7 @@ int LoadFlagFromNavigationType(FrameMsg_Navigate_Type::Value navigation_type) {
int load_flags = net::LOAD_NORMAL;
switch (navigation_type) {
case FrameMsg_Navigate_Type::RELOAD:
+ case FrameMsg_Navigate_Type::RELOAD_MAIN_RESOURCE:
case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL:
load_flags |= net::LOAD_VALIDATE_CACHE;
break;
@@ -81,20 +81,15 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
headers.SetHeaderIfMissing(net::HttpRequestHeaders::kUserAgent,
GetContentClient()->GetUserAgent());
- // Fill POST data from the browser in the request body.
- scoped_refptr<ResourceRequestBody> request_body;
- if (entry.GetHasPostData()) {
- request_body = new ResourceRequestBody();
- request_body->AppendBytes(
- reinterpret_cast<const char *>(
- entry.GetBrowserInitiatedPostData()->front()),
- entry.GetBrowserInitiatedPostData()->size());
- }
+ // Fill POST data in the request body.
+ scoped_refptr<ResourceRequestBodyImpl> request_body;
+ if (frame_entry.method() == "POST")
+ request_body = frame_entry.GetPostData();
std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
frame_tree_node, entry.ConstructCommonNavigationParams(
- dest_url, dest_referrer, navigation_type, lofi_state,
- navigation_start),
+ frame_entry, request_body, dest_url, dest_referrer,
+ navigation_type, lofi_state, navigation_start),
BeginNavigationParams(headers.ToString(),
LoadFlagFromNavigationType(navigation_type),
false, // has_user_gestures
@@ -107,7 +102,7 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
controller->GetIndexOfEntry(&entry),
controller->GetLastCommittedEntryIndex(),
controller->GetEntryCount()),
- request_body, true, &frame_entry, &entry));
+ true, &frame_entry, &entry));
return navigation_request;
}
@@ -116,7 +111,6 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params,
- scoped_refptr<ResourceRequestBody> body,
int current_history_list_offset,
int current_history_list_length) {
// TODO(clamy): Check if some PageState should be provided here.
@@ -142,7 +136,7 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
false); // should_clear_history_list
std::unique_ptr<NavigationRequest> navigation_request(
new NavigationRequest(frame_tree_node, common_params, begin_params,
- request_params, body, false, nullptr, nullptr));
+ request_params, false, nullptr, nullptr));
return navigation_request;
}
@@ -151,7 +145,6 @@ NavigationRequest::NavigationRequest(
const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params,
const RequestNavigationParams& request_params,
- scoped_refptr<ResourceRequestBody> body,
bool browser_initiated,
const FrameNavigationEntry* frame_entry,
const NavigationEntryImpl* entry)
@@ -196,7 +189,7 @@ NavigationRequest::NavigationRequest(
info_.reset(new NavigationRequestInfo(
common_params, begin_params, first_party_for_cookies,
frame_tree_node->current_origin(), frame_tree_node->IsMainFrame(),
- parent_is_main_frame, frame_tree_node->frame_tree_node_id(), body));
+ parent_is_main_frame, frame_tree_node->frame_tree_node_id()));
}
NavigationRequest::~NavigationRequest() {
@@ -215,8 +208,9 @@ void NavigationRequest::BeginNavigation() {
// TODO(clamy): pass the method to the NavigationHandle instead of a
// boolean.
navigation_handle_->WillStartRequest(
- common_params_.method, Referrer::SanitizeForRequest(
- common_params_.url, common_params_.referrer),
+ common_params_.method, common_params_.post_data,
+ Referrer::SanitizeForRequest(common_params_.url,
+ common_params_.referrer),
begin_params_.has_user_gesture, common_params_.transition, false,
base::Bind(&NavigationRequest::OnStartChecksComplete,
base::Unretained(this)));
@@ -258,6 +252,10 @@ void NavigationRequest::TransferNavigationHandleOwnership(
void NavigationRequest::OnRequestRedirected(
const net::RedirectInfo& redirect_info,
const scoped_refptr<ResourceResponse>& response) {
+ // If the navigation is no longer a POST, the POST data should be reset.
+ if (redirect_info.new_method != "POST")
+ common_params_.post_data = nullptr;
+
common_params_.url = redirect_info.new_url;
common_params_.method = redirect_info.new_method;
common_params_.referrer.url = GURL(redirect_info.new_referrer);
@@ -292,16 +290,6 @@ void NavigationRequest::OnResponseStarted(
return;
}
- // 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();
- }
-
// Update the lofi state of the request.
if (response->head.is_using_lofi)
common_params_.lofi_state = LOFI_ON;
@@ -359,6 +347,14 @@ void NavigationRequest::OnRequestStarted(base::TimeTicks timestamp) {
common_params_.url);
}
+void NavigationRequest::OnServiceWorkerEncountered() {
+ request_params_.should_create_service_worker = true;
+
+ // TODO(clamy): the navigation should be sent to a RenderFrameHost to be
+ // picked up by the ServiceWorker.
+ NOTIMPLEMENTED();
+}
+
void NavigationRequest::OnStartChecksComplete(
NavigationThrottle::ThrottleCheckResult result) {
CHECK(result != NavigationThrottle::DEFER);
@@ -371,10 +367,29 @@ void NavigationRequest::OnStartChecksComplete(
return;
}
- InitializeServiceWorkerHandleIfNeeded();
+ // 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.
+ DCHECK_NE(AssociatedSiteInstanceType::NONE, associated_site_instance_type_);
+ RenderFrameHostImpl* navigating_frame_host =
+ associated_site_instance_type_ == AssociatedSiteInstanceType::SPECULATIVE
+ ? frame_tree_node_->render_manager()->speculative_frame_host()
+ : frame_tree_node_->current_frame_host();
+ DCHECK(navigating_frame_host);
+
+ BrowserContext* browser_context =
+ frame_tree_node_->navigator()->GetController()->GetBrowserContext();
+ StoragePartition* partition = BrowserContext::GetStoragePartition(
+ browser_context, navigating_frame_host->GetSiteInstance());
+ DCHECK(partition);
+
+ ServiceWorkerContextWrapper* service_worker_context =
+ static_cast<ServiceWorkerContextWrapper*>(
+ partition->GetServiceWorkerContext());
+
loader_ = NavigationURLLoader::Create(
frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
- std::move(info_), navigation_handle_->service_worker_handle(), this);
+ std::move(info_), service_worker_context, this);
}
void NavigationRequest::OnRedirectChecksComplete(
@@ -436,34 +451,4 @@ void NavigationRequest::CommitNavigation() {
frame_tree_node_->ResetNavigationRequest(true);
}
-void NavigationRequest::InitializeServiceWorkerHandleIfNeeded() {
- // Only initialize the ServiceWorkerNavigationHandle if it can be created for
- // this frame.
- bool can_create_service_worker =
- (frame_tree_node_->pending_sandbox_flags() &
- blink::WebSandboxFlags::Origin) != blink::WebSandboxFlags::Origin;
- if (!can_create_service_worker)
- 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.
- RenderFrameHostImpl* navigating_frame_host =
- frame_tree_node_->render_manager()->speculative_frame_host();
- if (!navigating_frame_host)
- navigating_frame_host = frame_tree_node_->current_frame_host();
- DCHECK(navigating_frame_host);
-
- BrowserContext* browser_context =
- frame_tree_node_->navigator()->GetController()->GetBrowserContext();
- StoragePartition* partition = BrowserContext::GetStoragePartition(
- browser_context, navigating_frame_host->GetSiteInstance());
- DCHECK(partition);
-
- ServiceWorkerContextWrapper* service_worker_context =
- static_cast<ServiceWorkerContextWrapper*>(
- partition->GetServiceWorkerContext());
- navigation_handle_->InitServiceWorkerHandle(service_worker_context);
-}
-
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
index c8bb29613a1..3954cedc273 100644
--- a/chromium/content/browser/frame_host/navigation_request.h
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -92,7 +92,6 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params,
- scoped_refptr<ResourceRequestBody> body,
int current_history_list_offset,
int current_history_list_length);
@@ -166,7 +165,6 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params,
const RequestNavigationParams& request_params,
- scoped_refptr<ResourceRequestBody> body,
bool browser_initiated,
const FrameNavigationEntry* frame_navigation_entry,
const NavigationEntryImpl* navitation_entry);
@@ -181,6 +179,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
std::unique_ptr<NavigationData> navigation_data) override;
void OnRequestFailed(bool has_stale_copy_in_cache, int net_error) override;
void OnRequestStarted(base::TimeTicks timestamp) override;
+ void OnServiceWorkerEncountered() override;
// Called when the NavigationThrottles have been checked by the
// NavigationHandle.
@@ -193,9 +192,6 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// be destroyed after this call.
void CommitNavigation();
- // Called when the navigation is about to be sent to the IO thread.
- void InitializeServiceWorkerHandleIfNeeded();
-
FrameTreeNode* frame_tree_node_;
// Initialized on creation of the NavigationRequest. Sent to the renderer when
diff --git a/chromium/content/browser/frame_host/navigation_request_info.cc b/chromium/content/browser/frame_host/navigation_request_info.cc
index 5bfd979a256..6b01863fa1c 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.cc
+++ b/chromium/content/browser/frame_host/navigation_request_info.cc
@@ -14,16 +14,14 @@ NavigationRequestInfo::NavigationRequestInfo(
const url::Origin& request_initiator,
bool is_main_frame,
bool parent_is_main_frame,
- int frame_tree_node_id,
- scoped_refptr<ResourceRequestBody> request_body)
+ int frame_tree_node_id)
: common_params(common_params),
begin_params(begin_params),
first_party_for_cookies(first_party_for_cookies),
request_initiator(request_initiator),
is_main_frame(is_main_frame),
parent_is_main_frame(parent_is_main_frame),
- frame_tree_node_id(frame_tree_node_id),
- request_body(request_body) {}
+ frame_tree_node_id(frame_tree_node_id) {}
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 ef677db499e..ca6a9d76ba9 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.h
+++ b/chromium/content/browser/frame_host/navigation_request_info.h
@@ -10,7 +10,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/common/navigation_params.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/public/common/referrer.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -28,8 +28,7 @@ struct CONTENT_EXPORT NavigationRequestInfo {
const url::Origin& request_initiator,
bool is_main_frame,
bool parent_is_main_frame,
- int frame_tree_node_id,
- scoped_refptr<ResourceRequestBody> request_body);
+ int frame_tree_node_id);
~NavigationRequestInfo();
const CommonNavigationParams common_params;
@@ -46,8 +45,6 @@ struct CONTENT_EXPORT NavigationRequestInfo {
const bool parent_is_main_frame;
const int frame_tree_node_id;
-
- scoped_refptr<ResourceRequestBody> request_body;
};
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.cc b/chromium/content/browser/frame_host/navigator.cc
index ac6c248cae6..ef03d5249ac 100644
--- a/chromium/content/browser/frame_host/navigator.cc
+++ b/chromium/content/browser/frame_host/navigator.cc
@@ -5,7 +5,7 @@
#include "content/browser/frame_host/navigator.h"
#include "base/time/time.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/public/browser/stream_handle.h"
namespace content {
@@ -35,11 +35,8 @@ base::TimeTicks Navigator::GetCurrentLoadStart() {
return base::TimeTicks::Now();
}
-void Navigator::OnBeginNavigation(
- FrameTreeNode* frame_tree_node,
- const CommonNavigationParams& common_params,
- const BeginNavigationParams& begin_params,
- scoped_refptr<ResourceRequestBody> body) {
-}
+void Navigator::OnBeginNavigation(FrameTreeNode* frame_tree_node,
+ const CommonNavigationParams& common_params,
+ const BeginNavigationParams& begin_params) {}
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
index ce1c97dec99..7270a7c4234 100644
--- a/chromium/content/browser/frame_host/navigator.h
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -29,7 +29,7 @@ class NavigationControllerImpl;
class NavigationEntryImpl;
class NavigationRequest;
class RenderFrameHostImpl;
-class ResourceRequestBody;
+class ResourceRequestBodyImpl;
class StreamHandle;
struct BeginNavigationParams;
struct CommonNavigationParams;
@@ -110,17 +110,21 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
// The RenderFrameHostImpl has received a request to open a URL with the
// specified |disposition|.
- virtual void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- SiteInstance* source_site_instance,
- const Referrer& referrer,
- WindowOpenDisposition disposition,
- bool should_replace_current_entry,
- bool user_gesture) {}
+ virtual void RequestOpenURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ bool uses_post,
+ const scoped_refptr<ResourceRequestBodyImpl>& body,
+ SiteInstance* source_site_instance,
+ const Referrer& referrer,
+ WindowOpenDisposition disposition,
+ bool should_replace_current_entry,
+ bool user_gesture) {}
// The RenderFrameHostImpl wants to transfer the request to a new renderer.
// |redirect_chain| contains any redirect URLs (excluding |url|) that happened
- // before the transfer.
+ // before the transfer. If |method| is "POST", then |post_body| needs to
+ // specify the request body, otherwise |post_body| should be null.
virtual void RequestTransferURL(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
@@ -129,7 +133,9 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
const Referrer& referrer,
ui::PageTransition page_transition,
const GlobalRequestID& transferred_global_request_id,
- bool should_replace_current_entry) {}
+ bool should_replace_current_entry,
+ const std::string& method,
+ scoped_refptr<ResourceRequestBodyImpl> post_body) {}
// PlzNavigate
// Called after receiving a BeforeUnloadACK IPC from the renderer. If
@@ -142,11 +148,9 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
// PlzNavigate
// Used to start a new renderer-initiated navigation, following a
// BeginNavigation IPC from the renderer.
- virtual void OnBeginNavigation(
- FrameTreeNode* frame_tree_node,
- const CommonNavigationParams& common_params,
- const BeginNavigationParams& begin_params,
- scoped_refptr<ResourceRequestBody> body);
+ virtual void OnBeginNavigation(FrameTreeNode* frame_tree_node,
+ const CommonNavigationParams& common_params,
+ const BeginNavigationParams& begin_params);
// PlzNavigate
// Called when a NavigationRequest for |frame_tree_node| failed. An
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
index b5ed8602ce1..b854bbaaf09 100644
--- a/chromium/content/browser/frame_host/navigator_impl.cc
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/time/time.h"
#include "content/browser/frame_host/frame_tree.h"
@@ -42,6 +43,7 @@
#include "content/public/common/resource_response.h"
#include "content/public/common/url_constants.h"
#include "net/base/net_errors.h"
+#include "url/gurl.h"
#include "url/url_constants.h"
namespace content {
@@ -269,7 +271,8 @@ bool NavigatorImpl::NavigateToEntry(
const NavigationEntryImpl& entry,
NavigationController::ReloadType reload_type,
bool is_same_document_history_load,
- bool is_pending_entry) {
+ bool is_pending_entry,
+ const scoped_refptr<ResourceRequestBodyImpl>& post_body) {
TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry");
GURL dest_url = frame_entry.url();
@@ -348,8 +351,9 @@ bool NavigatorImpl::NavigateToEntry(
} else {
RenderFrameHostImpl* dest_render_frame_host =
- frame_tree_node->render_manager()->Navigate(dest_url, frame_entry,
- entry);
+ frame_tree_node->render_manager()->Navigate(
+ dest_url, frame_entry, entry,
+ reload_type != NavigationController::NO_RELOAD);
if (!dest_render_frame_host)
return false; // Unable to create the desired RenderFrameHost.
@@ -387,9 +391,9 @@ bool NavigatorImpl::NavigateToEntry(
FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType(
controller_->GetBrowserContext(), entry, reload_type);
dest_render_frame_host->Navigate(
- entry.ConstructCommonNavigationParams(dest_url, dest_referrer,
- navigation_type, lofi_state,
- navigation_start),
+ entry.ConstructCommonNavigationParams(
+ frame_entry, post_body, dest_url, dest_referrer, navigation_type,
+ lofi_state, navigation_start),
entry.ConstructStartNavigationParams(),
entry.ConstructRequestNavigationParams(
frame_entry, is_same_document_history_load,
@@ -436,7 +440,7 @@ bool NavigatorImpl::NavigateToPendingEntry(
bool is_same_document_history_load) {
return NavigateToEntry(frame_tree_node, frame_entry,
*controller_->GetPendingEntry(), reload_type,
- is_same_document_history_load, true);
+ is_same_document_history_load, true, nullptr);
}
bool NavigatorImpl::NavigateNewChildFrame(
@@ -457,7 +461,7 @@ bool NavigatorImpl::NavigateNewChildFrame(
return NavigateToEntry(render_frame_host->frame_tree_node(), *frame_entry,
*entry, NavigationControllerImpl::NO_RELOAD, false,
- false);
+ false, nullptr);
}
void NavigatorImpl::DidNavigate(
@@ -525,8 +529,8 @@ void NavigatorImpl::DidNavigate(
render_frame_host->frame_tree_node()->SetCurrentOrigin(
params.origin, params.has_potentially_trustworthy_unique_origin);
- render_frame_host->frame_tree_node()->SetEnforceStrictMixedContentChecking(
- params.should_enforce_strict_mixed_content_checking);
+ render_frame_host->frame_tree_node()->SetInsecureRequestPolicy(
+ params.insecure_request_policy);
// Navigating to a new location means a new, fresh set of http headers and/or
// <meta> elements - we need to reset CSP policy to an empty set.
@@ -644,13 +648,16 @@ bool NavigatorImpl::ShouldAssignSiteForURL(const GURL& url) {
return GetContentClient()->browser()->ShouldAssignSiteForURL(url);
}
-void NavigatorImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- SiteInstance* source_site_instance,
- const Referrer& referrer,
- WindowOpenDisposition disposition,
- bool should_replace_current_entry,
- bool user_gesture) {
+void NavigatorImpl::RequestOpenURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ bool uses_post,
+ const scoped_refptr<ResourceRequestBodyImpl>& body,
+ SiteInstance* source_site_instance,
+ const Referrer& referrer,
+ WindowOpenDisposition disposition,
+ bool should_replace_current_entry,
+ bool user_gesture) {
// Note: This can be called for subframes (even when OOPIFs are not possible)
// if the disposition calls for a different window.
@@ -688,6 +695,8 @@ void NavigatorImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
OpenURLParams params(dest_url, referrer, frame_tree_node_id, disposition,
ui::PAGE_TRANSITION_LINK,
true /* is_renderer_initiated */);
+ params.uses_post = uses_post;
+ params.post_data = body;
params.source_site_instance = source_site_instance;
if (redirect_chain.size() > 0)
params.redirect_chain = redirect_chain;
@@ -713,6 +722,9 @@ void NavigatorImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
params.is_renderer_initiated = false;
}
+ GetContentClient()->browser()->OverrideOpenURLParams(current_site_instance,
+ &params);
+
if (delegate_)
delegate_->RequestOpenURL(render_frame_host, params);
}
@@ -725,7 +737,15 @@ void NavigatorImpl::RequestTransferURL(
const Referrer& referrer,
ui::PageTransition page_transition,
const GlobalRequestID& transferred_global_request_id,
- bool should_replace_current_entry) {
+ bool should_replace_current_entry,
+ const std::string& method,
+ scoped_refptr<ResourceRequestBodyImpl> post_body) {
+ // |method != "POST"| should imply absence of |post_body|.
+ if (method != "POST" && post_body) {
+ NOTREACHED();
+ post_body = nullptr;
+ }
+
// This call only makes sense for subframes if OOPIFs are possible.
DCHECK(!render_frame_host->GetParent() ||
SiteIsolationPolicy::AreCrossProcessFramesPossible());
@@ -789,12 +809,10 @@ void NavigatorImpl::RequestTransferURL(
is_renderer_initiated, std::string(),
controller_->GetBrowserContext()));
}
- // TODO(creis): Handle POST submissions. See https://crbug.com/582211 and
- // https://crbug.com/101395.
entry->AddOrUpdateFrameEntry(
node, -1, -1, nullptr,
static_cast<SiteInstanceImpl*>(source_site_instance), dest_url,
- referrer_to_use, PageState(), "GET", -1);
+ referrer_to_use, PageState(), method, -1);
} else {
// Main frame case.
entry = NavigationEntryImpl::FromNavigationEntry(
@@ -824,14 +842,13 @@ void NavigatorImpl::RequestTransferURL(
// further in https://crbug.com/536906.
scoped_refptr<FrameNavigationEntry> frame_entry(entry->GetFrameEntry(node));
if (!frame_entry) {
- // TODO(creis): Handle POST submissions here, as above.
frame_entry = new FrameNavigationEntry(
node->unique_name(), -1, -1, nullptr,
static_cast<SiteInstanceImpl*>(source_site_instance), dest_url,
- referrer_to_use, "GET", -1);
+ referrer_to_use, method, -1);
}
NavigateToEntry(node, *frame_entry, *entry.get(),
- NavigationController::NO_RELOAD, false, false);
+ NavigationController::NO_RELOAD, false, false, post_body);
}
// PlzNavigate
@@ -861,8 +878,7 @@ void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node,
void NavigatorImpl::OnBeginNavigation(
FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
- const BeginNavigationParams& begin_params,
- scoped_refptr<ResourceRequestBody> body) {
+ const BeginNavigationParams& begin_params) {
// TODO(clamy): the url sent by the renderer should be validated with
// FilterURL.
// This is a renderer-initiated navigation.
@@ -890,7 +906,7 @@ void NavigatorImpl::OnBeginNavigation(
// NavigationRequest is created for the node.
frame_tree_node->CreatedNavigationRequest(
NavigationRequest::CreateRendererInitiated(
- frame_tree_node, common_params, begin_params, body,
+ frame_tree_node, common_params, begin_params,
controller_->GetLastCommittedEntryIndex(),
controller_->GetEntryCount()));
NavigationRequest* navigation_request = frame_tree_node->navigation_request();
@@ -1023,7 +1039,8 @@ void NavigatorImpl::RequestNavigation(
ShouldMakeNetworkRequestForURL(
navigation_request->common_params().url)) {
navigation_request->SetWaitingForRendererResponse();
- frame_tree_node->current_frame_host()->DispatchBeforeUnload(true);
+ frame_tree_node->current_frame_host()->DispatchBeforeUnload(
+ true, reload_type != NavigationController::NO_RELOAD);
} else {
navigation_request->BeginNavigation();
}
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
index 1495871395c..f4df9988737 100644
--- a/chromium/content/browser/frame_host/navigator_impl.h
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -24,6 +24,7 @@ namespace content {
class NavigationControllerImpl;
class NavigatorDelegate;
class NavigatorTest;
+class ResourceRequestBodyImpl;
struct LoadCommittedDetails;
// This class is an implementation of Navigator, responsible for managing
@@ -64,24 +65,28 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
const std::string& unique_name) override;
void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
const GURL& url,
+ bool uses_post,
+ const scoped_refptr<ResourceRequestBodyImpl>& body,
SiteInstance* source_site_instance,
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) 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 OnBeforeUnloadACK(FrameTreeNode* frame_tree_node, bool proceed) override;
void OnBeginNavigation(FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
- const BeginNavigationParams& begin_params,
- scoped_refptr<ResourceRequestBody> body) override;
+ const BeginNavigationParams& begin_params) override;
void FailedNavigation(FrameTreeNode* frame_tree_node,
bool has_stale_copy_in_cache,
int error_code) override;
@@ -107,7 +112,8 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
const NavigationEntryImpl& entry,
NavigationController::ReloadType reload_type,
bool is_same_document_history_load,
- bool is_pending_entry);
+ bool is_pending_entry,
+ const scoped_refptr<ResourceRequestBodyImpl>& post_body);
bool ShouldAssignSiteForURL(const GURL& url);
diff --git a/chromium/content/browser/frame_host/navigator_impl_unittest.cc b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
index e8a54420924..d869f06a0d1 100644
--- a/chromium/content/browser/frame_host/navigator_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
@@ -48,20 +48,12 @@ class NavigatorTestWithBrowserSideNavigation
using SiteInstanceRelation = RenderFrameHostManager::SiteInstanceRelation;
void SetUp() override {
-#if !defined(OS_ANDROID)
- ImageTransportFactory::InitializeForUnitTests(
- std::unique_ptr<ImageTransportFactory>(
- new NoTransportImageTransportFactory));
-#endif
EnableBrowserSideNavigation();
RenderViewHostImplTestHarness::SetUp();
}
void TearDown() override {
RenderViewHostImplTestHarness::TearDown();
-#if !defined(OS_ANDROID)
- ImageTransportFactory::Terminate();
-#endif
}
TestNavigationURLLoader* GetLoaderForNavigationRequest(
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 9054ea9f36c..c1cb9fb65c9 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -38,6 +38,7 @@ class WakeLockServiceContext;
class WebContents;
struct AXEventNotificationDetails;
struct ContextMenuParams;
+struct FileChooserParams;
struct TransitionLayerData;
// An interface implemented by an object interested in knowing about the state
@@ -81,6 +82,10 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
bool is_reload,
IPC::Message* reply_msg) {}
+ // Called when a file selection is to be done.
+ virtual void RunFileChooser(RenderFrameHost* render_frame_host,
+ const FileChooserParams& params) {}
+
// Another page accessed the top-level initial empty document, which means it
// is no longer safe to display a pending URL without risking a URL spoof.
virtual void DidAccessInitialDocument() {}
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 e0f6426de3a..720125a93f3 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -21,7 +21,6 @@
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
#include "content/browser/child_process_security_policy_impl.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"
@@ -58,7 +57,6 @@
#include "content/common/input_messages.h"
#include "content/common/inter_process_time_ticks_converter.h"
#include "content/common/navigation_params.h"
-#include "content/common/render_frame_setup.mojom.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/swapped_out_messages.h"
#include "content/public/browser/ax_event_notification_details.h"
@@ -71,15 +69,19 @@
#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/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_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/url_constants.h"
#include "content/public/common/url_utils.h"
#include "device/vibration/vibration_manager_impl.h"
+#include "services/shell/public/cpp/interface_provider.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/gfx/geometry/quad_f.h"
@@ -95,8 +97,8 @@
#if defined(ENABLE_WEBVR)
#include "base/command_line.h"
-#include "content/browser/vr/vr_device_manager.h"
#include "content/public/common/content_switches.h"
+#include "device/vr/vr_device_manager.h" // nogncheck
#endif
using base::TimeDelta;
@@ -158,6 +160,17 @@ class ScopedCommitStateResetter {
bool disabled_;
};
+void GrantFileAccess(int child_id,
+ const std::vector<base::FilePath>& file_paths) {
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+
+ for (const auto& file : file_paths) {
+ if (!policy->CanReadFile(child_id, file))
+ policy->GrantReadFile(child_id, file);
+ }
+}
+
} // namespace
// static
@@ -215,6 +228,7 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
render_frame_proxy_host_(NULL),
frame_tree_(frame_tree),
frame_tree_node_(frame_tree_node),
+ parent_(nullptr),
render_widget_host_(nullptr),
routing_id_(routing_id),
is_waiting_for_swapout_ack_(false),
@@ -233,6 +247,7 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
pending_web_ui_type_(WebUI::kNoWebUI),
should_reuse_web_ui_(false),
last_navigation_lofi_state_(LOFI_UNSPECIFIED),
+ frame_host_binding_(this),
weak_ptr_factory_(this) {
frame_tree_->AddRenderViewHostRef(render_view_host_);
GetProcess()->AddRoute(routing_id_, this);
@@ -242,8 +257,13 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
site_instance_->AddObserver(this);
GetSiteInstance()->IncrementActiveFrameCount();
- // New child frames should inherit the nav_entry_id of their parent.
if (frame_tree_node_->parent()) {
+ // Keep track of the parent RenderFrameHost, which shouldn't change even if
+ // this RenderFrameHost is on the pending deletion list and the parent
+ // FrameTreeNode has changed its current RenderFrameHost.
+ parent_ = frame_tree_node_->parent()->current_frame_host();
+
+ // New child frames should inherit the nav_entry_id of their parent.
set_nav_entry_id(
frame_tree_node_->parent()->current_frame_host()->nav_entry_id());
}
@@ -336,10 +356,7 @@ RenderProcessHost* RenderFrameHostImpl::GetProcess() {
}
RenderFrameHostImpl* RenderFrameHostImpl::GetParent() {
- FrameTreeNode* parent_node = frame_tree_node_->parent();
- if (!parent_node)
- return NULL;
- return parent_node->current_frame_host();
+ return parent_;
}
int RenderFrameHostImpl::GetFrameTreeNodeId() {
@@ -351,11 +368,9 @@ const std::string& RenderFrameHostImpl::GetFrameName() {
}
bool RenderFrameHostImpl::IsCrossProcessSubframe() {
- FrameTreeNode* parent_node = frame_tree_node_->parent();
- if (!parent_node)
+ if (!parent_)
return false;
- return GetSiteInstance() !=
- parent_node->current_frame_host()->GetSiteInstance();
+ return GetSiteInstance() != parent_->GetSiteInstance();
}
const GURL& RenderFrameHostImpl::GetLastCommittedURL() {
@@ -446,28 +461,47 @@ void RenderFrameHostImpl::ExecuteJavaScriptInIsolatedWorld(
routing_id_, javascript, key, request_reply, world_id));
}
+void RenderFrameHostImpl::CopyImageAt(int x, int y) {
+ Send(new FrameMsg_CopyImageAt(routing_id_, x, y));
+}
+
+void RenderFrameHostImpl::SaveImageAt(int x, int y) {
+ Send(new FrameMsg_SaveImageAt(routing_id_, x, y));
+}
+
RenderViewHost* RenderFrameHostImpl::GetRenderViewHost() {
return render_view_host_;
}
-ServiceRegistry* RenderFrameHostImpl::GetServiceRegistry() {
- return service_registry_.get();
+shell::InterfaceRegistry* RenderFrameHostImpl::GetInterfaceRegistry() {
+ return interface_registry_.get();
+}
+
+shell::InterfaceProvider* RenderFrameHostImpl::GetRemoteInterfaces() {
+ return remote_interfaces_.get();
}
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
- // detached from the frame tree.
- RenderWidgetHostView* view = RenderFrameHostImpl::GetView();
- if (!view || !view->GetRenderWidgetHost())
+ // detached from the frame tree. This tries to find a RenderWidgetHost
+ // attached to an ancestor frame, and defaults to visibility hidden if
+ // it fails.
+ // TODO(yfriedman, peter): Ideally this would never be called on an
+ // unattached frame and we could omit this check. See
+ // https://crbug.com/615867.
+ RenderFrameHostImpl* frame = this;
+ while (frame) {
+ if (frame->render_widget_host_)
+ break;
+ frame = frame->GetParent();
+ }
+ if (!frame)
return blink::WebPageVisibilityStateHidden;
- // TODO(mlamouri,kenrb): call GetRenderWidgetHost() directly when it stops
- // returning nullptr in some cases. See https://crbug.com/455245.
blink::WebPageVisibilityState visibility_state =
- RenderWidgetHostImpl::From(view->GetRenderWidgetHost())->is_hidden()
- ? blink::WebPageVisibilityStateHidden
- : blink::WebPageVisibilityStateVisible;
+ GetRenderWidgetHost()->is_hidden() ? blink::WebPageVisibilityStateHidden
+ : blink::WebPageVisibilityStateVisible;
GetContentClient()->browser()->OverridePageVisibilityState(this,
&visibility_state);
return visibility_state;
@@ -539,14 +573,15 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnRunJavaScriptMessage)
IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_RunBeforeUnloadConfirm,
OnRunBeforeUnloadConfirm)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_RunFileChooser, OnRunFileChooser)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidAccessInitialDocument,
OnDidAccessInitialDocument)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeOpener, OnDidChangeOpener)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeName, OnDidChangeName)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidAddContentSecurityPolicy,
OnDidAddContentSecurityPolicy)
- IPC_MESSAGE_HANDLER(FrameHostMsg_EnforceStrictMixedContentChecking,
- OnEnforceStrictMixedContentChecking)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_EnforceInsecureRequestPolicy,
+ OnEnforceInsecureRequestPolicy)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateToUniqueOrigin,
OnUpdateToUniqueOrigin)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidAssignPageId, OnDidAssignPageId)
@@ -577,7 +612,7 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnDidChangeLoadProgress)
IPC_MESSAGE_HANDLER(FrameHostMsg_SerializeAsMHTMLResponse,
OnSerializeAsMHTMLResponse)
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
IPC_MESSAGE_HANDLER(FrameHostMsg_HidePopup, OnHidePopup)
#endif
@@ -1074,8 +1109,7 @@ void RenderFrameHostImpl::OnDidCommitProvisionalLoad(const IPC::Message& msg) {
// Without this check, the renderer can trick the browser into using
// filenames it can't access in a future session restore.
- if (!render_view_host_->CanAccessFilesOfPageState(
- validated_params.page_state)) {
+ if (!CanAccessFilesOfPageState(validated_params.page_state)) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_CAN_ACCESS_FILES_OF_PAGE_STATE);
return;
@@ -1166,8 +1200,7 @@ void RenderFrameHostImpl::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.
- // TODO(creis): Move CanAccessFilesOfPageState to RenderFrameHostImpl.
- if (!render_view_host_->CanAccessFilesOfPageState(state)) {
+ if (!CanAccessFilesOfPageState(state)) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_CAN_ACCESS_FILES_OF_PAGE_STATE);
return;
@@ -1177,21 +1210,21 @@ void RenderFrameHostImpl::OnUpdateState(const PageState& state) {
}
RenderWidgetHostImpl* RenderFrameHostImpl::GetRenderWidgetHost() {
- return render_widget_host_;
-}
-
-RenderWidgetHostView* RenderFrameHostImpl::GetView() {
RenderFrameHostImpl* frame = this;
while (frame) {
if (frame->render_widget_host_)
- return frame->render_widget_host_->GetView();
- frame = static_cast<RenderFrameHostImpl*>(frame->GetParent());
+ return frame->render_widget_host_;
+ frame = frame->GetParent();
}
NOTREACHED();
return nullptr;
}
+RenderWidgetHostView* RenderFrameHostImpl::GetView() {
+ return GetRenderWidgetHost()->GetView();
+}
+
GlobalFrameRoutingId RenderFrameHostImpl::GetGlobalFrameRoutingId() {
return GlobalFrameRoutingId(GetProcess()->GetID(), GetRoutingID());
}
@@ -1264,6 +1297,9 @@ void RenderFrameHostImpl::SwapOut(
replication_state));
}
+ if (web_ui())
+ web_ui()->RenderFrameHostSwappingOut();
+
// TODO(nasko): If the frame is not live, the RFH should just be deleted by
// simulating the receipt of swap out ack.
is_waiting_for_swapout_ack_ = true;
@@ -1513,6 +1549,19 @@ void RenderFrameHostImpl::OnRunBeforeUnloadConfirm(
delegate_->RunBeforeUnloadConfirm(this, is_reload, reply_msg);
}
+void RenderFrameHostImpl::OnRunFileChooser(const FileChooserParams& params) {
+ // Do not allow messages with absolute paths in them as this can permit a
+ // renderer to coerce the browser to perform I/O on a renderer controlled
+ // path.
+ if (params.default_file_name != params.default_file_name.BaseName()) {
+ bad_message::ReceivedBadMessage(GetProcess(),
+ bad_message::RFH_FILE_CHOOSER_PATH);
+ return;
+ }
+
+ delegate_->RunFileChooser(this, params);
+}
+
void RenderFrameHostImpl::OnTextSurroundingSelectionResponse(
const base::string16& content,
uint32_t start_offset,
@@ -1549,8 +1598,9 @@ void RenderFrameHostImpl::OnDidAddContentSecurityPolicy(
frame_tree_node()->AddContentSecurityPolicy(header);
}
-void RenderFrameHostImpl::OnEnforceStrictMixedContentChecking() {
- frame_tree_node()->SetEnforceStrictMixedContentChecking(true);
+void RenderFrameHostImpl::OnEnforceInsecureRequestPolicy(
+ blink::WebInsecureRequestPolicy policy) {
+ frame_tree_node()->SetInsecureRequestPolicy(policy);
}
void RenderFrameHostImpl::OnUpdateToUniqueOrigin(
@@ -1608,23 +1658,15 @@ void RenderFrameHostImpl::OnDidChangeSandboxFlags(
void RenderFrameHostImpl::OnDidChangeFrameOwnerProperties(
int32_t frame_routing_id,
- const blink::WebFrameOwnerProperties& frame_owner_properties) {
+ const blink::WebFrameOwnerProperties& properties) {
FrameTreeNode* child = FindAndVerifyChild(
frame_routing_id, bad_message::RFH_OWNER_PROPERTY);
if (!child)
return;
- child->set_frame_owner_properties(frame_owner_properties);
+ child->set_frame_owner_properties(properties);
- // Notify the RenderFrame if it lives in a different process from its parent.
- // These properties only affect the RenderFrame and live in its parent
- // (HTMLFrameOwnerElement). Therefore, we do not need to notify this frame's
- // proxies.
- RenderFrameHost* child_rfh = child->current_frame_host();
- if (child_rfh->GetSiteInstance() != GetSiteInstance()) {
- child_rfh->Send(new FrameMsg_SetFrameOwnerProperties(
- child_rfh->GetRoutingID(), frame_owner_properties));
- }
+ child->render_manager()->OnDidUpdateFrameOwnerProperties(properties);
}
void RenderFrameHostImpl::OnUpdateTitle(
@@ -1652,13 +1694,12 @@ void RenderFrameHostImpl::OnUpdateEncoding(const std::string& encoding_name) {
void RenderFrameHostImpl::OnBeginNavigation(
const CommonNavigationParams& common_params,
- const BeginNavigationParams& begin_params,
- scoped_refptr<ResourceRequestBody> body) {
+ const BeginNavigationParams& begin_params) {
CHECK(IsBrowserSideNavigationEnabled());
CommonNavigationParams validated_params = common_params;
GetProcess()->FilterURL(false, &validated_params.url);
frame_tree_node()->navigator()->OnBeginNavigation(
- frame_tree_node(), validated_params, begin_params, body);
+ frame_tree_node(), validated_params, begin_params);
}
void RenderFrameHostImpl::OnDispatchLoad() {
@@ -1831,7 +1872,40 @@ void RenderFrameHostImpl::OnAccessibilitySnapshotResponse(
}
}
+// TODO(alexmos): When the allowFullscreen flag is known in the browser
+// process, use it to double-check that fullscreen can be entered here.
void RenderFrameHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
+ // Entering fullscreen from a cross-process subframe also affects all
+ // renderers for ancestor frames, which will need to apply fullscreen CSS to
+ // appropriate ancestor <iframe> elements, fire fullscreenchange events, etc.
+ // Thus, walk through the ancestor chain of this frame and for each (parent,
+ // child) pair, send a message about the pending fullscreen change to the
+ // child's proxy in parent's SiteInstance. The renderer process will use this
+ // to find the <iframe> element in the parent frame that will need fullscreen
+ // styles. This is done at most once per SiteInstance: for example, with a
+ // A-B-A-B hierarchy, if the bottom frame goes fullscreen, this only needs to
+ // notify its parent, and Blink-side logic will take care of applying
+ // necessary changes to the other two ancestors.
+ if (enter_fullscreen &&
+ SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ std::set<SiteInstance*> notified_instances;
+ notified_instances.insert(GetSiteInstance());
+ for (FrameTreeNode* node = frame_tree_node_; node->parent();
+ node = node->parent()) {
+ SiteInstance* parent_site_instance =
+ node->parent()->current_frame_host()->GetSiteInstance();
+ if (ContainsKey(notified_instances, parent_site_instance))
+ continue;
+
+ RenderFrameProxyHost* child_proxy =
+ node->render_manager()->GetRenderFrameProxyHost(parent_site_instance);
+ child_proxy->Send(
+ new FrameMsg_WillEnterFullscreen(child_proxy->GetRoutingID()));
+ notified_instances.insert(parent_site_instance);
+ }
+ }
+
+ // TODO(alexmos): See if this can use the last committed origin instead.
if (enter_fullscreen)
delegate_->EnterFullscreenMode(last_committed_url().GetOrigin());
else
@@ -1839,6 +1913,12 @@ void RenderFrameHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
// The previous call might change the fullscreen state. We need to make sure
// the renderer is aware of that, which is done via the resize message.
+ // Typically, this will be sent as part of the call on the |delegate_| above
+ // when resizing the native windows, but sometimes fullscreen can be entered
+ // without causing a resize, so we need to ensure that the resize message is
+ // sent in that case. We always send this to the main frame's widget, and if
+ // there are any OOPIF widgets, this will also trigger them to resize via
+ // frameRectsChanged.
render_view_host_->GetWidget()->WasResized();
}
@@ -1891,7 +1971,7 @@ void RenderFrameHostImpl::OnSerializeAsMHTMLResponse(
this, job_id, success, digests_of_uris_of_serialized_resources);
}
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
void RenderFrameHostImpl::OnShowPopup(
const FrameHostMsg_ShowPopup_Params& params) {
RenderViewHostDelegateView* view =
@@ -1918,7 +1998,7 @@ void RenderFrameHostImpl::OnHidePopup() {
}
#endif
-void RenderFrameHostImpl::RegisterMojoServices() {
+void RenderFrameHostImpl::RegisterMojoInterfaces() {
GeolocationServiceContext* geolocation_service_context =
delegate_ ? delegate_->GetGeolocationServiceContext() : NULL;
if (geolocation_service_context) {
@@ -1931,7 +2011,7 @@ void RenderFrameHostImpl::RegisterMojoServices() {
// latter is triggered by receiving a message that the pipe was closed from
// the renderer side. Hence, supply the reference to this object as a weak
// pointer.
- GetServiceRegistry()->AddService(
+ GetInterfaceRegistry()->AddInterface(
base::Bind(&GeolocationServiceContext::CreateService,
base::Unretained(geolocation_service_context),
base::Bind(&RenderFrameHostImpl::DidUseGeolocationPermission,
@@ -1944,7 +2024,7 @@ void RenderFrameHostImpl::RegisterMojoServices() {
// WakeLockServiceContext is owned by WebContentsImpl so it will outlive
// this RenderFrameHostImpl, hence a raw pointer can be bound to service
// factory callback.
- GetServiceRegistry()->AddService<blink::mojom::WakeLockService>(
+ GetInterfaceRegistry()->AddInterface<blink::mojom::WakeLockService>(
base::Bind(&WakeLockServiceContext::CreateService,
base::Unretained(wake_lock_service_context),
GetProcess()->GetID(), GetRoutingID()));
@@ -1953,26 +2033,26 @@ void RenderFrameHostImpl::RegisterMojoServices() {
if (!permission_service_context_)
permission_service_context_.reset(new PermissionServiceContext(this));
- GetServiceRegistry()->AddService(
+ GetInterfaceRegistry()->AddInterface(
base::Bind(&PermissionServiceContext::CreateService,
base::Unretained(permission_service_context_.get())));
- GetServiceRegistry()->AddService(base::Bind(
+ GetInterfaceRegistry()->AddInterface(base::Bind(
&PresentationServiceImpl::CreateMojoService, base::Unretained(this)));
#if !defined(OS_ANDROID)
- GetServiceRegistry()->AddService(
+ 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)
+#if defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_MACOSX)
enable_web_bluetooth = true;
#endif
if (enable_web_bluetooth) {
- GetServiceRegistry()->AddService(
+ GetInterfaceRegistry()->AddInterface(
base::Bind(&RenderFrameHostImpl::CreateWebBluetoothService,
base::Unretained(this)));
}
@@ -1980,7 +2060,7 @@ void RenderFrameHostImpl::RegisterMojoServices() {
if (!frame_mojo_shell_)
frame_mojo_shell_.reset(new FrameMojoShell(this));
- GetServiceRegistry()->AddService<shell::mojom::Connector>(base::Bind(
+ GetInterfaceRegistry()->AddInterface<shell::mojom::Connector>(base::Bind(
&FrameMojoShell::BindRequest, base::Unretained(frame_mojo_shell_.get())));
#if defined(ENABLE_WEBVR)
@@ -1988,13 +2068,13 @@ void RenderFrameHostImpl::RegisterMojoServices() {
*base::CommandLine::ForCurrentProcess();
if (browser_command_line.HasSwitch(switches::kEnableWebVR)) {
- GetServiceRegistry()->AddService<blink::mojom::VRService>(
- base::Bind(&VRDeviceManager::BindRequest));
+ GetInterfaceRegistry()->AddInterface<device::VRService>(
+ base::Bind(&device::VRDeviceManager::BindRequest));
}
#endif
- GetContentClient()->browser()->RegisterRenderFrameMojoServices(
- GetServiceRegistry(), this);
+ GetContentClient()->browser()->RegisterRenderFrameMojoInterfaces(
+ GetInterfaceRegistry(), this);
}
void RenderFrameHostImpl::ResetWaitingState() {
@@ -2108,7 +2188,7 @@ void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
data_url, Referrer(), ui::PAGE_TRANSITION_LINK,
FrameMsg_Navigate_Type::NORMAL, false, false, base::TimeTicks::Now(),
FrameMsg_UILoadMetricsReportType::NO_REPORT, GURL(), GURL(), LOFI_OFF,
- base::TimeTicks::Now(), "GET");
+ base::TimeTicks::Now(), "GET", nullptr);
if (IsBrowserSideNavigationEnabled()) {
CommitNavigation(nullptr, nullptr, common_params, RequestNavigationParams(),
false);
@@ -2125,16 +2205,19 @@ void RenderFrameHostImpl::OpenURL(const FrameHostMsg_OpenURL_Params& params,
TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL", "url",
validated_url.possibly_invalid_spec());
frame_tree_node_->navigator()->RequestOpenURL(
- this, validated_url, source_site_instance, params.referrer,
- params.disposition, params.should_replace_current_entry,
- params.user_gesture);
+ 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_));
}
-void RenderFrameHostImpl::DispatchBeforeUnload(bool for_navigation) {
+void RenderFrameHostImpl::DispatchBeforeUnload(bool for_navigation,
+ bool is_reload) {
+ DCHECK(for_navigation || !is_reload);
+
// TODO(creis): Support beforeunload on subframes. For now just pretend that
// the handler ran and allowed the navigation to proceed.
if (!ShouldDispatchBeforeUnload()) {
@@ -2147,7 +2230,7 @@ void RenderFrameHostImpl::DispatchBeforeUnload(bool for_navigation) {
this, "&RenderFrameHostImpl", (void*)this);
// This may be called more than once (if the user clicks the tab close button
- // several times, or if she clicks the tab close button then the browser close
+ // several times, or if they click the tab close button then the browser close
// button), and we only send the message once.
if (is_waiting_for_beforeunload_ack_) {
// Some of our close messages could be for the tab, others for cross-site
@@ -2167,12 +2250,19 @@ void RenderFrameHostImpl::DispatchBeforeUnload(bool for_navigation) {
// cancel the timeout timer.
render_view_host_->GetWidget()->increment_in_flight_event_count();
render_view_host_->GetWidget()->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS));
+ TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_BEFORE_UNLOAD);
send_before_unload_start_time_ = base::TimeTicks::Now();
- Send(new FrameMsg_BeforeUnload(routing_id_));
+ Send(new FrameMsg_BeforeUnload(routing_id_, is_reload));
}
}
+void RenderFrameHostImpl::SimulateBeforeUnloadAck() {
+ DCHECK(is_waiting_for_beforeunload_ack_);
+ base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
+ OnBeforeUnloadACK(true, approx_renderer_start_time, base::TimeTicks::Now());
+}
+
bool RenderFrameHostImpl::ShouldDispatchBeforeUnload() {
// TODO(creis): Support beforeunload on subframes.
return !GetParent() && IsRenderFrameLive();
@@ -2214,10 +2304,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;
+ if (success) {
+ type = is_waiting_for_beforeunload_ack_
+ ? RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_BEFORE_UNLOAD
+ : RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNLOAD;
+ }
render_view_host_->GetWidget()->StartHangMonitorTimeout(
success
? TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS)
- : render_view_host_->GetWidget()->hung_renderer_delay());
+ : render_view_host_->GetWidget()->hung_renderer_delay(),
+ type);
}
FrameHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg,
@@ -2232,7 +2330,8 @@ void RenderFrameHostImpl::JavaScriptDialogClosed(
// correctly while waiting for a response.
if (is_waiting && dialog_was_suppressed) {
render_view_host_->GetWidget()->delegate()->RendererUnresponsive(
- render_view_host_->GetWidget());
+ render_view_host_->GetWidget(),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_DIALOG_SUPPRESSED);
}
}
@@ -2301,29 +2400,31 @@ void RenderFrameHostImpl::FailedNavigation(
}
void RenderFrameHostImpl::SetUpMojoIfNeeded() {
- if (service_registry_.get())
+ if (interface_registry_.get())
return;
- service_registry_.reset(new ServiceRegistryImpl());
- if (!GetProcess()->GetServiceRegistry())
+ interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+ if (!GetProcess()->GetRemoteInterfaces())
return;
- RegisterMojoServices();
- mojom::RenderFrameSetupPtr setup;
- GetProcess()->GetServiceRegistry()->ConnectToRemoteService(
- mojo::GetProxy(&setup));
+ RegisterMojoInterfaces();
+ mojom::FrameFactoryPtr frame_factory;
+ GetProcess()->GetRemoteInterfaces()->GetInterface(&frame_factory);
+ frame_factory->CreateFrame(routing_id_, GetProxy(&frame_),
+ frame_host_binding_.CreateInterfacePtrAndBind());
- shell::mojom::InterfaceProviderPtr exposed_services;
- service_registry_->Bind(GetProxy(&exposed_services));
- shell::mojom::InterfaceProviderPtr services;
- setup->ExchangeInterfaceProviders(routing_id_, GetProxy(&services),
- std::move(exposed_services));
- service_registry_->BindRemoteServiceProvider(std::move(services));
+ shell::mojom::InterfaceProviderPtr remote_interfaces;
+ shell::mojom::InterfaceProviderRequest remote_interfaces_request =
+ GetProxy(&remote_interfaces);
+ remote_interfaces_.reset(new shell::InterfaceProvider);
+ remote_interfaces_->Bind(std::move(remote_interfaces));
+ frame_->GetInterfaceProvider(std::move(remote_interfaces_request));
#if defined(OS_ANDROID)
service_registry_android_ =
- ServiceRegistryAndroid::Create(service_registry_.get());
+ ServiceRegistryAndroid::Create(interface_registry_.get(),
+ remote_interfaces_.get());
ServiceRegistrarAndroid::RegisterFrameHostServices(
service_registry_android_.get());
#endif
@@ -2336,17 +2437,16 @@ void RenderFrameHostImpl::InvalidateMojoConnection() {
service_registry_android_.reset();
#endif
- service_registry_.reset();
+ interface_registry_.reset();
+ frame_.reset();
+ frame_host_binding_.Close();
// Disconnect with ImageDownloader Mojo service in RenderFrame.
mojo_image_downloader_.reset();
}
bool RenderFrameHostImpl::IsFocused() {
- // TODO(mlamouri,kenrb): call GetRenderWidgetHost() directly when it stops
- // returning nullptr in some cases. See https://crbug.com/455245.
- return RenderWidgetHostImpl::From(
- GetView()->GetRenderWidgetHost())->is_focused() &&
+ return GetRenderWidgetHost()->is_focused() &&
frame_tree_->GetFocusedFrame() &&
(frame_tree_->GetFocusedFrame() == frame_tree_node() ||
frame_tree_->GetFocusedFrame()->IsDescendantOf(frame_tree_node()));
@@ -2445,10 +2545,8 @@ void RenderFrameHostImpl::ClearAllWebUI() {
const content::mojom::ImageDownloaderPtr&
RenderFrameHostImpl::GetMojoImageDownloader() {
- if (!mojo_image_downloader_.get() && GetServiceRegistry()) {
- GetServiceRegistry()->ConnectToRemoteService(
- mojo::GetProxy(&mojo_image_downloader_));
- }
+ if (!mojo_image_downloader_.get() && GetRemoteInterfaces())
+ GetRemoteInterfaces()->GetInterface(&mojo_image_downloader_);
return mojo_image_downloader_;
}
@@ -2575,6 +2673,39 @@ int RenderFrameHostImpl::GetProxyCount() {
return frame_tree_node_->render_manager()->GetProxyCount();
}
+void RenderFrameHostImpl::FilesSelectedInChooser(
+ const std::vector<content::FileChooserFileInfo>& files,
+ FileChooserParams::Mode permissions) {
+ storage::FileSystemContext* const file_system_context =
+ BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
+ GetSiteInstance())
+ ->GetFileSystemContext();
+ // Grant the security access requested to the given files.
+ for (const auto& file : files) {
+ if (permissions == FileChooserParams::Save) {
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantCreateReadWriteFile(
+ GetProcess()->GetID(), file.file_path);
+ } else {
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
+ GetProcess()->GetID(), file.file_path);
+ }
+ if (file.file_system_url.is_valid()) {
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFileSystem(
+ GetProcess()->GetID(),
+ file_system_context->CrackURL(file.file_system_url)
+ .mount_filesystem_id());
+ }
+ }
+
+ Send(new FrameMsg_RunFileChooserResponse(routing_id_, files));
+}
+
+void RenderFrameHostImpl::GetInterfaceProvider(
+ shell::mojom::InterfaceProviderRequest interfaces) {
+ interface_registry_->Bind(std::move(interfaces));
+}
+
+#if defined(USE_EXTERNAL_POPUP_MENU)
#if defined(OS_MACOSX)
void RenderFrameHostImpl::DidSelectPopupMenuItem(int selected_index) {
@@ -2585,7 +2716,7 @@ void RenderFrameHostImpl::DidCancelPopupMenu() {
Send(new FrameMsg_SelectPopupMenuItem(routing_id_, -1));
}
-#elif defined(OS_ANDROID)
+#else
void RenderFrameHostImpl::DidSelectPopupMenuItems(
const std::vector<int>& selected_indices) {
@@ -2598,6 +2729,7 @@ void RenderFrameHostImpl::DidCancelPopupMenu() {
}
#endif
+#endif
void RenderFrameHostImpl::SetNavigationsSuspended(
bool suspend,
@@ -2664,6 +2796,20 @@ void RenderFrameHostImpl::DidUseGeolocationPermission() {
->last_committed_url().GetOrigin());
}
+bool RenderFrameHostImpl::CanAccessFilesOfPageState(const PageState& state) {
+ return ChildProcessSecurityPolicyImpl::GetInstance()->CanReadAllFiles(
+ GetProcess()->GetID(), state.GetReferencedFiles());
+}
+
+void RenderFrameHostImpl::GrantFileAccessFromPageState(const PageState& state) {
+ GrantFileAccess(GetProcess()->GetID(), state.GetReferencedFiles());
+}
+
+void RenderFrameHostImpl::GrantFileAccessFromResourceRequestBody(
+ const ResourceRequestBodyImpl& body) {
+ GrantFileAccess(GetProcess()->GetID(), body.GetReferencedFiles());
+}
+
void RenderFrameHostImpl::UpdatePermissionsForNavigation(
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params) {
@@ -2683,11 +2829,20 @@ void RenderFrameHostImpl::UpdatePermissionsForNavigation(
// We may be returning to an existing NavigationEntry that had been granted
// file access. If this is a different process, we will need to grant the
- // access again. The files listed in the page state are validated when they
- // are received from the renderer to prevent abuse.
- if (request_params.page_state.IsValid()) {
- render_view_host_->GrantFileAccessFromPageState(request_params.page_state);
- }
+ // access again. Abuse is prevented, because the files listed in the page
+ // state are validated earlier, when they are received from the renderer (in
+ // RenderFrameHostImpl::CanAccessFilesOfPageState).
+ if (request_params.page_state.IsValid())
+ GrantFileAccessFromPageState(request_params.page_state);
+
+ // We may be here after transferring navigation to a different renderer
+ // process. In this case, we need to ensure that the new renderer retains
+ // ability to access files that the old renderer could access. Abuse is
+ // prevented, because the files listed in ResourceRequestBody are validated
+ // earlier, when they are recieved from the renderer (in ShouldServiceRequest
+ // called from ResourceDispatcherHostImpl::BeginRequest).
+ if (common_params.post_data)
+ GrantFileAccessFromResourceRequestBody(*common_params.post_data);
}
bool RenderFrameHostImpl::CanExecuteJavaScript() {
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 eb2c46545f1..fe6afddd09d 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -29,14 +29,16 @@
#include "content/common/accessibility_mode_enums.h"
#include "content/common/ax_content_node_data.h"
#include "content/common/content_export.h"
+#include "content/common/frame.mojom.h"
#include "content/common/frame_message_enums.h"
#include "content/common/frame_replication_state.h"
#include "content/common/image_downloader/image_downloader.mojom.h"
-#include "content/common/mojo/service_registry_impl.h"
#include "content/common/navigation_params.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/javascript_message_type.h"
#include "net/http/http_response_headers.h"
+#include "services/shell/public/cpp/interface_registry.h"
+#include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
#include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
#include "third_party/WebKit/public/web/WebTreeScopeType.h"
@@ -54,7 +56,7 @@ struct AccessibilityHostMsg_LocationChangeParams;
struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
struct FrameHostMsg_OpenURL_Params;
struct FrameMsg_TextTrackSettings_Params;
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
struct FrameHostMsg_ShowPopup_Params;
#endif
@@ -92,13 +94,17 @@ class TimeoutMonitor;
class WebBluetoothServiceImpl;
struct ContentSecurityPolicyHeader;
struct ContextMenuParams;
+struct FileChooserParams;
struct GlobalRequestID;
+struct FileChooserParams;
struct Referrer;
struct ResourceResponse;
-class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
- public BrowserAccessibilityDelegate,
- public SiteInstanceImpl::Observer {
+class CONTENT_EXPORT RenderFrameHostImpl
+ : public RenderFrameHost,
+ NON_EXPORTED_BASE(public mojom::FrameHost),
+ public BrowserAccessibilityDelegate,
+ public SiteInstanceImpl::Observer {
public:
using AXTreeSnapshotCallback =
base::Callback<void(
@@ -145,11 +151,20 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
const base::string16& javascript) override;
void ActivateFindInPageResultForAccessibility(int request_id) override;
void InsertVisualStateCallback(const VisualStateCallback& callback) override;
+ void CopyImageAt(int x, int y) override;
+ void SaveImageAt(int x, int y) override;
RenderViewHost* GetRenderViewHost() override;
- ServiceRegistry* GetServiceRegistry() override;
+ shell::InterfaceRegistry* GetInterfaceRegistry() override;
+ shell::InterfaceProvider* GetRemoteInterfaces() override;
blink::WebPageVisibilityState GetVisibilityState() override;
bool IsRenderFrameLive() override;
int GetProxyCount() override;
+ void FilesSelectedInChooser(const std::vector<FileChooserFileInfo>& files,
+ FileChooserParams::Mode permissions) override;
+
+ // mojom::FrameHost
+ void GetInterfaceProvider(
+ shell::mojom::InterfaceProviderRequest interfaces) override;
// IPC::Sender
bool Send(IPC::Message* msg) override;
@@ -252,10 +267,23 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
// TODO(clamy): Remove this once PlzNavigate ships.
void set_is_loading(bool is_loading) { is_loading_ = is_loading; }
- // This returns the RenderFrameHost's owned RenderWidgetHost if it has one,
- // or else it returns nullptr.
- // If the RenderFrameHost is the page's main frame, this returns instead a
- // pointer to the RenderViewHost (which inherits RenderWidgetHost).
+ // Returns true if this is a top-level frame, or if this frame's RenderFrame
+ // is in a different process from its parent frame. Local roots are
+ // 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_; }
+
+ // Returns the RenderWidgetHostImpl attached to this frame or the nearest
+ // ancestor frame, which could potentially be the root. For most input
+ // and rendering related purposes, GetView() should be preferred and
+ // RenderWidgetHostViewBase methods used. GetRenderWidgetHost() will not
+ // return a nullptr, whereas GetView() potentially will (for instance,
+ // after a renderer crash).
+ //
+ // This method crashes if this RenderFrameHostImpl does not own a
+ // a RenderWidgetHost and nor does any of its ancestors. That would
+ // typically mean that the frame has been detached from the frame tree.
RenderWidgetHostImpl* GetRenderWidgetHost();
GlobalFrameRoutingId GetGlobalFrameRoutingId();
@@ -398,9 +426,14 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
// Runs the beforeunload handler for this frame. |for_navigation| indicates
// whether this call is for the current frame during a cross-process
- // navigation. False means we're closing the entire tab.
+ // navigation. False means we're closing the entire tab. |is_reload|
+ // indicates whether the navigation is a reload of the page or not. If
+ // |for_navigation| is false, |is_reload| should be false as well.
// PlzNavigate: this call happens on all browser-initiated navigations.
- void DispatchBeforeUnload(bool for_navigation);
+ void DispatchBeforeUnload(bool for_navigation, bool is_reload);
+
+ // Simulate beforeunload ack on behalf of renderer if it's unrenresponsive.
+ void SimulateBeforeUnloadAck();
// Returns true if a call to DispatchBeforeUnload will actually send the
// BeforeUnload IPC. This is the case if the current renderer is live and this
@@ -478,14 +511,16 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
no_create_browser_accessibility_manager_for_testing_ = flag;
}
+#if defined(USE_EXTERNAL_POPUP_MENU)
#if defined(OS_MACOSX)
// Select popup menu related methods (for external popup menus).
void DidSelectPopupMenuItem(int selected_index);
void DidCancelPopupMenu();
-#elif defined(OS_ANDROID)
+#else
void DidSelectPopupMenuItems(const std::vector<int>& selected_indices);
void DidCancelPopupMenu();
#endif
+#endif
// PlzNavigate: Indicates that a navigation is ready to commit and can be
// handled by this RenderFrame.
@@ -586,6 +621,8 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
RenderViewInitAfterNewProxyAndProcessKill);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest,
UnloadPushStateOnCrossProcessNavigation);
+ FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest,
+ WebUIJavascriptDisallowedAfterSwapOut);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrashSubframe);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
RenderViewHostIsNotReusedAfterDelayedSwapOutACK);
@@ -630,6 +667,7 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
void OnRunBeforeUnloadConfirm(const GURL& frame_url,
bool is_reload,
IPC::Message* reply_msg);
+ void OnRunFileChooser(const FileChooserParams& params);
void OnTextSurroundingSelectionResponse(const base::string16& content,
uint32_t start_offset,
uint32_t end_offset);
@@ -637,20 +675,19 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
void OnDidChangeOpener(int32_t opener_routing_id);
void OnDidChangeName(const std::string& name, const std::string& unique_name);
void OnDidAddContentSecurityPolicy(const ContentSecurityPolicyHeader& header);
- void OnEnforceStrictMixedContentChecking();
+ 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,
- const blink::WebFrameOwnerProperties& frame_owner_properties);
+ const blink::WebFrameOwnerProperties& properties);
void OnUpdateTitle(const base::string16& title,
blink::WebTextDirection title_direction);
void OnUpdateEncoding(const std::string& encoding);
void OnBeginNavigation(const CommonNavigationParams& common_params,
- const BeginNavigationParams& begin_params,
- scoped_refptr<ResourceRequestBody> body);
+ const BeginNavigationParams& begin_params);
void OnDispatchLoad();
void OnAccessibilityEvents(
const std::vector<AccessibilityHostMsg_EventParams>& params,
@@ -673,13 +710,13 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
bool success,
const std::set<std::string>& digests_of_uris_of_serialized_resources);
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params);
void OnHidePopup();
#endif
- // Registers Mojo services that this frame host makes available.
- void RegisterMojoServices();
+ // Registers Mojo interfaces that this frame host makes available.
+ void RegisterMojoInterfaces();
// Resets any waiting state of this RenderFrameHost that is no longer
// relevant.
@@ -705,6 +742,23 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
// Informs the content client that geolocation permissions were used.
void DidUseGeolocationPermission();
+ // Returns whether the current RenderProcessHost has read access to all the
+ // files reported in |state|.
+ bool CanAccessFilesOfPageState(const PageState& state);
+
+ // Grants the current RenderProcessHost read access to any file listed in
+ // |validated_state|. It is important that the PageState has been validated
+ // upon receipt from the renderer process to prevent it from forging access to
+ // files without the user's consent.
+ void GrantFileAccessFromPageState(const PageState& validated_state);
+
+ // Grants the current RenderProcessHost read access to any file listed in
+ // |body|. It is important that the ResourceRequestBody has been validated
+ // upon receipt from the renderer process to prevent it from forging access to
+ // files without the user's consent.
+ void GrantFileAccessFromResourceRequestBody(
+ const ResourceRequestBodyImpl& body);
+
void UpdatePermissionsForNavigation(
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params);
@@ -807,6 +861,12 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
// The FrameTreeNode which this RenderFrameHostImpl is hosted in.
FrameTreeNode* frame_tree_node_;
+ // The active parent RenderFrameHost for this frame, if it is a subframe.
+ // Null for the main frame. This is cached because the parent FrameTreeNode
+ // may change its current RenderFrameHost while this child is pending
+ // deletion, and GetParent() should never return a different value.
+ RenderFrameHostImpl* parent_;
+
// Track this frame's last committed URL.
GURL last_committed_url_;
@@ -894,7 +954,8 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
// SiteInstance. May be null in tests.
std::unique_ptr<TimeoutMonitor> swapout_event_monitor_timeout_;
- std::unique_ptr<ServiceRegistryImpl> service_registry_;
+ std::unique_ptr<shell::InterfaceRegistry> interface_registry_;
+ std::unique_ptr<shell::InterfaceProvider> remote_interfaces_;
#if defined(OS_ANDROID)
std::unique_ptr<ServiceRegistryAndroid> service_registry_android_;
@@ -975,6 +1036,9 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
// same LoFi status as the top-level frame.
LoFiState last_navigation_lofi_state_;
+ mojo::Binding<mojom::FrameHost> frame_host_binding_;
+ mojom::FramePtr frame_;
+
// 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 60be8217a56..5380f6e3350 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -199,7 +199,8 @@ void RenderFrameHostManager::RemoveOuterDelegateFrame() {
RenderFrameHostImpl* RenderFrameHostManager::Navigate(
const GURL& dest_url,
const FrameNavigationEntry& frame_entry,
- const NavigationEntryImpl& entry) {
+ const NavigationEntryImpl& entry,
+ bool is_reload) {
TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate",
"FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
// Create a pending RenderFrameHost to use for the navigation.
@@ -208,7 +209,7 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate(
entry.GetTransitionType(),
entry.restore_type() != NavigationEntryImpl::RESTORE_NONE,
entry.IsViewSourceMode(), entry.transferred_global_request_id(),
- entry.bindings());
+ entry.bindings(), is_reload);
if (!dest_render_frame_host)
return nullptr; // We weren't able to create a pending render frame host.
@@ -231,9 +232,9 @@ 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 ServiceRegistry 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 a service to this RFH's ServiceRegistry).
+ // RFH's shell::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();
// Recreate the opener chain.
@@ -486,9 +487,12 @@ void RenderFrameHostManager::OnCrossSiteResponse(
transferring_render_frame_host->frame_tree_node()
->navigator()
- ->RequestTransferURL(transferring_render_frame_host, transfer_url,
- nullptr, rest_of_chain, referrer, page_transition,
- global_request_id, should_replace_current_entry);
+ ->RequestTransferURL(
+ transferring_render_frame_host, transfer_url, nullptr, rest_of_chain,
+ 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.
@@ -961,14 +965,44 @@ void RenderFrameHostManager::OnDidResetContentSecurityPolicy() {
}
}
-void RenderFrameHostManager::OnEnforceStrictMixedContentChecking(
- bool should_enforce) {
+void RenderFrameHostManager::OnEnforceInsecureRequestPolicy(
+ blink::WebInsecureRequestPolicy policy) {
if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
return;
for (const auto& pair : proxy_hosts_) {
- pair.second->Send(new FrameMsg_EnforceStrictMixedContentChecking(
- pair.second->GetRoutingID(), should_enforce));
+ pair.second->Send(new FrameMsg_EnforceInsecureRequestPolicy(
+ pair.second->GetRoutingID(), policy));
+ }
+}
+
+void RenderFrameHostManager::OnDidUpdateFrameOwnerProperties(
+ const blink::WebFrameOwnerProperties& properties) {
+ if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
+ return;
+
+ // WebFrameOwnerProperties exist only for frames that have a parent.
+ CHECK(frame_tree_node_->parent());
+ SiteInstance* parent_instance =
+ frame_tree_node_->parent()->current_frame_host()->GetSiteInstance();
+
+ // Notify the RenderFrame if it lives in a different process from its parent.
+ if (render_frame_host_->GetSiteInstance() != parent_instance) {
+ render_frame_host_->Send(new FrameMsg_SetFrameOwnerProperties(
+ render_frame_host_->GetRoutingID(), properties));
+ }
+
+ // Notify this frame's proxies if they live in a different process from its
+ // parent. This is only currently needed for the allowFullscreen property,
+ // since that can be queried on RemoteFrame ancestors.
+ //
+ // TODO(alexmos): It would be sufficient to only send this update to proxies
+ // in the current FrameTree.
+ for (const auto& pair : proxy_hosts_) {
+ if (pair.second->GetSiteInstance() != parent_instance) {
+ pair.second->Send(new FrameMsg_SetFrameOwnerProperties(
+ pair.second->GetRoutingID(), properties));
+ }
}
}
@@ -1734,7 +1768,8 @@ int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
if (!render_view_host) {
CHECK(frame_tree_node_->IsMainFrame());
render_view_host = frame_tree_node_->frame_tree()->CreateRenderViewHost(
- instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, true, true);
+ instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, true,
+ delegate_->IsHidden());
}
RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
@@ -2139,7 +2174,8 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
bool dest_is_restore,
bool dest_is_view_source_mode,
const GlobalRequestID& transferred_request_id,
- int bindings) {
+ int bindings,
+ bool is_reload) {
if (!frame_tree_node_->IsMainFrame() &&
!CanSubframeSwapProcess(dest_url, source_instance, dest_instance)) {
// Note: Do not add code here to determine whether the subframe should swap
@@ -2215,14 +2251,14 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
// a timeout). If the handler returns false, we'll have to cancel the
// request.
//
- // Also make sure the old render view stops, in case a load is in
+ // Also make sure the old RenderFrame stops, in case a load is in
// progress. (We don't want to do this for transfers, since it will
// interrupt the transfer with an unexpected DidStopLoading.)
render_frame_host_->Send(new FrameMsg_Stop(
render_frame_host_->GetRoutingID()));
pending_render_frame_host_->SetNavigationsSuspended(true,
base::TimeTicks());
- render_frame_host_->DispatchBeforeUnload(true);
+ render_frame_host_->DispatchBeforeUnload(true, is_reload);
}
return pending_render_frame_host_.get();
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 e40a9263f2d..b875761d9a1 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.h
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.h
@@ -269,7 +269,8 @@ class CONTENT_EXPORT RenderFrameHostManager
// different URL than the last committed entry, without modifying it).
RenderFrameHostImpl* Navigate(const GURL& dest_url,
const FrameNavigationEntry& frame_entry,
- const NavigationEntryImpl& entry);
+ const NavigationEntryImpl& entry,
+ bool is_reload);
// Instructs the various live views to stop. Called when the user directed the
// page to stop loading.
@@ -435,9 +436,16 @@ class CONTENT_EXPORT RenderFrameHostManager
// Resets Content Security Policy in all the proxies.
void OnDidResetContentSecurityPolicy();
- // Sends updated enforcement of strict mixed content checking to all
- // frame proxies when the frame changes its setting.
- void OnEnforceStrictMixedContentChecking(bool should_enforce);
+ // Sends updated enforcement of insecure request policy to all frame proxies
+ // when the frame changes its setting.
+ void OnEnforceInsecureRequestPolicy(blink::WebInsecureRequestPolicy policy);
+
+ // Called on a frame to notify it that its out-of-process parent frame
+ // changed a property (such as allowFullscreen) on its <iframe> element.
+ // Sends updated WebFrameOwnerProperties to the RenderFrame and to all
+ // proxies, skipping the parent process.
+ void OnDidUpdateFrameOwnerProperties(
+ const blink::WebFrameOwnerProperties& properties);
// Send updated origin to all frame proxies when the frame navigates to a new
// origin.
@@ -722,7 +730,8 @@ class CONTENT_EXPORT RenderFrameHostManager
bool dest_is_restore,
bool dest_is_view_source_mode,
const GlobalRequestID& transferred_request_id,
- int bindings);
+ int bindings,
+ bool is_reload);
// Updates the pending WebUI of the current RenderFrameHost for a same-site
// navigation.
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 ae972e8f4b9..41740c4247b 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
@@ -5,6 +5,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <set>
#include "base/command_line.h"
@@ -34,11 +35,10 @@
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_ui_message_handler.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/file_chooser_file_info.h"
-#include "content/public/common/file_chooser_params.h"
#include "content/public/common/page_state.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
@@ -75,6 +75,58 @@ void OpenUrlViaClickTarget(const ToRenderFrameHost& adapter, const GURL& url) {
std::string(kOpenUrlViaClickTargetFunc) + "(\"" + url.spec() + "\");"));
}
+class TestWebUIMessageHandler : public WebUIMessageHandler {
+ public:
+ using WebUIMessageHandler::AllowJavascript;
+ using WebUIMessageHandler::IsJavascriptAllowed;
+
+ protected:
+ void RegisterMessages() override {}
+};
+
+// This class implements waiting for RenderFrameHost destruction. It relies on
+// the fact that RenderFrameDeleted event is fired when RenderFrameHost is
+// destroyed.
+// Note: RenderFrameDeleted is also fired when the process associated with the
+// RenderFrameHost crashes, so this cannot be used in cases where process dying
+// is expected.
+class RenderFrameHostDestructionObserver : public WebContentsObserver {
+ public:
+ explicit RenderFrameHostDestructionObserver(RenderFrameHost* rfh)
+ : WebContentsObserver(WebContents::FromRenderFrameHost(rfh)),
+ message_loop_runner_(new MessageLoopRunner),
+ deleted_(false),
+ render_frame_host_(rfh) {}
+ ~RenderFrameHostDestructionObserver() override {}
+
+ bool deleted() const { return deleted_; }
+
+ void Wait() {
+ if (deleted_)
+ return;
+
+ message_loop_runner_->Run();
+ }
+
+ // WebContentsObserver implementation:
+ void RenderFrameDeleted(RenderFrameHost* rfh) override {
+ if (rfh == render_frame_host_) {
+ CHECK(!deleted_);
+ deleted_ = true;
+ }
+
+ if (deleted_ && message_loop_runner_->loop_running()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, message_loop_runner_->QuitClosure());
+ }
+ }
+
+ private:
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+ bool deleted_;
+ RenderFrameHost* render_frame_host_;
+};
+
} // anonymous namespace
class RenderFrameHostManagerTest : public ContentBrowserTest {
@@ -125,7 +177,7 @@ class RenderFrameHostManagerTest : public ContentBrowserTest {
// links that initially look same-site.
std::string script = "setOriginForLinks('http://bar.com:" +
embedded_test_server()->base_url().port() + "/');";
- EXPECT_TRUE(ExecuteScript(shell->web_contents(), script));
+ EXPECT_TRUE(ExecuteScript(shell, script));
}
protected:
@@ -150,7 +202,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, NoScriptAccessAfterSwapOut) {
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteTargetedLink());",
&success));
EXPECT_TRUE(success);
@@ -167,7 +219,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, NoScriptAccessAfterSwapOut) {
// We should have access to the opened window's location.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(testScriptAccessToWindow());",
&success));
EXPECT_TRUE(success);
@@ -182,7 +234,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, NoScriptAccessAfterSwapOut) {
// We should no longer have script access to the opened window's location.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(testScriptAccessToWindow());",
&success));
EXPECT_FALSE(success);
@@ -190,8 +242,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, NoScriptAccessAfterSwapOut) {
// We now navigate the window to an about:blank page.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(clickBlankTargetedLink());",
+ shell(), "window.domAutomationController.send(clickBlankTargetedLink());",
&success));
EXPECT_TRUE(success);
@@ -205,7 +256,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, NoScriptAccessAfterSwapOut) {
// We should have access to the opened window's location.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(testScriptAccessToWindow());",
&success));
EXPECT_TRUE(success);
@@ -228,7 +279,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickNoRefTargetBlankLink());",
&success));
EXPECT_TRUE(success);
@@ -241,8 +292,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Check that `window.opener` is not set.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell->web_contents(),
- "window.domAutomationController.send(window.opener == null);", &success));
+ new_shell, "window.domAutomationController.send(window.opener == null);",
+ &success));
EXPECT_TRUE(success);
// Wait for the cross-site transition in the new tab to finish.
@@ -260,7 +311,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Same as above, but for 'noopener'
IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
- SwapProcessWithRelNopenerAndTargetBlank) {
+ SwapProcessWithRelNoopenerAndTargetBlank) {
StartEmbeddedServer();
NavigateToPageWithLinks(shell());
@@ -274,7 +325,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickNoOpenerTargetBlankLink());",
&success));
EXPECT_TRUE(success);
@@ -287,8 +338,18 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Check that `window.opener` is not set.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell->web_contents(),
- "window.domAutomationController.send(window.opener == null);", &success));
+ new_shell, "window.domAutomationController.send(window.opener == null);",
+ &success));
+ EXPECT_TRUE(success);
+
+ // Check that the referrer is set correctly.
+ std::string expected_referrer =
+ embedded_test_server()->GetURL("/click-noreferrer-links.html").spec();
+ success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ new_shell, "window.domAutomationController.send(document.referrer == '" +
+ expected_referrer + "');",
+ &success));
EXPECT_TRUE(success);
// Wait for the cross-site transition in the new tab to finish.
@@ -320,7 +381,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool hasWindowReference = true;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
" openWindowWithTargetAndFeatures('/title2.html', '', 'noopener')"
");",
@@ -344,8 +405,18 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Check that `window.opener` is not set.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell->web_contents(),
- "window.domAutomationController.send(window.opener == null);", &success));
+ new_shell, "window.domAutomationController.send(window.opener == null);",
+ &success));
+ EXPECT_TRUE(success);
+
+ // Check that the referrer is set correctly.
+ std::string expected_referrer =
+ embedded_test_server()->GetURL("/click-noreferrer-links.html").spec();
+ success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ new_shell, "window.domAutomationController.send(document.referrer == '" +
+ expected_referrer + "');",
+ &success));
EXPECT_TRUE(success);
// Should have a new SiteInstance.
@@ -373,7 +444,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteNoRefTargetedLink());",
&success));
EXPECT_TRUE(success);
@@ -387,8 +458,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Check that `window.opener` is not set.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell->web_contents(),
- "window.domAutomationController.send(window.opener == null);", &success));
+ new_shell, "window.domAutomationController.send(window.opener == null);",
+ &success));
EXPECT_TRUE(success);
// Wait for the cross-site transition in the new tab to finish.
@@ -420,7 +491,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Test clicking a same-site rel=noopener + target=foo link.
ShellAddedObserver new_shell_observer;
bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(shell()->web_contents(),
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(shell(),
"window.domAutomationController.send("
"clickSameSiteNoOpenerTargetedLink())"
";",
@@ -436,8 +507,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Check that `window.opener` is not set.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell->web_contents(),
- "window.domAutomationController.send(window.opener == null);", &success));
+ new_shell, "window.domAutomationController.send(window.opener == null);",
+ &success));
EXPECT_TRUE(success);
// Wait for the cross-site transition in the new tab to finish.
@@ -472,8 +543,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(clickTargetBlankLink());",
+ shell(), "window.domAutomationController.send(clickTargetBlankLink());",
&success));
EXPECT_TRUE(success);
@@ -511,8 +581,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Test clicking a rel=noreferrer link.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(clickNoRefLink());", &success));
+ shell(), "window.domAutomationController.send(clickNoRefLink());",
+ &success));
EXPECT_TRUE(success);
// Wait for the cross-site transition in the current tab to finish.
@@ -548,8 +618,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Test clicking a rel=noreferrer link.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(clickNoRefLink());",
+ shell(), "window.domAutomationController.send(clickNoRefLink());",
&success));
EXPECT_TRUE(success);
@@ -588,7 +657,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteTargetedLink());",
&success));
EXPECT_TRUE(success);
@@ -615,7 +684,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Clicking the original link in the first tab should cause us to swap back.
TestNavigationObserver navigation_observer(new_shell->web_contents());
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteTargetedLink());",
&success));
EXPECT_TRUE(success);
@@ -633,8 +702,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
new_shell->web_contents()->GetSiteInstance());
WebContentsDestroyedWatcher close_watcher(new_shell->web_contents());
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(testCloseWindow());",
+ shell(), "window.domAutomationController.send(testCloseWindow());",
&success));
EXPECT_TRUE(success);
close_watcher.Wait();
@@ -663,7 +731,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteTargetBlankLink());",
&success));
EXPECT_TRUE(success);
@@ -690,8 +758,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
EXPECT_TRUE(new_shell->web_contents()->HasOpener());
// Now disown the opener.
- EXPECT_TRUE(ExecuteScript(new_shell->web_contents(),
- "window.opener = null;"));
+ EXPECT_TRUE(ExecuteScript(new_shell, "window.opener = null;"));
EXPECT_FALSE(new_shell->web_contents()->HasOpener());
// Go back and ensure the opener is still null.
@@ -702,8 +769,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
}
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell->web_contents(),
- "window.domAutomationController.send(window.opener == null);",
+ new_shell, "window.domAutomationController.send(window.opener == null);",
&success));
EXPECT_TRUE(success);
EXPECT_FALSE(new_shell->web_contents()->HasOpener());
@@ -712,8 +778,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
NavigateToURL(new_shell, cross_site_url);
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell->web_contents(),
- "window.domAutomationController.send(window.opener == null);",
+ new_shell, "window.domAutomationController.send(window.opener == null);",
&success));
EXPECT_TRUE(success);
EXPECT_FALSE(new_shell->web_contents()->HasOpener());
@@ -725,8 +790,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, DisownSubframeOpener) {
NavigateToURL(shell(), frame_url);
// Give the frame an opener using window.open.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.open('about:blank','foo');"));
+ EXPECT_TRUE(ExecuteScript(shell(), "window.open('about:blank','foo');"));
// Check that the browser process updates the subframe's opener.
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
@@ -735,8 +799,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, DisownSubframeOpener) {
EXPECT_EQ(root, root->child_at(0)->opener());
// Now disown the frame's opener. Shouldn't crash.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.frames[0].opener = null;"));
+ EXPECT_TRUE(ExecuteScript(shell(), "window.frames[0].opener = null;"));
// Check that the subframe's opener in the browser process is disowned.
EXPECT_EQ(nullptr, root->child_at(0)->opener());
@@ -757,15 +820,13 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_TRUE(orig_site_instance.get() != NULL);
// Open a popup using window.open with a 'foo' window.name.
- Shell* new_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ Shell* new_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
EXPECT_TRUE(new_shell);
// The window.name for the new popup should be "foo".
std::string name;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- new_shell->web_contents(),
- "window.domAutomationController.send(window.name);", &name));
+ new_shell, "window.domAutomationController.send(window.name);", &name));
EXPECT_EQ("foo", name);
// Now navigate the new tab to a different site.
@@ -778,13 +839,11 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// window.name should still be "foo".
name = "";
EXPECT_TRUE(ExecuteScriptAndExtractString(
- new_shell->web_contents(),
- "window.domAutomationController.send(window.name);", &name));
+ new_shell, "window.domAutomationController.send(window.name);", &name));
EXPECT_EQ("foo", name);
// Open another popup from the 'foo' popup and navigate it cross-site.
- Shell* new_shell2 =
- OpenPopup(new_shell->web_contents(), GURL(url::kAboutBlankURL), "bar");
+ Shell* new_shell2 = OpenPopup(new_shell, GURL(url::kAboutBlankURL), "bar");
EXPECT_TRUE(new_shell2);
GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title3.html"));
EXPECT_TRUE(NavigateToURL(new_shell2, bar_url));
@@ -794,7 +853,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// be done via window.open, since window.name isn't readable cross-origin.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell2->web_contents(),
+ new_shell2,
"window.domAutomationController.send("
" window.opener === window.open('','foo'));",
&success));
@@ -853,7 +912,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Second, a target=_blank window.
ShellAddedObserver new_shell_observer2;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteTargetBlankLink());",
&success));
EXPECT_TRUE(success);
@@ -1073,8 +1132,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// The opened tab should be able to navigate the opener back to its process.
TestNavigationObserver navigation_observer(orig_contents);
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell->web_contents(),
- "window.domAutomationController.send(navigateOpener());",
+ new_shell, "window.domAutomationController.send(navigateOpener());",
&success));
EXPECT_TRUE(success);
navigation_observer.Wait();
@@ -1110,8 +1168,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_EQ(frame_url, root->child_at(0)->current_url());
// Register an unload handler that sends a postMessage to the top frame.
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
- "registerUnload();"));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), "registerUnload();"));
// Navigate the top frame cross-site. This will cause the top frame to be
// swapped out and run unload handlers, and the original renderer process
@@ -1149,7 +1206,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteTargetedLink());",
&success));
EXPECT_TRUE(success);
@@ -1220,8 +1277,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ClickLinkAfter204Error) {
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
GURL url = embedded_test_server()->GetURL("/title2.html");
EXPECT_TRUE(ExecuteScript(
- shell()->web_contents(),
- base::StringPrintf("location.href = '%s'", url.spec().c_str())));
+ shell(), base::StringPrintf("location.href = '%s'", url.spec().c_str())));
ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
// Opens in same tab.
@@ -1522,9 +1578,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(openWindow());",
- &success));
+ shell(), "window.domAutomationController.send(openWindow());", &success));
EXPECT_TRUE(success);
Shell* new_shell = new_shell_observer.GetShell();
@@ -1763,7 +1817,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, WebUIGetsBindings) {
TestNavigationObserver nav_observer(NULL);
nav_observer.StartWatchingNewWebContents();
ShellAddedObserver shao;
- OpenUrlViaClickTarget(shell()->web_contents(), url2);
+ OpenUrlViaClickTarget(shell(), url2);
nav_observer.Wait();
Shell* new_shell = shao.GetShell();
WebContentsImpl* new_web_contents = static_cast<WebContentsImpl*>(
@@ -1817,30 +1871,63 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
shell()->web_contents()->GetRenderProcessHost()->GetID()));
}
-class FileChooserDelegate : public WebContentsDelegate {
- public:
- FileChooserDelegate(const base::FilePath& file)
- : file_(file), file_chosen_(false) {}
-
- void RunFileChooser(WebContents* web_contents,
- const FileChooserParams& params) override {
- // Send the selected file to the renderer process.
- FileChooserFileInfo file_info;
- file_info.file_path = file_;
- std::vector<FileChooserFileInfo> files;
- files.push_back(file_info);
- web_contents->GetRenderViewHost()->FilesSelectedInChooser(
- files, FileChooserParams::Open);
-
- file_chosen_ = true;
- }
+// crbug.com/615274
+// This test ensures that after an RFH is swapped out, the associated WebUI
+// instance is no longer allowed to send JavaScript messages. This is necessary
+// because WebUI currently (and unusually) always sends JavaScript messages to
+// the current main frame, rather than the RFH that owns the WebUI.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ WebUIJavascriptDisallowedAfterSwapOut) {
+ StartEmbeddedServer();
- bool file_chosen() { return file_chosen_; }
+ const GURL web_ui_url(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost));
+ EXPECT_TRUE(NavigateToURL(shell(), web_ui_url));
- private:
- base::FilePath file_;
- bool file_chosen_;
-};
+ RenderFrameHostImpl* rfh =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->GetMainFrame();
+
+ // Set up a slow unload handler to force the RFH to linger in the swapped
+ // out but not-yet-deleted state.
+ EXPECT_TRUE(
+ ExecuteScript(rfh, "window.onunload=function(e){ while(1); };\n"));
+
+ WebUIImpl* web_ui = rfh->web_ui();
+
+ EXPECT_TRUE(web_ui->CanCallJavascript());
+ TestWebUIMessageHandler* handler = new TestWebUIMessageHandler();
+
+ web_ui->AddMessageHandler(handler);
+ EXPECT_FALSE(handler->IsJavascriptAllowed());
+
+ handler->AllowJavascript();
+ EXPECT_TRUE(handler->IsJavascriptAllowed());
+
+ rfh->DisableSwapOutTimerForTesting();
+ RenderFrameHostDestructionObserver rfh_observer(rfh);
+
+ // Navigate, but wait for commit, not the actual load to finish.
+ SiteInstanceImpl* web_ui_site_instance = rfh->GetSiteInstance();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ TestFrameNavigationObserver commit_observer(root);
+ shell()->LoadURL(GURL(url::kAboutBlankURL));
+ commit_observer.WaitForCommit();
+ EXPECT_NE(web_ui_site_instance, shell()->web_contents()->GetSiteInstance());
+ EXPECT_TRUE(
+ root->render_manager()->GetRenderFrameProxyHost(web_ui_site_instance));
+
+ // The previous RFH should still be pending deletion, as we wait for either
+ // the SwapOut ACK or a timeout.
+ ASSERT_TRUE(rfh->IsRenderFrameLive());
+ ASSERT_FALSE(rfh->is_active());
+
+ // We specifically want verify behavior between swap-out and RFH destruction.
+ ASSERT_FALSE(rfh_observer.deleted());
+
+ EXPECT_FALSE(handler->IsJavascriptAllowed());
+}
// Test for http://crbug.com/262948.
IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
@@ -1856,8 +1943,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
std::unique_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file));
shell()->web_contents()->SetDelegate(delegate.get());
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "document.getElementById('fileinput').click();"));
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "document.getElementById('fileinput').click();"));
EXPECT_TRUE(delegate->file_chosen());
EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
process_id, file));
@@ -1919,7 +2006,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
std::unique_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file));
shell()->web_contents()->SetDelegate(delegate.get());
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
"document.getElementById('fileinput').click();"));
EXPECT_TRUE(delegate->file_chosen());
EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
@@ -1928,6 +2015,18 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Disable the swap out timer so we wait for the UpdateState message.
root->current_frame_host()->DisableSwapOutTimerForTesting();
+ // Do an in-page navigation in the child to make sure we hear a PageState with
+ // the chosen file before the subframe's FrameTreeNode is deleted. In
+ // practice, we'll get the PageState 1 second after the file is chosen.
+ // TODO(creis): Remove this in-page navigation once we keep track of
+ // FrameTreeNodes that are pending deletion. See https://crbug.com/609963.
+ {
+ TestNavigationObserver nav_observer(shell()->web_contents());
+ std::string script = "location.href='#foo';";
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
+ nav_observer.Wait();
+ }
+
// Navigate to a different process without access to the file, and wait for
// the old process to exit.
RenderProcessHostWatcher exit_observer(
@@ -1949,7 +2048,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Go back, ending up in a different RenderProcessHost than before.
TestNavigationObserver back_nav_load_observer(shell()->web_contents());
- shell()->web_contents()->GetController().GoBack();
+ shell()->web_contents()->GetController().GoToIndex(0);
back_nav_load_observer.Wait();
EXPECT_NE(process_id,
shell()->web_contents()->GetRenderProcessHost()->GetID());
@@ -1959,47 +2058,6 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
}
-// This class implements waiting for RenderFrameHost destruction. It relies on
-// the fact that RenderFrameDeleted event is fired when RenderFrameHost is
-// destroyed.
-// Note: RenderFrameDeleted is also fired when the process associated with the
-// RenderFrameHost crashes, so this cannot be used in cases where process dying
-// is expected.
-class RenderFrameHostDestructionObserver : public WebContentsObserver {
- public:
- explicit RenderFrameHostDestructionObserver(RenderFrameHost* rfh)
- : WebContentsObserver(WebContents::FromRenderFrameHost(rfh)),
- message_loop_runner_(new MessageLoopRunner),
- deleted_(false),
- render_frame_host_(rfh) {}
- ~RenderFrameHostDestructionObserver() override {}
-
- void Wait() {
- if (deleted_)
- return;
-
- message_loop_runner_->Run();
- }
-
- // WebContentsObserver implementation:
- void RenderFrameDeleted(RenderFrameHost* rfh) override {
- if (rfh == render_frame_host_) {
- CHECK(!deleted_);
- deleted_ = true;
- }
-
- if (deleted_ && message_loop_runner_->loop_running()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, message_loop_runner_->QuitClosure());
- }
- }
-
- private:
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
- bool deleted_;
- RenderFrameHost* render_frame_host_;
-};
-
// Ensures that no RenderFrameHost/RenderViewHost objects are leaked when
// doing a simple cross-process navigation.
IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
@@ -2053,8 +2111,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_TRUE(orig_site_instance);
// Open a popup and navigate it cross-site.
- Shell* new_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ Shell* new_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
EXPECT_TRUE(new_shell);
FrameTreeNode* popup_root =
static_cast<WebContentsImpl*>(new_shell->web_contents())
@@ -2119,15 +2176,14 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, UpdateOpener) {
EXPECT_TRUE(orig_site_instance);
// Open a cross-site popup named "foo" and a same-site popup named "bar".
- Shell* foo_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ Shell* foo_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
EXPECT_TRUE(foo_shell);
GURL foo_url(embedded_test_server()->GetURL("foo.com", "/post_message.html"));
NavigateToURL(foo_shell, foo_url);
GURL bar_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_post_message_frames.html"));
- Shell* bar_shell = OpenPopup(shell()->web_contents(), bar_url, "bar");
+ Shell* bar_shell = OpenPopup(shell(), bar_url, "bar");
EXPECT_TRUE(bar_shell);
EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
@@ -2153,7 +2209,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, UpdateOpener) {
// target frame without navigating it.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- bar_shell->web_contents(),
+ bar_shell,
"window.domAutomationController.send(!!window.open('','foo'));",
&success));
EXPECT_TRUE(success);
@@ -2169,7 +2225,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, UpdateOpener) {
TitleWatcher title_watcher(bar_shell->web_contents(), expected_title);
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- foo_shell->web_contents(),
+ foo_shell,
"window.domAutomationController.send(postToOpener('opener-msg', '*'));",
&success));
EXPECT_TRUE(success);
@@ -2177,8 +2233,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, UpdateOpener) {
// Check that a non-null assignment to the opener doesn't change the opener
// in the browser process.
- EXPECT_TRUE(
- ExecuteScript(foo_shell->web_contents(), "window.opener = window;"));
+ EXPECT_TRUE(ExecuteScript(foo_shell, "window.opener = window;"));
EXPECT_EQ(bar_root, foo_root->opener());
}
@@ -2196,7 +2251,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteTargetedLink());",
&success));
EXPECT_TRUE(success);
@@ -2211,8 +2266,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Capture the window reference, so we can check that accessing its location
// works after navigating cross-process and back.
GURL expected_url = new_shell->web_contents()->GetLastCommittedURL();
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "saveWindowReference();"));
+ EXPECT_TRUE(ExecuteScript(shell(), "saveWindowReference();"));
// Now navigate the popup to a different site and then go back.
NavigateToURL(new_shell,
@@ -2224,7 +2278,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Check that the location.href window attribute is accessible and is correct.
std::string result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(getLastOpenedWindowLocation());",
&result));
EXPECT_EQ(expected_url.spec(), result);
@@ -2244,8 +2298,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
NavigateToURL(shell(), main_url);
// Open a popup to navigate.
- Shell* new_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ Shell* new_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
new_shell->web_contents()->GetSiteInstance());
@@ -2278,8 +2331,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
// Open a popup to navigate cross-process.
- Shell* new_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ Shell* new_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
new_shell->web_contents()->GetSiteInstance());
@@ -2326,8 +2378,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
// Open a popup to navigate.
- Shell* new_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ Shell* new_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
FrameTreeNode* popup_root =
static_cast<WebContentsImpl*>(new_shell->web_contents())
->GetFrameTree()
@@ -2370,12 +2421,11 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Give an initial page an unload handler that never completes.
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(),
- "window.onunload=function(e){ while(1); };\n"));
+ EXPECT_TRUE(
+ ExecuteScript(root, "window.onunload=function(e){ while(1); };\n"));
// Open a popup in the same process.
- Shell* new_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ Shell* new_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
FrameTreeNode* popup_root =
static_cast<WebContentsImpl*>(new_shell->web_contents())
->GetFrameTree()
@@ -2451,8 +2501,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Give an initial page an unload handler that never completes.
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(),
- "window.onunload=function(e){ while(1); };\n"));
+ EXPECT_TRUE(
+ ExecuteScript(root, "window.onunload=function(e){ while(1); };\n"));
// Navigate the tab to a different site, and only wait for commit, not load
// stop.
@@ -2474,8 +2524,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(site_instance_a));
// Open a popup in the new B process.
- Shell* new_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ Shell* new_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "foo");
EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
new_shell->web_contents()->GetSiteInstance());
@@ -2518,8 +2567,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
// Open a popup and navigate it to b.com to keep the b.com process alive.
- Shell* new_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "popup");
+ Shell* new_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "popup");
NavigateToURL(new_shell,
embedded_test_server()->GetURL("b.com", "/title3.html"));
@@ -2586,7 +2634,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
"var frame = document.createElement('iframe');\n"
"frame.sandbox = 'allow-scripts allow-popups';\n"
"document.body.appendChild(frame);\n";
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+ EXPECT_TRUE(ExecuteScript(shell(), script));
}
// Navigate iframe to a page with target=_blank links, and rewrite the links
@@ -2596,7 +2644,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
NavigateFrameToURL(root->child_at(0), frame_url);
std::string script = "setOriginForLinks('http://b.com:" +
embedded_test_server()->base_url().port() + "/');";
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
// Helper to click on the 'rel=noreferrer target=_blank' and 'rel=noopener
// target=_blank' links. Checks that these links open a popup that ends up
@@ -2607,7 +2655,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0)->current_frame_host(),
+ root->child_at(0),
"window.domAutomationController.send(" + link_opening_script + ")",
&success));
EXPECT_TRUE(success);
@@ -2621,8 +2669,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// should be unique.
std::string origin;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- new_shell->web_contents(),
- "domAutomationController.send(document.origin)", &origin));
+ new_shell, "domAutomationController.send(document.origin)", &origin));
EXPECT_EQ("null", origin);
};
@@ -2649,7 +2696,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ShellAddedObserver new_shell_observer;
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteTargetedLink());"
"saveWindowReference();",
&success));
@@ -2680,7 +2727,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
std::string result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send((function() {\n"
" try {\n"
" return getLastOpenedWindowLocation();\n"
@@ -2714,9 +2761,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, CtrlClickSubframeLink) {
// Simulate a ctrl click on the link. This won't actually create a new Shell
// because Shell::OpenURLFromTab only supports CURRENT_TAB, but it's enough to
// trigger the crash from https://crbug.com/605055.
- EXPECT_TRUE(
- ExecuteScript(shell()->web_contents(),
- "window.domAutomationController.send(ctrlClickLink());"));
+ EXPECT_TRUE(ExecuteScript(
+ shell(), "window.domAutomationController.send(ctrlClickLink());"));
}
// Ensure that we don't update the wrong NavigationEntry's title after an
@@ -2734,7 +2780,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// meant for a NavigationEntry that will never be created.
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("a.com", "/title2.html")));
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(),
+ EXPECT_TRUE(ExecuteScript(root,
"window.onunload=function(e){"
"history.pushState({}, 'foo', 'foo');"
"document.title='foo'; };\n"));
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 306710c0b88..caea1bee9c1 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
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include <tuple>
#include <utility>
#include "base/command_line.h"
@@ -16,7 +17,6 @@
#include "base/test/histogram_tester.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "content/browser/compositor/test/no_transport_image_transport_factory.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"
@@ -54,6 +54,7 @@
#include "content/test/test_web_contents.h"
#include "net/base/load_flags.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
#include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
#include "ui/base/page_transition_types.h"
@@ -72,22 +73,22 @@ void VerifyPageFocusMessage(MockRenderProcessHost* rph,
EXPECT_EQ(expected_routing_id, message->routing_id());
InputMsg_SetFocus::Param params;
EXPECT_TRUE(InputMsg_SetFocus::Read(message, &params));
- EXPECT_EQ(expected_focus, base::get<0>(params));
+ EXPECT_EQ(expected_focus, std::get<0>(params));
}
// Helper function for strict mixed content checking tests.
-void CheckMixedContentIPC(TestRenderFrameHost* rfh,
- bool expected_param,
- int expected_routing_id) {
+void CheckInsecureRequestPolicyIPC(
+ TestRenderFrameHost* rfh,
+ blink::WebInsecureRequestPolicy expected_param,
+ int expected_routing_id) {
const IPC::Message* message =
rfh->GetProcess()->sink().GetUniqueMessageMatching(
- FrameMsg_EnforceStrictMixedContentChecking::ID);
+ FrameMsg_EnforceInsecureRequestPolicy::ID);
ASSERT_TRUE(message);
EXPECT_EQ(expected_routing_id, message->routing_id());
- FrameMsg_EnforceStrictMixedContentChecking::Param params;
- EXPECT_TRUE(
- FrameMsg_EnforceStrictMixedContentChecking::Read(message, &params));
- EXPECT_EQ(expected_param, base::get<0>(params));
+ FrameMsg_EnforceInsecureRequestPolicy::Param params;
+ EXPECT_TRUE(FrameMsg_EnforceInsecureRequestPolicy::Read(message, &params));
+ EXPECT_EQ(expected_param, std::get<0>(params));
}
class RenderFrameHostManagerTestWebUIControllerFactory
@@ -304,20 +305,11 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
WebUIControllerFactory::RegisterFactory(&factory_);
-#if !defined(OS_ANDROID)
- ImageTransportFactory::InitializeForUnitTests(
- base::WrapUnique(new NoTransportImageTransportFactory));
-#endif
}
void TearDown() override {
RenderViewHostImplTestHarness::TearDown();
WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
-#if !defined(OS_ANDROID)
- // RenderWidgetHostView holds on to a reference to SurfaceManager, so it
- // must be shut down before the ImageTransportFactory.
- ImageTransportFactory::Terminate();
-#endif
}
void set_should_create_webui(bool should_create_webui) {
@@ -464,7 +456,7 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
return frame_host;
}
- return manager->Navigate(frame_entry->url(), *frame_entry, entry);
+ return manager->Navigate(frame_entry->url(), *frame_entry, entry, false);
}
// Returns the pending RenderFrameHost.
@@ -1743,7 +1735,9 @@ TEST_F(RenderFrameHostManagerTest, CloseWithPendingWhileUnresponsive) {
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
// Simulate the unresponsiveness timer. The tab should close.
- contents()->RendererUnresponsive(rfh1->render_view_host()->GetWidget());
+ contents()->RendererUnresponsive(
+ rfh1->render_view_host()->GetWidget(),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_CLOSE_PAGE);
EXPECT_TRUE(close_delegate.is_closed());
}
@@ -2231,7 +2225,7 @@ TEST_F(RenderFrameHostManagerTest, CreateOpenerProxiesWithCycleOnOpenerChain) {
EXPECT_TRUE(message);
FrameMsg_UpdateOpener::Param params;
EXPECT_TRUE(FrameMsg_UpdateOpener::Read(message, &params));
- EXPECT_EQ(tab2_opener_routing_id, base::get<0>(params));
+ EXPECT_EQ(tab2_opener_routing_id, std::get<0>(params));
}
// Test that opener proxies are created properly when the opener points
@@ -2278,7 +2272,7 @@ TEST_F(RenderFrameHostManagerTest, CreateOpenerProxiesWhenOpenerPointsToSelf) {
EXPECT_TRUE(message);
FrameMsg_UpdateOpener::Param params;
EXPECT_TRUE(FrameMsg_UpdateOpener::Read(message, &params));
- EXPECT_EQ(opener_routing_id, base::get<0>(params));
+ EXPECT_EQ(opener_routing_id, std::get<0>(params));
}
// Build the following frame opener graph and see that it can be properly
@@ -3015,9 +3009,9 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
}
// Tests that frame proxies receive updates when a frame's enforcement
-// of strict mixed content checking changes.
+// of insecure request policy changes.
TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
- ProxiesReceiveShouldEnforceStrictMixedContentChecking) {
+ ProxiesReceiveInsecureRequestPolicy) {
const GURL kUrl1("http://www.google.test");
const GURL kUrl2("http://www.google2.test");
const GURL kUrl3("http://www.google2.test/foo");
@@ -3049,16 +3043,18 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
// Change the parent's enforcement of strict mixed content checking,
// and check that the correct IPC is sent to the child frame's
// process.
- EXPECT_FALSE(root->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
- main_test_rfh()->DidEnforceStrictMixedContentChecking();
+ EXPECT_EQ(blink::kLeaveInsecureRequestsAlone,
+ root->current_replication_state().insecure_request_policy);
+ main_test_rfh()->DidEnforceInsecureRequestPolicy(
+ blink::kBlockAllMixedContent);
RenderFrameProxyHost* proxy_to_child =
root->render_manager()->GetRenderFrameProxyHost(
child_host->GetSiteInstance());
EXPECT_NO_FATAL_FAILURE(
- CheckMixedContentIPC(child_host, true, proxy_to_child->GetRoutingID()));
- EXPECT_TRUE(root->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
+ CheckInsecureRequestPolicyIPC(child_host, blink::kBlockAllMixedContent,
+ proxy_to_child->GetRoutingID()));
+ EXPECT_EQ(blink::kBlockAllMixedContent,
+ root->current_replication_state().insecure_request_policy);
// Do the same for the child's enforcement. In general, the parent
// needs to know the status of the child's flag in case a grandchild
@@ -3066,17 +3062,18 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
// content checking, and B.com adds an iframe to A.com, then the
// A.com process needs to know B.com's flag so that the grandchild
// A.com frame can inherit it.
- EXPECT_FALSE(root->child_at(0)
- ->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
- child_host->DidEnforceStrictMixedContentChecking();
+ EXPECT_EQ(
+ blink::kLeaveInsecureRequestsAlone,
+ root->child_at(0)->current_replication_state().insecure_request_policy);
+ child_host->DidEnforceInsecureRequestPolicy(blink::kBlockAllMixedContent);
RenderFrameProxyHost* proxy_to_parent =
child->GetRenderFrameProxyHost(main_test_rfh()->GetSiteInstance());
- EXPECT_NO_FATAL_FAILURE(CheckMixedContentIPC(
- main_test_rfh(), true, proxy_to_parent->GetRoutingID()));
- EXPECT_TRUE(root->child_at(0)
- ->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
+ EXPECT_NO_FATAL_FAILURE(CheckInsecureRequestPolicyIPC(
+ main_test_rfh(), blink::kBlockAllMixedContent,
+ proxy_to_parent->GetRoutingID()));
+ EXPECT_EQ(
+ blink::kBlockAllMixedContent,
+ root->child_at(0)->current_replication_state().insecure_request_policy);
// Check that the flag for the parent's proxy to the child is reset
// when the child navigates.
@@ -3092,13 +3089,14 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
commit_params.was_within_same_page = false;
commit_params.method = "GET";
commit_params.page_state = PageState::CreateFromURL(kUrl3);
- commit_params.should_enforce_strict_mixed_content_checking = false;
+ commit_params.insecure_request_policy = blink::kLeaveInsecureRequestsAlone;
child_host->SendNavigateWithParams(&commit_params);
- EXPECT_NO_FATAL_FAILURE(CheckMixedContentIPC(
- main_test_rfh(), false, proxy_to_parent->GetRoutingID()));
- EXPECT_FALSE(root->child_at(0)
- ->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
+ EXPECT_NO_FATAL_FAILURE(CheckInsecureRequestPolicyIPC(
+ main_test_rfh(), blink::kLeaveInsecureRequestsAlone,
+ proxy_to_parent->GetRoutingID()));
+ EXPECT_EQ(
+ blink::kLeaveInsecureRequestsAlone,
+ root->child_at(0)->current_replication_state().insecure_request_policy);
}
} // 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 bbffcca4fa9..d6efb2cce20 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -10,14 +10,20 @@
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/download/download_stats.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/renderer_host/render_widget_helper.h"
+#include "content/browser/resource_context_impl.h"
+#include "content/common/content_constants_internal.h"
#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_manager.h"
+#include "content/public/browser/download_url_parameters.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "gpu/GLES2/gl2extchromium.h"
@@ -26,6 +32,7 @@
#include "net/cookies/cookie_store.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "url/gurl.h"
#if !defined(OS_MACOSX)
@@ -70,6 +77,21 @@ void CreateChildFrameOnUI(
}
}
+void DownloadUrlOnUIThread(std::unique_ptr<DownloadUrlParameters> parameters) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(parameters->render_process_host_id());
+ if (!render_process_host)
+ return;
+
+ BrowserContext* browser_context = render_process_host->GetBrowserContext();
+ DownloadManager* download_manager =
+ BrowserContext::GetDownloadManager(browser_context);
+ RecordDownloadSource(INITIATED_BY_RENDERER);
+ download_manager->DownloadUrl(std::move(parameters));
+}
+
// Common functionality for converting a sync renderer message to a callback
// function in the browser. Derive from this, create it on the heap when
// issuing your callback. When done, write your reply parameters into
@@ -213,6 +235,9 @@ bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(FrameHostMsg_SetCookie, OnSetCookie)
IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_GetCookies, OnGetCookies)
IPC_MESSAGE_HANDLER(FrameHostMsg_CookiesEnabled, OnCookiesEnabled)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_DownloadUrl, OnDownloadUrl)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_SaveImageFromDataURL,
+ OnSaveImageFromDataURL)
IPC_MESSAGE_HANDLER(FrameHostMsg_Are3DAPIsBlocked, OnAre3DAPIsBlocked)
IPC_MESSAGE_HANDLER_GENERIC(FrameHostMsg_RenderProcessGone,
OnRenderProcessGone())
@@ -236,6 +261,37 @@ bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+void RenderFrameMessageFilter::DownloadUrl(int render_view_id,
+ int render_frame_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& suggested_name,
+ const bool use_prompt) const {
+ if (!resource_context_)
+ return;
+
+ std::unique_ptr<DownloadUrlParameters> parameters(
+ new DownloadUrlParameters(url, render_process_id_, render_view_id,
+ render_frame_id, request_context_.get()));
+ parameters->set_content_initiated(true);
+ parameters->set_suggested_name(suggested_name);
+ parameters->set_prompt(use_prompt);
+ parameters->set_referrer(referrer);
+
+ if (url.SchemeIsBlob()) {
+ ChromeBlobStorageContext* blob_context =
+ GetChromeBlobStorageContextForResourceContext(resource_context_);
+ parameters->set_blob_data_handle(
+ blob_context->context()->GetBlobDataFromPublicURL(url));
+ // Don't care if the above fails. We are going to let the download go
+ // through and allow it to be interrupted so that the embedder can deal.
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DownloadUrlOnUIThread, base::Passed(&parameters)));
+}
+
void RenderFrameMessageFilter::OnCreateChildFrame(
const FrameHostMsg_CreateChildFrame_Params& params,
int* new_routing_id) {
@@ -361,6 +417,32 @@ void RenderFrameMessageFilter::SendGetCookiesResponse(
Send(reply_msg);
}
+void RenderFrameMessageFilter::OnDownloadUrl(
+ int render_view_id,
+ int render_frame_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& suggested_name) {
+ DownloadUrl(render_view_id, render_frame_id, url, referrer, suggested_name,
+ false);
+}
+
+void RenderFrameMessageFilter::OnSaveImageFromDataURL(
+ int render_view_id,
+ int render_frame_id,
+ const std::string& url_str) {
+ // Please refer to RenderFrameImpl::saveImageFromDataURL().
+ if (url_str.length() >= kMaxLengthOfDataURLString)
+ return;
+
+ GURL data_url(url_str);
+ if (!data_url.is_valid() || !data_url.SchemeIs(url::kDataScheme))
+ return;
+
+ DownloadUrl(render_view_id, render_frame_id, data_url, Referrer(),
+ base::string16(), true);
+}
+
void RenderFrameMessageFilter::OnAre3DAPIsBlocked(int render_frame_id,
const GURL& top_origin_url,
ThreeDAPIType requester,
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter.h b/chromium/content/browser/frame_host/render_frame_message_filter.h
index 16190cf3d67..40716cd6746 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.h
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.h
@@ -31,6 +31,7 @@ class URLRequestContextGetter;
namespace content {
class BrowserContext;
class PluginServiceImpl;
+struct Referrer;
class RenderWidgetHelper;
class ResourceContext;
struct WebPluginInfo;
@@ -41,7 +42,7 @@ struct WebPluginInfo;
// with the routing id for a newly created RenderFrame.
//
// This object is created on the UI thread and used on the IO thread.
-class RenderFrameMessageFilter : public BrowserMessageFilter {
+class CONTENT_EXPORT RenderFrameMessageFilter : public BrowserMessageFilter {
public:
RenderFrameMessageFilter(int render_process_id,
PluginServiceImpl* plugin_service,
@@ -52,6 +53,17 @@ class RenderFrameMessageFilter : public BrowserMessageFilter {
// BrowserMessageFilter methods:
bool OnMessageReceived(const IPC::Message& message) override;
+ protected:
+ friend class TestSaveImageFromDataURL;
+
+ // This method will be overridden by TestSaveImageFromDataURL class for test.
+ virtual void DownloadUrl(int render_view_id,
+ int render_frame_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& suggested_name,
+ const bool use_prompt) const;
+
private:
class OpenChannelToPpapiPluginCallback;
class OpenChannelToPpapiBrokerCallback;
@@ -85,6 +97,15 @@ class RenderFrameMessageFilter : public BrowserMessageFilter {
void SendGetCookiesResponse(IPC::Message* reply_msg,
const std::string& cookies);
+ void OnDownloadUrl(int render_view_id,
+ int render_frame_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& suggested_name);
+ void OnSaveImageFromDataURL(int render_view_id,
+ int render_frame_id,
+ const std::string& url_str);
+
void OnAre3DAPIsBlocked(int render_frame_id,
const GURL& top_origin_url,
ThreeDAPIType requester,
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 3881d87e504..6ee07fd4c7b 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -193,6 +193,16 @@ bool RenderFrameProxyHost::InitRenderFrameProxy() {
->current_replication_state()));
render_frame_proxy_created_ = true;
+
+ // For subframes, initialize the proxy's WebFrameOwnerProperties only if they
+ // differ from default values.
+ bool should_send_properties = frame_tree_node_->frame_owner_properties() !=
+ blink::WebFrameOwnerProperties();
+ if (frame_tree_node_->parent() && should_send_properties) {
+ Send(new FrameMsg_SetFrameOwnerProperties(
+ routing_id_, frame_tree_node_->frame_owner_properties()));
+ }
+
return true;
}
@@ -253,7 +263,8 @@ void RenderFrameProxyHost::OnOpenURL(
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.should_replace_current_entry, params.uses_post ? "POST" : "GET",
+ params.resource_request_body);
}
void RenderFrameProxyHost::OnRouteMessageEvent(
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 7101a901d12..21d4b1cadd1 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
@@ -8,7 +8,10 @@
#include <utility>
#include <vector>
+#include "base/location.h"
#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
@@ -30,6 +33,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/common/browser_plugin_guest_mode.h"
#include "gpu/ipc/common/gpu_messages.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"
@@ -74,6 +78,13 @@ void RenderWidgetHostViewChildFrame::SetCrossProcessFrameConnector(
id_allocator_->id_namespace());
parent_surface_id_namespace_ = 0;
+
+ // After the RenderWidgetHostViewChildFrame loses the frame_connector, it
+ // won't be able to walk up the frame tree anymore. Clean up anything that
+ // needs to be done through the CrossProcessFrameConnector before it's gone.
+
+ // Unlocks the mouse if this RenderWidgetHostView holds the lock.
+ UnlockMouse();
}
frame_connector_ = frame_connector;
if (frame_connector_) {
@@ -230,10 +241,6 @@ void RenderWidgetHostViewChildFrame::InitAsFullscreen(
NOTREACHED();
}
-void RenderWidgetHostViewChildFrame::ImeCancelComposition() {
- // TODO(kenrb): Fix OOPIF Ime.
-}
-
void RenderWidgetHostViewChildFrame::ImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
@@ -260,11 +267,6 @@ void RenderWidgetHostViewChildFrame::SetIsLoading(bool is_loading) {
NOTREACHED();
}
-void RenderWidgetHostViewChildFrame::TextInputStateChanged(
- const TextInputState& params) {
- // TODO(kenrb): Implement.
-}
-
void RenderWidgetHostViewChildFrame::RenderProcessGone(
base::TerminationStatus status,
int error_code) {
@@ -289,11 +291,12 @@ void RenderWidgetHostViewChildFrame::Destroy() {
host_->SetView(nullptr);
host_ = nullptr;
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
void RenderWidgetHostViewChildFrame::SetTooltipText(
const base::string16& tooltip_text) {
+ frame_connector_->GetRootRenderWidgetHostView()->SetTooltipText(tooltip_text);
}
void RenderWidgetHostViewChildFrame::SelectionChanged(
@@ -368,20 +371,20 @@ void RenderWidgetHostViewChildFrame::SurfaceDrawn(uint32_t output_surface_id,
void RenderWidgetHostViewChildFrame::OnSwapCompositorFrame(
uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {
+ cc::CompositorFrame frame) {
TRACE_EVENT0("content",
"RenderWidgetHostViewChildFrame::OnSwapCompositorFrame");
- last_scroll_offset_ = frame->metadata.root_scroll_offset;
+ last_scroll_offset_ = frame.metadata.root_scroll_offset;
if (!frame_connector_)
return;
cc::RenderPass* root_pass =
- frame->delegated_frame_data->render_pass_list.back().get();
+ frame.delegated_frame_data->render_pass_list.back().get();
gfx::Size frame_size = root_pass->output_rect.size();
- float scale_factor = frame->metadata.device_scale_factor;
+ 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.
@@ -445,15 +448,6 @@ void RenderWidgetHostViewChildFrame::GetScreenInfo(
frame_connector_->GetScreenInfo(results);
}
-bool RenderWidgetHostViewChildFrame::GetScreenColorProfile(
- std::vector<char>* color_profile) {
- if (!frame_connector_)
- return false;
- DCHECK(color_profile->empty());
- NOTIMPLEMENTED();
- return false;
-}
-
gfx::Rect RenderWidgetHostViewChildFrame::GetBoundsInRootWindow() {
gfx::Rect rect;
if (frame_connector_) {
@@ -477,10 +471,22 @@ void RenderWidgetHostViewChildFrame::ProcessAckedTouchEvent(
}
bool RenderWidgetHostViewChildFrame::LockMouse() {
+ if (frame_connector_)
+ return frame_connector_->LockMouse();
return false;
}
void RenderWidgetHostViewChildFrame::UnlockMouse() {
+ if (host_->delegate() && host_->delegate()->HasMouseLock(host_) &&
+ frame_connector_)
+ frame_connector_->UnlockMouse();
+}
+
+bool RenderWidgetHostViewChildFrame::IsMouseLocked() {
+ if (!host_->delegate())
+ return false;
+
+ return host_->delegate()->HasMouseLock(host_);
}
uint32_t RenderWidgetHostViewChildFrame::GetSurfaceIdNamespace() {
@@ -493,14 +499,16 @@ void RenderWidgetHostViewChildFrame::ProcessKeyboardEvent(
}
void RenderWidgetHostViewChildFrame::ProcessMouseEvent(
- const blink::WebMouseEvent& event) {
- host_->ForwardMouseEvent(event);
+ const blink::WebMouseEvent& event,
+ const ui::LatencyInfo& latency) {
+ host_->ForwardMouseEventWithLatencyInfo(event, latency);
}
void RenderWidgetHostViewChildFrame::ProcessMouseWheelEvent(
- const blink::WebMouseWheelEvent& event) {
+ const blink::WebMouseWheelEvent& event,
+ const ui::LatencyInfo& latency) {
if (event.deltaX != 0 || event.deltaY != 0)
- host_->ForwardWheelEvent(event);
+ host_->ForwardWheelEventWithLatencyInfo(event, latency);
}
void RenderWidgetHostViewChildFrame::ProcessTouchEvent(
@@ -670,6 +678,31 @@ void RenderWidgetHostViewChildFrame::OnSetNeedsBeginFrames(
}
}
+InputEventAckState RenderWidgetHostViewChildFrame::FilterInputEvent(
+ const blink::WebInputEvent& input_event) {
+ if (input_event.type == blink::WebInputEvent::GestureFlingStart) {
+ const blink::WebGestureEvent& gesture_event =
+ static_cast<const blink::WebGestureEvent&>(input_event);
+ // Zero-velocity touchpad flings are an Aura-specific signal that the
+ // touchpad scroll has ended, and should not be forwarded to the renderer.
+ if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad &&
+ !gesture_event.data.flingStart.velocityX &&
+ !gesture_event.data.flingStart.velocityY) {
+ // Here we indicate that there was no consumer for this event, as
+ // otherwise the fling animation system will try to run an animation
+ // and will also expect a notification when the fling ends. Since
+ // CrOS just uses the GestureFlingStart with zero-velocity as a means
+ // of indicating that touchpad scroll has ended, we don't actually want
+ // a fling animation.
+ // Note: this event handling is modeled on similar code in
+ // TenderWidgetHostViewAura::FilterInputEvent().
+ return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ }
+ }
+
+ return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+}
+
BrowserAccessibilityManager*
RenderWidgetHostViewChildFrame::CreateBrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
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 9a2bd5e470e..67fdcd213b8 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
@@ -40,7 +40,6 @@ class RenderWidgetHost;
class RenderWidgetHostImpl;
class RenderWidgetHostViewChildFrameTest;
class RenderWidgetHostViewGuestSurfaceTest;
-struct TextInputState;
// RenderWidgetHostViewChildFrame implements the view for a RenderWidgetHost
// associated with content being rendered in a separate process from
@@ -89,6 +88,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
gfx::NativeViewAccessible GetNativeViewAccessible() override;
void SetBackgroundColor(SkColor color) override;
gfx::Size GetPhysicalBackingSize() const override;
+ bool IsMouseLocked() override;
// RenderWidgetHostViewBase implementation.
void InitAsPopup(RenderWidgetHostView* parent_host_view,
@@ -96,8 +96,6 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
void UpdateCursor(const WebCursor& cursor) override;
void SetIsLoading(bool is_loading) override;
- void TextInputStateChanged(const TextInputState& params) override;
- void ImeCancelComposition() override;
void ImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) override;
@@ -125,14 +123,12 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
InputEventAckState ack_result) override;
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
- void OnSwapCompositorFrame(
- uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) override;
+ void OnSwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) override;
// Since the URL of content rendered by this class is not displayed in
// the URL bar, this method does not need an implementation.
void ClearCompositorFrame() override {}
void GetScreenInfo(blink::WebScreenInfo* results) override;
- bool GetScreenColorProfile(std::vector<char>* color_profile) override;
gfx::Rect GetBoundsInRootWindow() override;
void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) override;
@@ -140,8 +136,10 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void UnlockMouse() override;
uint32_t GetSurfaceIdNamespace() override;
void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) override;
- void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
- void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
+ void ProcessMouseEvent(const blink::WebMouseEvent& event,
+ const ui::LatencyInfo& latency) override;
+ void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event,
+ const ui::LatencyInfo& latency) override;
void ProcessTouchEvent(const blink::WebTouchEvent& event,
const ui::LatencyInfo& latency) override;
void ProcessGestureEvent(const blink::WebGestureEvent& event,
@@ -163,6 +161,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void LockCompositingSurface() override;
void UnlockCompositingSurface() override;
+ InputEventAckState FilterInputEvent(
+ const blink::WebInputEvent& input_event) override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
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 c395fa5377f..ca5d43677e8 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
@@ -123,18 +123,17 @@ class RenderWidgetHostViewChildFrameTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewChildFrameTest);
};
-std::unique_ptr<cc::CompositorFrame> CreateDelegatedFrame(
- float scale_factor,
- gfx::Size size,
- const gfx::Rect& damage) {
- std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
- frame->metadata.device_scale_factor = scale_factor;
- frame->delegated_frame_data.reset(new cc::DelegatedFrameData);
+cc::CompositorFrame CreateDelegatedFrame(float scale_factor,
+ gfx::Size size,
+ const gfx::Rect& damage) {
+ cc::CompositorFrame frame;
+ frame.metadata.device_scale_factor = scale_factor;
+ frame.delegated_frame_data.reset(new cc::DelegatedFrameData);
std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
pass->SetNew(cc::RenderPassId(1, 1), gfx::Rect(size), damage,
gfx::Transform());
- frame->delegated_frame_data->render_pass_list.push_back(std::move(pass));
+ frame.delegated_frame_data->render_pass_list.push_back(std::move(pass));
return frame;
}
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 d5434c96f1b..a3062e07efb 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
@@ -258,16 +258,16 @@ void RenderWidgetHostViewGuest::SetTooltipText(
void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {
+ cc::CompositorFrame frame) {
TRACE_EVENT0("content", "RenderWidgetHostViewGuest::OnSwapCompositorFrame");
- last_scroll_offset_ = frame->metadata.root_scroll_offset;
+ last_scroll_offset_ = frame.metadata.root_scroll_offset;
cc::RenderPass* root_pass =
- frame->delegated_frame_data->render_pass_list.back().get();
+ frame.delegated_frame_data->render_pass_list.back().get();
gfx::Size frame_size = root_pass->output_rect.size();
- float scale_factor = frame->metadata.device_scale_factor;
+ 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.
@@ -472,17 +472,6 @@ void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo* results) {
embedder_view->GetScreenInfo(results);
}
-bool RenderWidgetHostViewGuest::GetScreenColorProfile(
- std::vector<char>* color_profile) {
- if (!guest_)
- return false;
- DCHECK(color_profile->empty());
- RenderWidgetHostViewBase* embedder_view = GetOwnerRenderWidgetHostView();
- if (embedder_view)
- return embedder_view->GetScreenColorProfile(color_profile);
- return false;
-}
-
#if defined(OS_MACOSX)
void RenderWidgetHostViewGuest::SetActive(bool active) {
platform_view_->SetActive(active);
@@ -566,6 +555,24 @@ void RenderWidgetHostViewGuest::OnHandleInputEvent(
RenderWidgetHostImpl* embedder,
int browser_plugin_instance_id,
const blink::WebInputEvent* event) {
+ // WebMouseWheelEvents go into a queue, and may not be forwarded to the
+ // renderer until after this method goes out of scope. Therefore we need to
+ // explicitly remove the additional device scale factor from the coordinates
+ // before allowing the event to be queued.
+ if (IsUseZoomForDSFEnabled() &&
+ event->type == blink::WebInputEvent::MouseWheel) {
+ blink::WebMouseWheelEvent rescaled_event =
+ *static_cast<const blink::WebMouseWheelEvent*>(event);
+ rescaled_event.x /= current_device_scale_factor();
+ rescaled_event.y /= current_device_scale_factor();
+ rescaled_event.deltaX /= current_device_scale_factor();
+ 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);
+ return;
+ }
+
ScopedInputScaleDisabler disable(host_, current_device_scale_factor());
if (blink::WebInputEvent::isMouseEventType(event->type)) {
// The mouse events for BrowserPlugin are modified by all
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 bcefc2dc7e7..1be1dab9489 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
@@ -92,9 +92,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
const gfx::Range& range) override;
void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) override;
- void OnSwapCompositorFrame(
- uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) override;
+ void OnSwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) override;
#if defined(USE_AURA)
void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) override;
@@ -105,7 +104,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
bool LockMouse() override;
void UnlockMouse() override;
void GetScreenInfo(blink::WebScreenInfo* results) override;
- bool GetScreenColorProfile(std::vector<char>* color_profile) override;
#if defined(OS_MACOSX)
// RenderWidgetHostView implementation.
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 f2fdc76a6d0..6f87593bfab 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
@@ -210,18 +210,17 @@ class RenderWidgetHostViewGuestSurfaceTest
};
namespace {
-std::unique_ptr<cc::CompositorFrame> CreateDelegatedFrame(
- float scale_factor,
- gfx::Size size,
- const gfx::Rect& damage) {
- std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
- frame->metadata.device_scale_factor = scale_factor;
- frame->delegated_frame_data.reset(new cc::DelegatedFrameData);
+cc::CompositorFrame CreateDelegatedFrame(float scale_factor,
+ gfx::Size size,
+ const gfx::Rect& damage) {
+ cc::CompositorFrame frame;
+ frame.metadata.device_scale_factor = scale_factor;
+ frame.delegated_frame_data.reset(new cc::DelegatedFrameData);
std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
pass->SetNew(cc::RenderPassId(1, 1), gfx::Rect(size), damage,
gfx::Transform());
- frame->delegated_frame_data->render_pass_list.push_back(std::move(pass));
+ frame.delegated_frame_data->render_pass_list.push_back(std::move(pass));
return frame;
}
} // anonymous namespace
diff --git a/chromium/content/browser/frame_host/traced_frame_tree_node.cc b/chromium/content/browser/frame_host/traced_frame_tree_node.cc
deleted file mode 100644
index 702601115e5..00000000000
--- a/chromium/content/browser/frame_host/traced_frame_tree_node.cc
+++ /dev/null
@@ -1,69 +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/frame_host/traced_frame_tree_node.h"
-
-#include "base/command_line.h"
-#include "base/json/json_writer.h"
-#include "base/strings/stringprintf.h"
-#include "content/browser/frame_host/frame_tree.h"
-#include "content/public/common/content_switches.h"
-#include "url/gurl.h"
-
-namespace content {
-
-TracedFrameTreeNode::TracedFrameTreeNode(const FrameTreeNode& node)
- : parent_node_id_(-1),
- process_id_(-1),
- routing_id_(-1) {
- FrameTreeNode* parent = node.parent();
- if (parent)
- parent_node_id_ = parent->frame_tree_node_id();
-
- RenderFrameHostImpl* current_frame_host = node.current_frame_host();
-
- if (current_frame_host->last_committed_url().is_valid())
- url_ = current_frame_host->last_committed_url().spec();
-
- // On Windows, |rph->GetHandle()| does not duplicate ownership
- // of the process handle and the render host still retains it. Therefore, we
- // cannot create a base::Process object, which provides a proper way to get a
- // process id, from the handle. For a stopgap, we use this deprecated
- // function that does not require the ownership (http://crbug.com/417532).
- process_id_ = base::GetProcId(current_frame_host->GetProcess()->GetHandle());
-
- routing_id_ = current_frame_host->GetRoutingID();
- DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
-}
-
-TracedFrameTreeNode::~TracedFrameTreeNode() {
-}
-
-void TracedFrameTreeNode::AppendAsTraceFormat(std::string* out) const {
- std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue());
-
- if (parent_node_id_ >= 0) {
- std::unique_ptr<base::DictionaryValue> ref(new base::DictionaryValue());
- ref->SetString("id_ref", base::StringPrintf("0x%x", parent_node_id_));
- ref->SetString("scope", "FrameTreeNode");
- value->Set("parent", std::move(ref));
- }
-
- if (process_id_ >= 0) {
- std::unique_ptr<base::DictionaryValue> ref(new base::DictionaryValue());
- ref->SetInteger("pid_ref", process_id_);
- ref->SetString("id_ref", base::StringPrintf("0x%x", routing_id_));
- ref->SetString("scope", "RenderFrame");
- value->Set("RenderFrame", std::move(ref));
- }
-
- if (!url_.empty())
- value->SetString("url", url_);
-
- std::string tmp;
- base::JSONWriter::Write(*value, &tmp);
- *out += tmp;
-}
-
-} // content
diff --git a/chromium/content/browser/frame_host/traced_frame_tree_node.h b/chromium/content/browser/frame_host/traced_frame_tree_node.h
deleted file mode 100644
index 79c2a80e911..00000000000
--- a/chromium/content/browser/frame_host/traced_frame_tree_node.h
+++ /dev/null
@@ -1,36 +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 "base/macros.h"
-#include "base/memory/scoped_vector.h"
-#include "base/trace_event/trace_event_impl.h"
-#include "base/values.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class FrameTree;
-class FrameTreeNode;
-
-// This is a temporary container used when tracing snapshots of FrameTree
-// objects. When a snapshot of a FrameTree is taken, a TracedFrameTreeNode is
-// created and stored by the tracing system until the trace is dumped.
-class CONTENT_EXPORT TracedFrameTreeNode :
- public base::trace_event::ConvertableToTraceFormat {
- public:
- TracedFrameTreeNode(const FrameTreeNode& node);
- void AppendAsTraceFormat(std::string* out) const override;
-
- private:
- ~TracedFrameTreeNode() override;
-
- int parent_node_id_;
- std::string url_;
- int process_id_;
- int routing_id_;
-
- DISALLOW_COPY_AND_ASSIGN(TracedFrameTreeNode);
-};
-
-} // content
diff --git a/chromium/content/browser/gamepad/gamepad_consumer.h b/chromium/content/browser/gamepad/gamepad_consumer.h
deleted file mode 100644
index a733d4a82a9..00000000000
--- a/chromium/content/browser/gamepad/gamepad_consumer.h
+++ /dev/null
@@ -1,28 +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_GAMEPAD_GAMEPAD_CONSUMER_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_CONSUMER_H_
-
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebGamepad.h"
-
-namespace content {
-
-class CONTENT_EXPORT GamepadConsumer {
- public:
- virtual void OnGamepadConnected(
- unsigned index,
- const blink::WebGamepad& gamepad) = 0;
- virtual void OnGamepadDisconnected(
- unsigned index,
- const blink::WebGamepad& gamepad) = 0;
-
- protected:
- virtual ~GamepadConsumer() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_CONSUMER_H_
diff --git a/chromium/content/browser/gamepad/gamepad_data_fetcher.cc b/chromium/content/browser/gamepad/gamepad_data_fetcher.cc
deleted file mode 100644
index 891722461e5..00000000000
--- a/chromium/content/browser/gamepad/gamepad_data_fetcher.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 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/gamepad/gamepad_data_fetcher.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-
-namespace {
-
-#if !defined(OS_ANDROID)
-const float kMinAxisResetValue = 0.1f;
-#endif
-
-} // namespace
-
-namespace content {
-
-using blink::WebGamepad;
-using blink::WebGamepads;
-
-#if !defined(OS_ANDROID)
-void GamepadDataFetcher::MapAndSanitizeGamepadData(
- PadState* pad_state, WebGamepad* pad) {
- DCHECK(pad_state);
- DCHECK(pad);
-
- if (!pad_state->data.connected) {
- memset(pad, 0, sizeof(WebGamepad));
- return;
- }
-
- // Copy the current state to the output buffer, using the mapping
- // function, if there is one available.
- if (pad_state->mapper)
- pad_state->mapper(pad_state->data, pad);
- else
- *pad = pad_state->data;
-
- // About sanitization: Gamepads may report input event if the user is not
- // interacting with it, due to hardware problems or environmental ones (pad
- // has something heavy leaning against an axis.) This may cause user gestures
- // to be detected erroniously, exposing gamepad information when the user had
- // no intention of doing so. To avoid this we require that each button or axis
- // report being at rest (zero) at least once before exposing its value to the
- // Gamepad API. This state is tracked by the axis_mask and button_mask
- // bitfields. If the bit for an axis or button is 0 it means the axis has
- // never reported being at rest, and the value will be forced to zero.
-
- // We can skip axis sanitation if all available axes have been masked.
- uint32_t full_axis_mask = (1 << pad->axesLength) - 1;
- if (pad_state->axis_mask != full_axis_mask) {
- for (size_t axis = 0; axis < pad->axesLength; ++axis) {
- if (!(pad_state->axis_mask & 1 << axis)) {
- if (fabs(pad->axes[axis]) < kMinAxisResetValue) {
- pad_state->axis_mask |= 1 << axis;
- } else {
- pad->axes[axis] = 0.0f;
- }
- }
- }
- }
-
- // We can skip button sanitation if all available buttons have been masked.
- uint32_t full_button_mask = (1 << pad->buttonsLength) - 1;
- if (pad_state->button_mask != full_button_mask) {
- for (size_t button = 0; button < pad->buttonsLength; ++button) {
- if (!(pad_state->button_mask & 1 << button)) {
- if (!pad->buttons[button].pressed) {
- pad_state->button_mask |= 1 << button;
- } else {
- pad->buttons[button].pressed = false;
- pad->buttons[button].value = 0.0f;
- }
- }
- }
- }
-}
-#endif
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_data_fetcher.h b/chromium/content/browser/gamepad/gamepad_data_fetcher.h
deleted file mode 100644
index a395fd9b0d2..00000000000
--- a/chromium/content/browser/gamepad/gamepad_data_fetcher.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2011 The Chromium 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_GAMEPAD_GAMEPAD_DATA_FETCHER_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_DATA_FETCHER_H_
-
-#include <stdint.h>
-
-#include "build/build_config.h"
-#include "content/browser/gamepad/gamepad_standard_mappings.h"
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-
-namespace content {
-
-// Abstract interface for imlementing platform- (and test-) specific behaviro
-// for getting the gamepad data.
-class GamepadDataFetcher {
- public:
- virtual ~GamepadDataFetcher() {}
- virtual void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) = 0;
- virtual void PauseHint(bool paused) {}
-
-#if !defined(OS_ANDROID)
- struct PadState {
- // Gamepad data, unmapped.
- blink::WebGamepad data;
-
- // Functions to map from device data to standard layout, if available. May
- // be null if no mapping is available.
- GamepadStandardMappingFunction mapper;
-
- // Sanitization masks
- // axis_mask and button_mask are bitfields that represent the reset state of
- // each input. If a button or axis has ever reported 0 in the past the
- // corresponding bit will be set to 1.
-
- // If we ever increase the max axis count this will need to be updated.
- static_assert(blink::WebGamepad::axesLengthCap <=
- std::numeric_limits<uint32_t>::digits,
- "axis_mask is not large enough");
- uint32_t axis_mask;
-
- // If we ever increase the max button count this will need to be updated.
- static_assert(blink::WebGamepad::buttonsLengthCap <=
- std::numeric_limits<uint32_t>::digits,
- "button_mask is not large enough");
- uint32_t button_mask;
- };
-
- void MapAndSanitizeGamepadData(PadState* pad_state, blink::WebGamepad* pad);
-
- protected:
- PadState pad_state_[blink::WebGamepads::itemsLengthCap];
-#endif
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_DATA_FETCHER_H_
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.cc b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.cc
deleted file mode 100644
index d889526e0d4..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.cc
+++ /dev/null
@@ -1,19 +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/gamepad/gamepad_platform_data_fetcher.h"
-
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-
-namespace content {
-
-GamepadDataFetcherEmpty::GamepadDataFetcherEmpty() {
-}
-
-void GamepadDataFetcherEmpty::GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) {
- pads->length = 0;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h
deleted file mode 100644
index d2dc8b73d76..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h
+++ /dev/null
@@ -1,62 +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.
-
-// Define the default data fetcher that GamepadProvider will use if none is
-// supplied. (GamepadPlatformDataFetcher).
-
-#ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-
-#if defined(OS_ANDROID)
-#include "content/browser/gamepad/gamepad_platform_data_fetcher_android.h"
-#elif defined(OS_WIN)
-#include "content/browser/gamepad/gamepad_platform_data_fetcher_win.h"
-#elif defined(OS_MACOSX)
-#include "content/browser/gamepad/gamepad_platform_data_fetcher_mac.h"
-#elif defined(OS_LINUX)
-#include "content/browser/gamepad/gamepad_platform_data_fetcher_linux.h"
-#endif
-
-namespace content {
-
-#if defined(OS_ANDROID)
-
-typedef GamepadPlatformDataFetcherAndroid GamepadPlatformDataFetcher;
-
-#elif defined(OS_WIN)
-
-typedef GamepadPlatformDataFetcherWin GamepadPlatformDataFetcher;
-
-#elif defined(OS_MACOSX)
-
-typedef GamepadPlatformDataFetcherMac GamepadPlatformDataFetcher;
-
-#elif defined(OS_LINUX) && defined(USE_UDEV)
-
-typedef GamepadPlatformDataFetcherLinux GamepadPlatformDataFetcher;
-
-#else
-
-class GamepadDataFetcherEmpty : public GamepadDataFetcher {
- public:
- GamepadDataFetcherEmpty();
-
- void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GamepadDataFetcherEmpty);
-};
-typedef GamepadDataFetcherEmpty GamepadPlatformDataFetcher;
-
-#endif
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_H_
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.cc b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.cc
deleted file mode 100644
index 1e38cc7f5a9..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.cc
+++ /dev/null
@@ -1,151 +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/gamepad/gamepad_platform_data_fetcher_android.h"
-
-#include <stddef.h>
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/trace_event/trace_event.h"
-
-#include "jni/GamepadList_jni.h"
-
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-
-using base::android::AttachCurrentThread;
-using base::android::CheckException;
-using base::android::ClearException;
-using base::android::ConvertJavaStringToUTF8;
-using base::android::ScopedJavaLocalRef;
-using blink::WebGamepad;
-using blink::WebGamepads;
-
-namespace content {
-
-bool
-GamepadPlatformDataFetcherAndroid::RegisterGamepadPlatformDataFetcherAndroid(
- JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-GamepadPlatformDataFetcherAndroid::GamepadPlatformDataFetcherAndroid() {
- PauseHint(false);
-}
-
-GamepadPlatformDataFetcherAndroid::~GamepadPlatformDataFetcherAndroid() {
- PauseHint(true);
-}
-
-void GamepadPlatformDataFetcherAndroid::GetGamepadData(
- blink::WebGamepads* pads,
- bool devices_changed_hint) {
- TRACE_EVENT0("GAMEPAD", "GetGamepadData");
-
- pads->length = 0;
-
- JNIEnv* env = AttachCurrentThread();
- if (!env)
- return;
-
- Java_GamepadList_updateGamepadData(env, reinterpret_cast<intptr_t>(pads));
-}
-
-void GamepadPlatformDataFetcherAndroid::PauseHint(bool paused) {
- JNIEnv* env = AttachCurrentThread();
- if (!env)
- return;
-
- Java_GamepadList_setGamepadAPIActive(env, !paused);
-}
-
-static void SetGamepadData(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jlong gamepads,
- jint index,
- jboolean mapping,
- jboolean connected,
- const JavaParamRef<jstring>& devicename,
- jlong timestamp,
- const JavaParamRef<jfloatArray>& jaxes,
- const JavaParamRef<jfloatArray>& jbuttons) {
- DCHECK(gamepads);
- blink::WebGamepads* pads = reinterpret_cast<WebGamepads*>(gamepads);
- DCHECK_EQ(pads->length, unsigned(index));
- DCHECK_LT(index, static_cast<int>(blink::WebGamepads::itemsLengthCap));
-
- ++pads->length;
-
- blink::WebGamepad& pad = pads->items[index];
-
- pad.connected = connected;
-
- pad.timestamp = timestamp;
-
- // Do not set gamepad parameters for all the gamepad devices that are not
- // attached.
- if (!connected)
- return;
-
- // Map the Gamepad DeviceName String to the WebGamepad Id. Ideally it should
- // be mapped to vendor and product information but it is only available at
- // kernel level and it can not be queried using class
- // android.hardware.input.InputManager.
- // TODO(SaurabhK): Store a cached WebGamePad object in
- // GamepadPlatformDataFetcherAndroid and only update constant WebGamepad
- // values when a device has changed.
- base::string16 device_name;
- base::android::ConvertJavaStringToUTF16(env, devicename, &device_name);
- const size_t name_to_copy =
- std::min(device_name.size(), WebGamepad::idLengthCap - 1);
- memcpy(pad.id,
- device_name.data(),
- name_to_copy * sizeof(base::string16::value_type));
- pad.id[name_to_copy] = 0;
-
- base::string16 mapping_name = base::UTF8ToUTF16(mapping ? "standard" : "");
- const size_t mapping_to_copy =
- std::min(mapping_name.size(), WebGamepad::mappingLengthCap - 1);
- memcpy(pad.mapping,
- mapping_name.data(),
- mapping_to_copy * sizeof(base::string16::value_type));
- pad.mapping[mapping_to_copy] = 0;
-
- pad.timestamp = timestamp;
-
- std::vector<float> axes;
- base::android::JavaFloatArrayToFloatVector(env, jaxes, &axes);
-
- // Set WebGamepad axeslength to total number of axes on the gamepad device.
- // Only return the first axesLengthCap if axeslength captured by GamepadList
- // is larger than axesLengthCap.
- pad.axesLength = std::min(static_cast<int>(axes.size()),
- static_cast<int>(WebGamepad::axesLengthCap));
-
- // Copy axes state to the WebGamepad axes[].
- for (unsigned int i = 0; i < pad.axesLength; i++) {
- pad.axes[i] = static_cast<double>(axes[i]);
- }
-
- std::vector<float> buttons;
- base::android::JavaFloatArrayToFloatVector(env, jbuttons, &buttons);
-
- // Set WebGamepad buttonslength to total number of axes on the gamepad
- // device. Only return the first buttonsLengthCap if axeslength captured by
- // GamepadList is larger than buttonsLengthCap.
- pad.buttonsLength = std::min(static_cast<int>(buttons.size()),
- static_cast<int>(WebGamepad::buttonsLengthCap));
-
- // Copy buttons state to the WebGamepad buttons[].
- for (unsigned int j = 0; j < pad.buttonsLength; j++) {
- pad.buttons[j].pressed = buttons[j];
- pad.buttons[j].value = buttons[j];
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.h
deleted file mode 100644
index c6ea2e37e1a..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.h
+++ /dev/null
@@ -1,41 +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.
-
-// Define the data fetcher that GamepadProvider will use for android port.
-// (GamepadPlatformDataFetcher).
-
-#ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_ANDROID_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_ANDROID_H_
-
-#include <jni.h>
-
-#include "base/android/jni_android.h"
-#include "base/macros.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-#include "content/browser/gamepad/gamepad_provider.h"
-#include "content/browser/gamepad/gamepad_standard_mappings.h"
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-
-namespace content {
-
-class GamepadPlatformDataFetcherAndroid : public GamepadDataFetcher {
- public:
- GamepadPlatformDataFetcherAndroid();
- ~GamepadPlatformDataFetcherAndroid() override;
-
- void PauseHint(bool paused) override;
-
- void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) override;
-
- // Registers the JNI methods for GamepadsReader.
- static bool RegisterGamepadPlatformDataFetcherAndroid(JNIEnv* env);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GamepadPlatformDataFetcherAndroid);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_ANDROID_H_
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
deleted file mode 100644
index 87ec3714b66..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
+++ /dev/null
@@ -1,274 +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/gamepad/gamepad_platform_data_fetcher_linux.h"
-
-#include <fcntl.h>
-#include <linux/joystick.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/trace_event/trace_event.h"
-#include "device/udev_linux/scoped_udev.h"
-#include "device/udev_linux/udev_linux.h"
-
-namespace {
-
-const char kInputSubsystem[] = "input";
-const char kUsbSubsystem[] = "usb";
-const char kUsbDeviceType[] = "usb_device";
-const float kMaxLinuxAxisValue = 32767.0;
-
-void CloseFileDescriptorIfValid(int fd) {
- if (fd >= 0)
- close(fd);
-}
-
-bool IsGamepad(udev_device* dev, int* index, std::string* path) {
- if (!device::udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK"))
- return false;
-
- const char* node_path = device::udev_device_get_devnode(dev);
- if (!node_path)
- return false;
-
- static const char kJoystickRoot[] = "/dev/input/js";
- bool is_gamepad = base::StartsWith(node_path, kJoystickRoot,
- base::CompareCase::SENSITIVE);
- if (!is_gamepad)
- return false;
-
- int tmp_idx = -1;
- const int base_len = sizeof(kJoystickRoot) - 1;
- base::StringPiece str(&node_path[base_len], strlen(node_path) - base_len);
- if (!base::StringToInt(str, &tmp_idx))
- return false;
- if (tmp_idx < 0 ||
- tmp_idx >= static_cast<int>(blink::WebGamepads::itemsLengthCap)) {
- return false;
- }
- *index = tmp_idx;
- *path = node_path;
- return true;
-}
-
-} // namespace
-
-namespace content {
-
-using blink::WebGamepad;
-using blink::WebGamepads;
-
-GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() {
- for (size_t i = 0; i < arraysize(pad_state_); ++i) {
- device_fd_[i] = -1;
- pad_state_[i].mapper = 0;
- pad_state_[i].axis_mask = 0;
- pad_state_[i].button_mask = 0;
- }
-
- std::vector<device::UdevLinux::UdevMonitorFilter> filters;
- filters.push_back(
- device::UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL));
- udev_.reset(new device::UdevLinux(
- filters, base::Bind(&GamepadPlatformDataFetcherLinux::RefreshDevice,
- base::Unretained(this))));
-
- EnumerateDevices();
-}
-
-GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() {
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i)
- CloseFileDescriptorIfValid(device_fd_[i]);
-}
-
-void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) {
- TRACE_EVENT0("GAMEPAD", "GetGamepadData");
-
- // Update our internal state.
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- if (device_fd_[i] >= 0) {
- ReadDeviceData(i);
- }
- }
-
- pads->length = WebGamepads::itemsLengthCap;
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]);
- }
-}
-
-// Used during enumeration, and monitor notifications.
-void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
- int index;
- std::string node_path;
- if (IsGamepad(dev, &index, &node_path)) {
- int& device_fd = device_fd_[index];
- WebGamepad& pad = pad_state_[index].data;
- GamepadStandardMappingFunction& mapper = pad_state_[index].mapper;
-
- CloseFileDescriptorIfValid(device_fd);
-
- // The device pointed to by dev contains information about the logical
- // joystick device. In order to get the information about the physical
- // hardware, get the parent device that is also in the "input" subsystem.
- // This function should just walk up the tree one level.
- dev = device::udev_device_get_parent_with_subsystem_devtype(
- dev, kInputSubsystem, NULL);
- if (!dev) {
- // Unable to get device information, don't use this device.
- device_fd = -1;
- pad.connected = false;
- return;
- }
-
- device_fd = HANDLE_EINTR(open(node_path.c_str(), O_RDONLY | O_NONBLOCK));
- if (device_fd < 0) {
- // Unable to open device, don't use.
- pad.connected = false;
- return;
- }
-
- const char* vendor_id =
- device::udev_device_get_sysattr_value(dev, "id/vendor");
- const char* product_id =
- device::udev_device_get_sysattr_value(dev, "id/product");
- mapper = GetGamepadStandardMappingFunction(vendor_id, product_id);
-
- // Driver returns utf-8 strings here, so combine in utf-8 first and
- // convert to WebUChar later once we've picked an id string.
- const char* name = device::udev_device_get_sysattr_value(dev, "name");
- std::string name_string(name);
-
- // In many cases the information the input subsystem contains isn't
- // as good as the information that the device bus has, walk up further
- // to the subsystem/device type "usb"/"usb_device" and if this device
- // has the same vendor/product id, prefer the description from that.
- struct udev_device* usb_dev =
- device::udev_device_get_parent_with_subsystem_devtype(
- dev, kUsbSubsystem, kUsbDeviceType);
- if (usb_dev) {
- const char* usb_vendor_id =
- device::udev_device_get_sysattr_value(usb_dev, "idVendor");
- const char* usb_product_id =
- device::udev_device_get_sysattr_value(usb_dev, "idProduct");
-
- if (strcmp(vendor_id, usb_vendor_id) == 0 &&
- strcmp(product_id, usb_product_id) == 0) {
- const char* manufacturer =
- device::udev_device_get_sysattr_value(usb_dev, "manufacturer");
- const char* product =
- device::udev_device_get_sysattr_value(usb_dev, "product");
-
- // Replace the previous name string with one containing the better
- // information, again driver returns utf-8 strings here so combine
- // in utf-8 for conversion to WebUChar below.
- name_string = base::StringPrintf("%s %s", manufacturer, product);
- }
- }
-
- // Append the vendor and product information then convert the utf-8
- // id string to WebUChar.
- std::string id =
- name_string + base::StringPrintf(" (%sVendor: %s Product: %s)",
- mapper ? "STANDARD GAMEPAD " : "",
- vendor_id,
- product_id);
- base::TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id);
- base::string16 tmp16 = base::UTF8ToUTF16(id);
- memset(pad.id, 0, sizeof(pad.id));
- tmp16.copy(pad.id, arraysize(pad.id) - 1);
-
- if (mapper) {
- std::string mapping = "standard";
- base::TruncateUTF8ToByteSize(
- mapping, WebGamepad::mappingLengthCap - 1, &mapping);
- tmp16 = base::UTF8ToUTF16(mapping);
- memset(pad.mapping, 0, sizeof(pad.mapping));
- tmp16.copy(pad.mapping, arraysize(pad.mapping) - 1);
- } else {
- pad.mapping[0] = 0;
- }
-
- pad_state_[index].axis_mask = 0;
- pad_state_[index].button_mask = 0;
-
- pad.connected = true;
- }
-}
-
-void GamepadPlatformDataFetcherLinux::EnumerateDevices() {
- device::ScopedUdevEnumeratePtr enumerate(
- device::udev_enumerate_new(udev_->udev_handle()));
- if (!enumerate)
- return;
- int ret = device::udev_enumerate_add_match_subsystem(enumerate.get(),
- kInputSubsystem);
- if (ret != 0)
- return;
- ret = device::udev_enumerate_scan_devices(enumerate.get());
- if (ret != 0)
- return;
-
- udev_list_entry* devices =
- device::udev_enumerate_get_list_entry(enumerate.get());
- for (udev_list_entry* dev_list_entry = devices; dev_list_entry != NULL;
- dev_list_entry = device::udev_list_entry_get_next(dev_list_entry)) {
- // Get the filename of the /sys entry for the device and create a
- // udev_device object (dev) representing it
- const char* path = device::udev_list_entry_get_name(dev_list_entry);
- device::ScopedUdevDevicePtr dev(
- device::udev_device_new_from_syspath(udev_->udev_handle(), path));
- if (!dev)
- continue;
- RefreshDevice(dev.get());
- }
-}
-
-void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) {
- // Linker does not like CHECK_LT(index, WebGamepads::itemsLengthCap). =/
- if (index >= WebGamepads::itemsLengthCap) {
- CHECK(false);
- return;
- }
-
- const int& fd = device_fd_[index];
- WebGamepad& pad = pad_state_[index].data;
- DCHECK_GE(fd, 0);
-
- js_event event;
- while (HANDLE_EINTR(read(fd, &event, sizeof(struct js_event))) > 0) {
- size_t item = event.number;
- if (event.type & JS_EVENT_AXIS) {
- if (item >= WebGamepad::axesLengthCap)
- continue;
-
- pad.axes[item] = event.value / kMaxLinuxAxisValue;
-
- if (item >= pad.axesLength)
- pad.axesLength = item + 1;
- } else if (event.type & JS_EVENT_BUTTON) {
- if (item >= WebGamepad::buttonsLengthCap)
- continue;
-
- pad.buttons[item].pressed = event.value;
- pad.buttons[item].value = event.value ? 1.0 : 0.0;
-
- if (item >= pad.buttonsLength)
- pad.buttonsLength = item + 1;
- }
- pad.timestamp = event.time;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
deleted file mode 100644
index a260760d9c1..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
+++ /dev/null
@@ -1,51 +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_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_LINUX_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_LINUX_H_
-
-#include <stddef.h>
-
-#include <memory>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-
-extern "C" {
-struct udev_device;
-}
-
-namespace device {
-class UdevLinux;
-}
-
-namespace content {
-
-class GamepadPlatformDataFetcherLinux : public GamepadDataFetcher {
- public:
- GamepadPlatformDataFetcherLinux();
- ~GamepadPlatformDataFetcherLinux() override;
-
- // GamepadDataFetcher implementation.
- void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) override;
-
- private:
- void RefreshDevice(udev_device* dev);
- void EnumerateDevices();
- void ReadDeviceData(size_t index);
-
- // File descriptor for the /dev/input/js* devices. -1 if not in use.
- int device_fd_[blink::WebGamepads::itemsLengthCap];
-
- std::unique_ptr<device::UdevLinux> udev_;
-
- DISALLOW_COPY_AND_ASSIGN(GamepadPlatformDataFetcherLinux);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_LINUX_H_
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h
deleted file mode 100644
index 254ebb5ca8f..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h
+++ /dev/null
@@ -1,106 +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_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_MAC_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_MAC_H_
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOKit/hid/IOHIDManager.h>
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-#include "content/browser/gamepad/xbox_data_fetcher_mac.h"
-#include "content/common/gamepad_hardware_buffer.h"
-
-#if defined(__OBJC__)
-@class NSArray;
-#else
-class NSArray;
-#endif
-
-namespace content {
-
-class GamepadPlatformDataFetcherMac : public GamepadDataFetcher,
- public XboxDataFetcher::Delegate {
- public:
- GamepadPlatformDataFetcherMac();
- ~GamepadPlatformDataFetcherMac() override;
- void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) override;
- void PauseHint(bool paused) override;
-
- private:
- bool enabled_;
- bool paused_;
- base::ScopedCFTypeRef<IOHIDManagerRef> hid_manager_ref_;
-
- static GamepadPlatformDataFetcherMac* InstanceFromContext(void* context);
- static void DeviceAddCallback(void* context,
- IOReturn result,
- void* sender,
- IOHIDDeviceRef ref);
- static void DeviceRemoveCallback(void* context,
- IOReturn result,
- void* sender,
- IOHIDDeviceRef ref);
- static void ValueChangedCallback(void* context,
- IOReturn result,
- void* sender,
- IOHIDValueRef ref);
-
- size_t GetEmptySlot();
- size_t GetSlotForDevice(IOHIDDeviceRef device);
- size_t GetSlotForXboxDevice(XboxController* device);
-
- void DeviceAdd(IOHIDDeviceRef device);
- bool CheckCollection(IOHIDElementRef element);
- bool AddButtonsAndAxes(NSArray* elements, size_t slot);
- void DeviceRemove(IOHIDDeviceRef device);
- void ValueChanged(IOHIDValueRef value);
-
- void XboxDeviceAdd(XboxController* device) override;
- void XboxDeviceRemove(XboxController* device) override;
- void XboxValueChanged(XboxController* device,
- const XboxController::Data& data) override;
-
- void RegisterForNotifications();
- void UnregisterFromNotifications();
-
- void SanitizeGamepadData(size_t index, blink::WebGamepad* pad);
-
- std::unique_ptr<XboxDataFetcher> xbox_fetcher_;
-
- // Side-band data that's not passed to the consumer, but we need to maintain
- // to update data_.
- struct AssociatedData {
- bool is_xbox;
- union {
- struct {
- IOHIDDeviceRef device_ref;
- IOHIDElementRef button_elements[blink::WebGamepad::buttonsLengthCap];
- IOHIDElementRef axis_elements[blink::WebGamepad::axesLengthCap];
- CFIndex axis_minimums[blink::WebGamepad::axesLengthCap];
- CFIndex axis_maximums[blink::WebGamepad::axesLengthCap];
- CFIndex axis_report_sizes[blink::WebGamepad::axesLengthCap];
- } hid;
- struct {
- XboxController* device;
- UInt32 location_id;
- } xbox;
- };
- };
- AssociatedData associated_[blink::WebGamepads::itemsLengthCap];
-
- DISALLOW_COPY_AND_ASSIGN(GamepadPlatformDataFetcherMac);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_MAC_H_
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
deleted file mode 100644
index 38e69b6c3e3..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
+++ /dev/null
@@ -1,575 +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/gamepad/gamepad_platform_data_fetcher_mac.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#include "base/mac/foundation_util.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-
-#import <Foundation/Foundation.h>
-#include <IOKit/hid/IOHIDKeys.h>
-
-using blink::WebGamepad;
-using blink::WebGamepads;
-
-namespace content {
-
-namespace {
-
-void CopyNSStringAsUTF16LittleEndian(
- NSString* src, blink::WebUChar* dest, size_t dest_len) {
- NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
- memset(dest, 0, dest_len);
- [as16 getBytes:dest length:dest_len - sizeof(blink::WebUChar)];
-}
-
-NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) {
- return [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithUnsignedInt:usage_page],
- base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsagePageKey)),
- [NSNumber numberWithUnsignedInt:usage],
- base::mac::CFToNSCast(CFSTR(kIOHIDDeviceUsageKey)),
- nil];
-}
-
-float NormalizeAxis(CFIndex value, CFIndex min, CFIndex max) {
- return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
-}
-
-float NormalizeUInt8Axis(uint8_t value, uint8_t min, uint8_t max) {
- return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
-}
-
-float NormalizeUInt16Axis(uint16_t value, uint16_t min, uint16_t max) {
- return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
-}
-
-float NormalizeUInt32Axis(uint32_t value, uint32_t min, uint32_t max) {
- return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
-}
-
-// http://www.usb.org/developers/hidpage
-const uint32_t kGenericDesktopUsagePage = 0x01;
-const uint32_t kGameControlsUsagePage = 0x05;
-const uint32_t kButtonUsagePage = 0x09;
-const uint32_t kJoystickUsageNumber = 0x04;
-const uint32_t kGameUsageNumber = 0x05;
-const uint32_t kMultiAxisUsageNumber = 0x08;
-const uint32_t kAxisMinimumUsageNumber = 0x30;
-
-} // namespace
-
-GamepadPlatformDataFetcherMac::GamepadPlatformDataFetcherMac()
- : enabled_(true), paused_(false) {
- memset(associated_, 0, sizeof(associated_));
-
- xbox_fetcher_.reset(new XboxDataFetcher(this));
- if (!xbox_fetcher_->RegisterForNotifications())
- xbox_fetcher_.reset();
-
- hid_manager_ref_.reset(IOHIDManagerCreate(kCFAllocatorDefault,
- kIOHIDOptionsTypeNone));
- if (CFGetTypeID(hid_manager_ref_) != IOHIDManagerGetTypeID()) {
- enabled_ = false;
- return;
- }
-
- base::scoped_nsobject<NSArray> criteria([[NSArray alloc] initWithObjects:
- DeviceMatching(kGenericDesktopUsagePage, kJoystickUsageNumber),
- DeviceMatching(kGenericDesktopUsagePage, kGameUsageNumber),
- DeviceMatching(kGenericDesktopUsagePage, kMultiAxisUsageNumber),
- nil]);
- IOHIDManagerSetDeviceMatchingMultiple(
- hid_manager_ref_,
- base::mac::NSToCFCast(criteria));
-
- RegisterForNotifications();
-}
-
-void GamepadPlatformDataFetcherMac::RegisterForNotifications() {
- // Register for plug/unplug notifications.
- IOHIDManagerRegisterDeviceMatchingCallback(
- hid_manager_ref_,
- DeviceAddCallback,
- this);
- IOHIDManagerRegisterDeviceRemovalCallback(
- hid_manager_ref_,
- DeviceRemoveCallback,
- this);
-
- // Register for value change notifications.
- IOHIDManagerRegisterInputValueCallback(
- hid_manager_ref_,
- ValueChangedCallback,
- this);
-
- IOHIDManagerScheduleWithRunLoop(
- hid_manager_ref_,
- CFRunLoopGetMain(),
- kCFRunLoopDefaultMode);
-
- enabled_ = IOHIDManagerOpen(hid_manager_ref_,
- kIOHIDOptionsTypeNone) == kIOReturnSuccess;
-
- if (xbox_fetcher_)
- xbox_fetcher_->RegisterForNotifications();
-}
-
-void GamepadPlatformDataFetcherMac::UnregisterFromNotifications() {
- IOHIDManagerUnscheduleFromRunLoop(
- hid_manager_ref_,
- CFRunLoopGetCurrent(),
- kCFRunLoopDefaultMode);
- IOHIDManagerClose(hid_manager_ref_, kIOHIDOptionsTypeNone);
- if (xbox_fetcher_)
- xbox_fetcher_->UnregisterFromNotifications();
-}
-
-void GamepadPlatformDataFetcherMac::PauseHint(bool pause) {
- paused_ = pause;
-}
-
-GamepadPlatformDataFetcherMac::~GamepadPlatformDataFetcherMac() {
- UnregisterFromNotifications();
-}
-
-GamepadPlatformDataFetcherMac*
-GamepadPlatformDataFetcherMac::InstanceFromContext(void* context) {
- return reinterpret_cast<GamepadPlatformDataFetcherMac*>(context);
-}
-
-void GamepadPlatformDataFetcherMac::DeviceAddCallback(void* context,
- IOReturn result,
- void* sender,
- IOHIDDeviceRef ref) {
- InstanceFromContext(context)->DeviceAdd(ref);
-}
-
-void GamepadPlatformDataFetcherMac::DeviceRemoveCallback(void* context,
- IOReturn result,
- void* sender,
- IOHIDDeviceRef ref) {
- InstanceFromContext(context)->DeviceRemove(ref);
-}
-
-void GamepadPlatformDataFetcherMac::ValueChangedCallback(void* context,
- IOReturn result,
- void* sender,
- IOHIDValueRef ref) {
- InstanceFromContext(context)->ValueChanged(ref);
-}
-
-bool GamepadPlatformDataFetcherMac::CheckCollection(IOHIDElementRef element) {
- // Check that a parent collection of this element matches one of the usage
- // numbers that we are looking for.
- while ((element = IOHIDElementGetParent(element)) != NULL) {
- uint32_t usage_page = IOHIDElementGetUsagePage(element);
- uint32_t usage = IOHIDElementGetUsage(element);
- if (usage_page == kGenericDesktopUsagePage) {
- if (usage == kJoystickUsageNumber ||
- usage == kGameUsageNumber ||
- usage == kMultiAxisUsageNumber) {
- return true;
- }
- }
- }
- return false;
-}
-
-bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements,
- size_t slot) {
- WebGamepad& pad = pad_state_[slot].data;
- AssociatedData& associated = associated_[slot];
- CHECK(!associated.is_xbox);
-
- pad.axesLength = 0;
- pad.buttonsLength = 0;
- pad.timestamp = 0;
- memset(pad.axes, 0, sizeof(pad.axes));
- memset(pad.buttons, 0, sizeof(pad.buttons));
-
- bool mapped_all_axes = true;
-
- for (id elem in elements) {
- IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
- if (!CheckCollection(element))
- continue;
-
- uint32_t usage_page = IOHIDElementGetUsagePage(element);
- uint32_t usage = IOHIDElementGetUsage(element);
- if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button &&
- usage_page == kButtonUsagePage) {
- uint32_t button_index = usage - 1;
- if (button_index < WebGamepad::buttonsLengthCap) {
- associated.hid.button_elements[button_index] = element;
- pad.buttonsLength = std::max(pad.buttonsLength, button_index + 1);
- }
- }
- else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) {
- uint32_t axis_index = usage - kAxisMinimumUsageNumber;
- if (axis_index < WebGamepad::axesLengthCap) {
- associated.hid.axis_elements[axis_index] = element;
- pad.axesLength = std::max(pad.axesLength, axis_index + 1);
- } else {
- mapped_all_axes = false;
- }
- }
- }
-
- if (!mapped_all_axes) {
- // For axes who's usage puts them outside the standard axesLengthCap range.
- uint32_t next_index = 0;
- for (id elem in elements) {
- IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
- if (!CheckCollection(element))
- continue;
-
- uint32_t usage_page = IOHIDElementGetUsagePage(element);
- uint32_t usage = IOHIDElementGetUsage(element);
- if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc &&
- usage - kAxisMinimumUsageNumber >= WebGamepad::axesLengthCap &&
- usage_page <= kGameControlsUsagePage) {
- for (; next_index < WebGamepad::axesLengthCap; ++next_index) {
- if (associated.hid.axis_elements[next_index] == NULL)
- break;
- }
- if (next_index < WebGamepad::axesLengthCap) {
- associated.hid.axis_elements[next_index] = element;
- pad.axesLength = std::max(pad.axesLength, next_index + 1);
- }
- }
-
- if (next_index >= WebGamepad::axesLengthCap)
- break;
- }
- }
-
- for (uint32_t axis_index = 0; axis_index < pad.axesLength; ++axis_index) {
- IOHIDElementRef element = associated.hid.axis_elements[axis_index];
- if (element != NULL) {
- CFIndex axis_min = IOHIDElementGetLogicalMin(element);
- CFIndex axis_max = IOHIDElementGetLogicalMax(element);
-
- // Some HID axes report a logical range of -1 to 0 signed, which must be
- // interpreted as 0 to -1 unsigned for correct normalization behavior.
- if (axis_min == -1 && axis_max == 0) {
- axis_max = -1;
- axis_min = 0;
- }
-
- associated.hid.axis_minimums[axis_index] = axis_min;
- associated.hid.axis_maximums[axis_index] = axis_max;
- associated.hid.axis_report_sizes[axis_index] =
- IOHIDElementGetReportSize(element);
- }
- }
-
- return (pad.axesLength > 0 || pad.buttonsLength > 0);
-}
-
-size_t GamepadPlatformDataFetcherMac::GetEmptySlot() {
- // Find a free slot for this device.
- for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
- if (!pad_state_[slot].data.connected)
- return slot;
- }
- return WebGamepads::itemsLengthCap;
-}
-
-size_t GamepadPlatformDataFetcherMac::GetSlotForDevice(IOHIDDeviceRef device) {
- for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
- // If we already have this device, and it's already connected, don't do
- // anything now.
- if (pad_state_[slot].data.connected &&
- !associated_[slot].is_xbox &&
- associated_[slot].hid.device_ref == device)
- return WebGamepads::itemsLengthCap;
- }
- return GetEmptySlot();
-}
-
-size_t GamepadPlatformDataFetcherMac::GetSlotForXboxDevice(
- XboxController* device) {
- for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
- if (associated_[slot].is_xbox &&
- associated_[slot].xbox.location_id == device->location_id()) {
- if (pad_state_[slot].data.connected) {
- // The device is already connected. No idea why we got a second "device
- // added" call, but let's not add it twice.
- DCHECK_EQ(associated_[slot].xbox.device, device);
- return WebGamepads::itemsLengthCap;
- } else {
- // A device with the same location ID was previously connected, so put
- // it in the same slot.
- return slot;
- }
- }
- }
- return GetEmptySlot();
-}
-
-void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) {
- using base::mac::CFToNSCast;
- using base::mac::CFCastStrict;
-
- if (!enabled_)
- return;
-
- // Find an index for this device.
- size_t slot = GetSlotForDevice(device);
-
- // We can't handle this many connected devices.
- if (slot == WebGamepads::itemsLengthCap)
- return;
-
- // Clear some state that may have been left behind by previous gamepads
- memset(&associated_[slot], 0, sizeof(AssociatedData));
-
- NSNumber* vendor_id = CFToNSCast(CFCastStrict<CFNumberRef>(
- IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey))));
- NSNumber* product_id = CFToNSCast(CFCastStrict<CFNumberRef>(
- IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey))));
- NSString* product = CFToNSCast(CFCastStrict<CFStringRef>(
- IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))));
- int vendor_int = [vendor_id intValue];
- int product_int = [product_id intValue];
-
- char vendor_as_str[5], product_as_str[5];
- snprintf(vendor_as_str, sizeof(vendor_as_str), "%04x", vendor_int);
- snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int);
- pad_state_[slot].mapper =
- GetGamepadStandardMappingFunction(vendor_as_str, product_as_str);
-
- NSString* ident = [NSString stringWithFormat:
- @"%@ (%sVendor: %04x Product: %04x)",
- product,
- pad_state_[slot].mapper ? "STANDARD GAMEPAD " : "",
- vendor_int,
- product_int];
- CopyNSStringAsUTF16LittleEndian(
- ident,
- pad_state_[slot].data.id,
- sizeof(pad_state_[slot].data.id));
-
- if (pad_state_[slot].mapper) {
- CopyNSStringAsUTF16LittleEndian(
- @"standard",
- pad_state_[slot].data.mapping,
- sizeof(pad_state_[slot].data.mapping));
- } else {
- pad_state_[slot].data.mapping[0] = 0;
- }
-
- base::ScopedCFTypeRef<CFArrayRef> elements(
- IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone));
-
- if (!AddButtonsAndAxes(CFToNSCast(elements), slot))
- return;
-
- associated_[slot].hid.device_ref = device;
- pad_state_[slot].data.connected = true;
- pad_state_[slot].axis_mask = 0;
- pad_state_[slot].button_mask = 0;
-}
-
-void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) {
- if (!enabled_)
- return;
-
- // Find the index for this device.
- size_t slot;
- for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
- if (pad_state_[slot].data.connected &&
- !associated_[slot].is_xbox &&
- associated_[slot].hid.device_ref == device)
- break;
- }
- DCHECK(slot < WebGamepads::itemsLengthCap);
- // Leave associated device_ref so that it will be reconnected in the same
- // location. Simply mark it as disconnected.
- pad_state_[slot].data.connected = false;
-}
-
-void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) {
- if (!enabled_ || paused_)
- return;
-
- IOHIDElementRef element = IOHIDValueGetElement(value);
- IOHIDDeviceRef device = IOHIDElementGetDevice(element);
-
- // Find device slot.
- size_t slot;
- for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
- if (pad_state_[slot].data.connected &&
- !associated_[slot].is_xbox &&
- associated_[slot].hid.device_ref == device)
- break;
- }
- if (slot == WebGamepads::itemsLengthCap)
- return;
-
- WebGamepad& pad = pad_state_[slot].data;
- AssociatedData& associated = associated_[slot];
-
- uint32_t value_length = IOHIDValueGetLength(value);
- if (value_length > 4) {
- // Workaround for bizarre issue with PS3 controllers that try to return
- // massive (30+ byte) values and crash IOHIDValueGetIntegerValue
- return;
- }
-
- // Find and fill in the associated button event, if any.
- for (size_t i = 0; i < pad.buttonsLength; ++i) {
- if (associated.hid.button_elements[i] == element) {
- pad.buttons[i].pressed = IOHIDValueGetIntegerValue(value);
- pad.buttons[i].value = pad.buttons[i].pressed ? 1.f : 0.f;
- pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value));
- return;
- }
- }
-
- // Find and fill in the associated axis event, if any.
- for (size_t i = 0; i < pad.axesLength; ++i) {
- if (associated.hid.axis_elements[i] == element) {
- CFIndex axis_min = associated.hid.axis_minimums[i];
- CFIndex axis_max = associated.hid.axis_maximums[i];
- CFIndex axis_value = IOHIDValueGetIntegerValue(value);
-
- if (axis_min > axis_max) {
- // We'll need to interpret this axis as unsigned during normalization.
- switch (associated.hid.axis_report_sizes[i]) {
- case 8:
- pad.axes[i] = NormalizeUInt8Axis(axis_value, axis_min, axis_max);
- break;
- case 16:
- pad.axes[i] = NormalizeUInt16Axis(axis_value, axis_min, axis_max);
- break;
- case 32:
- pad.axes[i] = NormalizeUInt32Axis(axis_value, axis_min, axis_max);
- break;
- }
- } else {
- pad.axes[i] = NormalizeAxis(axis_value, axis_min, axis_max);
- }
-
- pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value));
- return;
- }
- }
-}
-
-void GamepadPlatformDataFetcherMac::XboxDeviceAdd(XboxController* device) {
- if (!enabled_)
- return;
-
- size_t slot = GetSlotForXboxDevice(device);
-
- // We can't handle this many connected devices.
- if (slot == WebGamepads::itemsLengthCap)
- return;
-
- device->SetLEDPattern(
- (XboxController::LEDPattern)(XboxController::LED_FLASH_TOP_LEFT + slot));
-
- NSString* ident =
- [NSString stringWithFormat:
- @"%@ (STANDARD GAMEPAD Vendor: %04x Product: %04x)",
- device->GetControllerType() == XboxController::XBOX_360_CONTROLLER
- ? @"Xbox 360 Controller"
- : @"Xbox One Controller",
- device->GetProductId(), device->GetVendorId()];
- CopyNSStringAsUTF16LittleEndian(
- ident,
- pad_state_[slot].data.id,
- sizeof(pad_state_[slot].data.id));
-
- CopyNSStringAsUTF16LittleEndian(
- @"standard",
- pad_state_[slot].data.mapping,
- sizeof(pad_state_[slot].data.mapping));
-
- associated_[slot].is_xbox = true;
- associated_[slot].xbox.device = device;
- associated_[slot].xbox.location_id = device->location_id();
- pad_state_[slot].data.connected = true;
- pad_state_[slot].data.axesLength = 4;
- pad_state_[slot].data.buttonsLength = 17;
- pad_state_[slot].data.timestamp = 0;
- pad_state_[slot].mapper = 0;
- pad_state_[slot].axis_mask = 0;
- pad_state_[slot].button_mask = 0;
-}
-
-void GamepadPlatformDataFetcherMac::XboxDeviceRemove(XboxController* device) {
- if (!enabled_)
- return;
-
- // Find the index for this device.
- size_t slot;
- for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
- if (pad_state_[slot].data.connected &&
- associated_[slot].is_xbox &&
- associated_[slot].xbox.device == device)
- break;
- }
- DCHECK(slot < WebGamepads::itemsLengthCap);
- // Leave associated location id so that the controller will be reconnected in
- // the same slot if it is plugged in again. Simply mark it as disconnected.
- pad_state_[slot].data.connected = false;
-}
-
-void GamepadPlatformDataFetcherMac::XboxValueChanged(
- XboxController* device, const XboxController::Data& data) {
- // Find device slot.
- size_t slot;
- for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) {
- if (pad_state_[slot].data.connected &&
- associated_[slot].is_xbox &&
- associated_[slot].xbox.device == device)
- break;
- }
- if (slot == WebGamepads::itemsLengthCap)
- return;
-
- WebGamepad& pad = pad_state_[slot].data;
-
- for (size_t i = 0; i < 6; i++) {
- pad.buttons[i].pressed = data.buttons[i];
- pad.buttons[i].value = data.buttons[i] ? 1.0f : 0.0f;
- }
- pad.buttons[6].pressed = data.triggers[0] > kDefaultButtonPressedThreshold;
- pad.buttons[6].value = data.triggers[0];
- pad.buttons[7].pressed = data.triggers[1] > kDefaultButtonPressedThreshold;
- pad.buttons[7].value = data.triggers[1];
- for (size_t i = 8; i < 17; i++) {
- pad.buttons[i].pressed = data.buttons[i - 2];
- pad.buttons[i].value = data.buttons[i - 2] ? 1.0f : 0.0f;
- }
- for (size_t i = 0; i < arraysize(data.axes); i++) {
- pad.axes[i] = data.axes[i];
- }
-
- pad.timestamp = base::TimeTicks::Now().ToInternalValue();
-}
-
-void GamepadPlatformDataFetcherMac::GetGamepadData(WebGamepads* pads, bool) {
- if (!enabled_ && !xbox_fetcher_) {
- pads->length = 0;
- return;
- }
-
- pads->length = WebGamepads::itemsLengthCap;
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i)
- MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
deleted file mode 100644
index c761e83858f..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
+++ /dev/null
@@ -1,352 +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/gamepad/gamepad_platform_data_fetcher_win.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/trace_event.h"
-#include "base/win/windows_version.h"
-#include "content/common/gamepad_hardware_buffer.h"
-#include "content/common/gamepad_messages.h"
-
-namespace content {
-
-using namespace blink;
-
-namespace {
-
-// See http://goo.gl/5VSJR. These are not available in all versions of the
-// header, but they can be returned from the driver, so we define our own
-// versions here.
-static const BYTE kDeviceSubTypeGamepad = 1;
-static const BYTE kDeviceSubTypeWheel = 2;
-static const BYTE kDeviceSubTypeArcadeStick = 3;
-static const BYTE kDeviceSubTypeFlightStick = 4;
-static const BYTE kDeviceSubTypeDancePad = 5;
-static const BYTE kDeviceSubTypeGuitar = 6;
-static const BYTE kDeviceSubTypeGuitarAlternate = 7;
-static const BYTE kDeviceSubTypeDrumKit = 8;
-static const BYTE kDeviceSubTypeGuitarBass = 11;
-static const BYTE kDeviceSubTypeArcadePad = 19;
-
-float NormalizeXInputAxis(SHORT value) {
- return ((value + 32768.f) / 32767.5f) - 1.f;
-}
-
-const WebUChar* GamepadSubTypeName(BYTE sub_type) {
- switch (sub_type) {
- case kDeviceSubTypeGamepad: return L"GAMEPAD";
- case kDeviceSubTypeWheel: return L"WHEEL";
- case kDeviceSubTypeArcadeStick: return L"ARCADE_STICK";
- case kDeviceSubTypeFlightStick: return L"FLIGHT_STICK";
- case kDeviceSubTypeDancePad: return L"DANCE_PAD";
- case kDeviceSubTypeGuitar: return L"GUITAR";
- case kDeviceSubTypeGuitarAlternate: return L"GUITAR_ALTERNATE";
- case kDeviceSubTypeDrumKit: return L"DRUM_KIT";
- case kDeviceSubTypeGuitarBass: return L"GUITAR_BASS";
- case kDeviceSubTypeArcadePad: return L"ARCADE_PAD";
- default: return L"<UNKNOWN>";
- }
-}
-
-const WebUChar* XInputDllFileName() {
- // Xinput.h defines filename (XINPUT_DLL) on different Windows versions, but
- // Xinput.h specifies it in build time. Approach here uses the same values
- // and it is resolving dll filename based on Windows version it is running on.
- if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
- // For Windows 8 and 10, XINPUT_DLL is xinput1_4.dll.
- return FILE_PATH_LITERAL("xinput1_4.dll");
- } else if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
- return FILE_PATH_LITERAL("xinput9_1_0.dll");
- } else {
- NOTREACHED();
- return nullptr;
- }
-}
-
-} // namespace
-
-GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin()
- : xinput_dll_(base::FilePath(XInputDllFileName())),
- xinput_available_(GetXInputDllFunctions()) {
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- platform_pad_state_[i].status = DISCONNECTED;
- pad_state_[i].mapper = NULL;
- pad_state_[i].axis_mask = 0;
- pad_state_[i].button_mask = 0;
- }
-
- raw_input_fetcher_.reset(new RawInputDataFetcher());
- raw_input_fetcher_->StartMonitor();
-}
-
-GamepadPlatformDataFetcherWin::~GamepadPlatformDataFetcherWin() {
- raw_input_fetcher_->StopMonitor();
-}
-
-int GamepadPlatformDataFetcherWin::FirstAvailableGamepadId() const {
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- if (platform_pad_state_[i].status == DISCONNECTED)
- return i;
- }
- return -1;
-}
-
-bool GamepadPlatformDataFetcherWin::HasXInputGamepad(int index) const {
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- if (platform_pad_state_[i].status == XINPUT_CONNECTED &&
- platform_pad_state_[i].xinput_index == index)
- return true;
- }
- return false;
-}
-
-bool GamepadPlatformDataFetcherWin::HasRawInputGamepad(
- const HANDLE handle) const {
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- if (platform_pad_state_[i].status == RAWINPUT_CONNECTED &&
- platform_pad_state_[i].raw_input_handle == handle)
- return true;
- }
- return false;
-}
-
-void GamepadPlatformDataFetcherWin::EnumerateDevices() {
- TRACE_EVENT0("GAMEPAD", "EnumerateDevices");
-
- // Mark all disconnected pads DISCONNECTED.
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- if (!pad_state_[i].data.connected)
- platform_pad_state_[i].status = DISCONNECTED;
- }
-
- for (size_t i = 0; i < XUSER_MAX_COUNT; ++i) {
- if (HasXInputGamepad(i))
- continue;
- int pad_index = FirstAvailableGamepadId();
- if (pad_index == -1)
- return; // We can't add any more gamepads.
- WebGamepad& pad = pad_state_[pad_index].data;
- if (xinput_available_ && GetXInputPadConnectivity(i, &pad)) {
- platform_pad_state_[pad_index].status = XINPUT_CONNECTED;
- platform_pad_state_[pad_index].xinput_index = i;
- pad_state_[pad_index].mapper = NULL;
- pad_state_[pad_index].axis_mask = 0;
- pad_state_[pad_index].button_mask = 0;
- }
- }
-
- if (raw_input_fetcher_->Available()) {
- std::vector<RawGamepadInfo*> raw_inputs =
- raw_input_fetcher_->EnumerateDevices();
- for (size_t i = 0; i < raw_inputs.size(); ++i) {
- RawGamepadInfo* gamepad = raw_inputs[i];
- if (gamepad->buttons_length == 0 && gamepad->axes_length == 0)
- continue;
- if (HasRawInputGamepad(gamepad->handle))
- continue;
- int pad_index = FirstAvailableGamepadId();
- if (pad_index == -1)
- return;
- WebGamepad& pad = pad_state_[pad_index].data;
- pad.connected = true;
- PadState& state = pad_state_[pad_index];
- PlatformPadState& platform_state = platform_pad_state_[pad_index];
- platform_state.status = RAWINPUT_CONNECTED;
- platform_state.raw_input_handle = gamepad->handle;
-
- std::string vendor = base::StringPrintf("%04x", gamepad->vendor_id);
- std::string product = base::StringPrintf("%04x", gamepad->product_id);
- state.mapper = GetGamepadStandardMappingFunction(vendor, product);
- state.axis_mask = 0;
- state.button_mask = 0;
-
- swprintf(pad.id, WebGamepad::idLengthCap,
- L"%ls (%lsVendor: %04x Product: %04x)",
- gamepad->id, state.mapper ? L"STANDARD GAMEPAD " : L"",
- gamepad->vendor_id, gamepad->product_id);
-
- if (state.mapper)
- swprintf(pad.mapping, WebGamepad::mappingLengthCap, L"standard");
- else
- pad.mapping[0] = 0;
- }
- }
-}
-
-void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads,
- bool devices_changed_hint) {
- TRACE_EVENT0("GAMEPAD", "GetGamepadData");
-
- if (!xinput_available_ &&
- !raw_input_fetcher_->Available()) {
- pads->length = 0;
- return;
- }
-
- // A note on XInput devices:
- // If we got notification that system devices have been updated, then
- // run GetCapabilities to update the connected status and the device
- // identifier. It can be slow to do to both GetCapabilities and
- // GetState on unconnected devices, so we want to avoid a 2-5ms pause
- // here by only doing this when the devices are updated (despite
- // documentation claiming it's OK to call it any time).
- if (devices_changed_hint)
- EnumerateDevices();
-
- pads->length = 0;
-
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- // We rely on device_changed and GetCapabilities to tell us that
- // something's been connected, but we will mark as disconnected if
- // Get___PadState returns that we've lost the pad.
- if (!pad_state_[i].data.connected)
- continue;
-
- if (platform_pad_state_[i].status == XINPUT_CONNECTED)
- GetXInputPadData(i, &pad_state_[i].data);
- else if (platform_pad_state_[i].status == RAWINPUT_CONNECTED)
- GetRawInputPadData(i, &pad_state_[i].data);
-
- MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]);
-
- if (pads->items[i].connected)
- pads->length++;
- }
-}
-
-void GamepadPlatformDataFetcherWin::PauseHint(bool pause) {
- if (pause)
- raw_input_fetcher_->StopMonitor();
- else
- raw_input_fetcher_->StartMonitor();
-}
-
-bool GamepadPlatformDataFetcherWin::GetXInputPadConnectivity(
- int i,
- WebGamepad* pad) const {
- DCHECK(pad);
- TRACE_EVENT1("GAMEPAD", "GetXInputPadConnectivity", "id", i);
- XINPUT_CAPABILITIES caps;
- DWORD res = xinput_get_capabilities_(i, XINPUT_FLAG_GAMEPAD, &caps);
- if (res == ERROR_DEVICE_NOT_CONNECTED) {
- pad->connected = false;
- return false;
- } else {
- pad->connected = true;
- swprintf(pad->id,
- WebGamepad::idLengthCap,
- L"Xbox 360 Controller (XInput STANDARD %ls)",
- GamepadSubTypeName(caps.SubType));
- swprintf(pad->mapping, WebGamepad::mappingLengthCap, L"standard");
- return true;
- }
-}
-
-void GamepadPlatformDataFetcherWin::GetXInputPadData(
- int i,
- WebGamepad* pad) {
- XINPUT_STATE state;
- memset(&state, 0, sizeof(XINPUT_STATE));
- TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i);
- DWORD dwResult = xinput_get_state_(platform_pad_state_[i].xinput_index,
- &state);
- TRACE_EVENT_END1("GAMEPAD", "XInputGetState", "id", i);
-
- if (dwResult == ERROR_SUCCESS) {
- pad->timestamp = state.dwPacketNumber;
- pad->buttonsLength = 0;
- WORD val = state.Gamepad.wButtons;
-#define ADD(b) pad->buttons[pad->buttonsLength].pressed = (val & (b)) != 0; \
- pad->buttons[pad->buttonsLength++].value = ((val & (b)) ? 1.f : 0.f);
- ADD(XINPUT_GAMEPAD_A);
- ADD(XINPUT_GAMEPAD_B);
- ADD(XINPUT_GAMEPAD_X);
- ADD(XINPUT_GAMEPAD_Y);
- ADD(XINPUT_GAMEPAD_LEFT_SHOULDER);
- ADD(XINPUT_GAMEPAD_RIGHT_SHOULDER);
-
- pad->buttons[pad->buttonsLength].pressed =
- state.Gamepad.bLeftTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
- pad->buttons[pad->buttonsLength++].value =
- state.Gamepad.bLeftTrigger / 255.f;
-
- pad->buttons[pad->buttonsLength].pressed =
- state.Gamepad.bRightTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
- pad->buttons[pad->buttonsLength++].value =
- state.Gamepad.bRightTrigger / 255.f;
-
- ADD(XINPUT_GAMEPAD_BACK);
- ADD(XINPUT_GAMEPAD_START);
- ADD(XINPUT_GAMEPAD_LEFT_THUMB);
- ADD(XINPUT_GAMEPAD_RIGHT_THUMB);
- ADD(XINPUT_GAMEPAD_DPAD_UP);
- ADD(XINPUT_GAMEPAD_DPAD_DOWN);
- ADD(XINPUT_GAMEPAD_DPAD_LEFT);
- ADD(XINPUT_GAMEPAD_DPAD_RIGHT);
-#undef ADD
- pad->axesLength = 0;
-
- float value = 0.0;
-#define ADD(a, factor) value = factor * NormalizeXInputAxis(a); \
- pad->axes[pad->axesLength++] = value;
-
- // XInput are +up/+right, -down/-left, we want -up/-left.
- ADD(state.Gamepad.sThumbLX, 1);
- ADD(state.Gamepad.sThumbLY, -1);
- ADD(state.Gamepad.sThumbRX, 1);
- ADD(state.Gamepad.sThumbRY, -1);
-#undef ADD
- } else {
- pad->connected = false;
- }
-}
-
-void GamepadPlatformDataFetcherWin::GetRawInputPadData(
- int index,
- WebGamepad* pad) {
- RawGamepadInfo* gamepad = raw_input_fetcher_->GetGamepadInfo(
- platform_pad_state_[index].raw_input_handle);
- if (!gamepad) {
- pad->connected = false;
- return;
- }
-
- pad->timestamp = gamepad->report_id;
- pad->buttonsLength = gamepad->buttons_length;
- pad->axesLength = gamepad->axes_length;
-
- for (unsigned int i = 0; i < pad->buttonsLength; i++) {
- pad->buttons[i].pressed = gamepad->buttons[i];
- pad->buttons[i].value = gamepad->buttons[i] ? 1.0 : 0.0;
- }
-
- for (unsigned int i = 0; i < pad->axesLength; i++)
- pad->axes[i] = gamepad->axes[i].value;
-}
-
-bool GamepadPlatformDataFetcherWin::GetXInputDllFunctions() {
- xinput_get_capabilities_ = NULL;
- xinput_get_state_ = NULL;
- XInputEnableFunc xinput_enable = reinterpret_cast<XInputEnableFunc>(
- xinput_dll_.GetFunctionPointer("XInputEnable"));
- xinput_get_capabilities_ = reinterpret_cast<XInputGetCapabilitiesFunc>(
- xinput_dll_.GetFunctionPointer("XInputGetCapabilities"));
- if (!xinput_get_capabilities_)
- return false;
- xinput_get_state_ = reinterpret_cast<XInputGetStateFunc>(
- xinput_dll_.GetFunctionPointer("XInputGetState"));
- if (!xinput_get_state_)
- return false;
- if (xinput_enable) {
- // XInputEnable is unavailable before Win8 and deprecated in Win10.
- xinput_enable(true);
- }
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
deleted file mode 100644
index 4fbd1cf0ce7..00000000000
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.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_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_WIN_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_WIN_H_
-
-#include <memory>
-
-#include "build/build_config.h"
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <stdlib.h>
-#include <Unknwn.h>
-#include <WinDef.h>
-#include <windows.h>
-#include <XInput.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/scoped_native_library.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-#include "content/browser/gamepad/gamepad_standard_mappings.h"
-#include "content/browser/gamepad/raw_input_data_fetcher_win.h"
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-
-namespace content {
-
-class GamepadPlatformDataFetcherWin : public GamepadDataFetcher {
- public:
- GamepadPlatformDataFetcherWin();
- ~GamepadPlatformDataFetcherWin() override;
- void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) override;
- void PauseHint(bool paused) override;
-
- private:
- // XInput-specific implementation for GetGamepadData.
- bool GetXInputGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint);
-
- // The three function types we use from xinput1_3.dll.
- typedef void (WINAPI *XInputEnableFunc)(BOOL enable);
- typedef DWORD (WINAPI *XInputGetCapabilitiesFunc)(
- DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities);
- typedef DWORD (WINAPI *XInputGetStateFunc)(
- DWORD dwUserIndex, XINPUT_STATE* pState);
-
- // Get functions from dynamically loading the xinput dll.
- // Returns true if loading was successful.
- bool GetXInputDllFunctions();
-
- // Scan for connected XInput and DirectInput gamepads.
- void EnumerateDevices();
- bool GetXInputPadConnectivity(int i, blink::WebGamepad* pad) const;
-
- void GetXInputPadData(int i, blink::WebGamepad* pad);
- void GetRawInputPadData(int i, blink::WebGamepad* pad);
-
- int FirstAvailableGamepadId() const;
- bool HasXInputGamepad(int index) const;
- bool HasRawInputGamepad(const HANDLE handle) const;
-
- base::ScopedNativeLibrary xinput_dll_;
- bool xinput_available_;
-
- // Function pointers to XInput functionality, retrieved in
- // |GetXinputDllFunctions|.
- XInputGetCapabilitiesFunc xinput_get_capabilities_;
- XInputGetStateFunc xinput_get_state_;
-
- enum PadConnectionStatus {
- DISCONNECTED,
- XINPUT_CONNECTED,
- RAWINPUT_CONNECTED
- };
-
- struct PlatformPadState {
- PadConnectionStatus status;
-
- int xinput_index; // XInput-only
- HANDLE raw_input_handle; // RawInput-only fields.
- };
- PlatformPadState platform_pad_state_[blink::WebGamepads::itemsLengthCap];
-
- std::unique_ptr<RawInputDataFetcher> raw_input_fetcher_;
-
- DISALLOW_COPY_AND_ASSIGN(GamepadPlatformDataFetcherWin);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_WIN_H_
diff --git a/chromium/content/browser/gamepad/gamepad_provider.cc b/chromium/content/browser/gamepad/gamepad_provider.cc
deleted file mode 100644
index 46796150a80..00000000000
--- a/chromium/content/browser/gamepad/gamepad_provider.cc
+++ /dev/null
@@ -1,334 +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/gamepad/gamepad_provider.h"
-
-#include <stddef.h>
-#include <string.h>
-#include <cmath>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/single_thread_task_runner.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-#include "content/browser/gamepad/gamepad_platform_data_fetcher.h"
-#include "content/browser/gamepad/gamepad_service.h"
-#include "content/common/gamepad_hardware_buffer.h"
-#include "content/common/gamepad_messages.h"
-#include "content/common/gamepad_user_gesture.h"
-#include "content/public/browser/browser_thread.h"
-
-using blink::WebGamepad;
-using blink::WebGamepads;
-
-namespace content {
-
-GamepadProvider::ClosureAndThread::ClosureAndThread(
- const base::Closure& c,
- const scoped_refptr<base::SingleThreadTaskRunner>& m)
- : closure(c), task_runner(m) {
-}
-
-GamepadProvider::ClosureAndThread::ClosureAndThread(
- const ClosureAndThread& other) = default;
-
-GamepadProvider::ClosureAndThread::~ClosureAndThread() {
-}
-
-GamepadProvider::GamepadProvider()
- : is_paused_(true),
- have_scheduled_do_poll_(false),
- devices_changed_(true),
- ever_had_user_gesture_(false) {
- Initialize(std::unique_ptr<GamepadDataFetcher>());
-}
-
-GamepadProvider::GamepadProvider(std::unique_ptr<GamepadDataFetcher> fetcher)
- : is_paused_(true),
- have_scheduled_do_poll_(false),
- devices_changed_(true),
- ever_had_user_gesture_(false) {
- Initialize(std::move(fetcher));
-}
-
-GamepadProvider::~GamepadProvider() {
- base::SystemMonitor* monitor = base::SystemMonitor::Get();
- if (monitor)
- monitor->RemoveDevicesChangedObserver(this);
-
- // Use Stop() to join the polling thread, as there may be pending callbacks
- // which dereference |polling_thread_|.
- polling_thread_->Stop();
- data_fetcher_.reset();
-}
-
-base::SharedMemoryHandle GamepadProvider::GetSharedMemoryHandleForProcess(
- base::ProcessHandle process) {
- base::SharedMemoryHandle renderer_handle;
- gamepad_shared_memory_.ShareToProcess(process, &renderer_handle);
- return renderer_handle;
-}
-
-void GamepadProvider::GetCurrentGamepadData(WebGamepads* data) {
- const WebGamepads& pads = SharedMemoryAsHardwareBuffer()->buffer;
- base::AutoLock lock(shared_memory_lock_);
- *data = pads;
-}
-
-void GamepadProvider::Pause() {
- {
- base::AutoLock lock(is_paused_lock_);
- is_paused_ = true;
- }
- base::MessageLoop* polling_loop = polling_thread_->message_loop();
- polling_loop->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&GamepadProvider::SendPauseHint, Unretained(this), true));
-}
-
-void GamepadProvider::Resume() {
- {
- base::AutoLock lock(is_paused_lock_);
- if (!is_paused_)
- return;
- is_paused_ = false;
- }
-
- base::MessageLoop* polling_loop = polling_thread_->message_loop();
- polling_loop->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&GamepadProvider::SendPauseHint, Unretained(this), false));
- polling_loop->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&GamepadProvider::ScheduleDoPoll, Unretained(this)));
-}
-
-void GamepadProvider::RegisterForUserGesture(const base::Closure& closure) {
- base::AutoLock lock(user_gesture_lock_);
- user_gesture_observers_.push_back(
- ClosureAndThread(closure, base::MessageLoop::current()->task_runner()));
-}
-
-void GamepadProvider::OnDevicesChanged(base::SystemMonitor::DeviceType type) {
- base::AutoLock lock(devices_changed_lock_);
- devices_changed_ = true;
-}
-
-void GamepadProvider::Initialize(std::unique_ptr<GamepadDataFetcher> fetcher) {
- size_t data_size = sizeof(GamepadHardwareBuffer);
- base::SystemMonitor* monitor = base::SystemMonitor::Get();
- if (monitor)
- monitor->AddDevicesChangedObserver(this);
- bool res = gamepad_shared_memory_.CreateAndMapAnonymous(data_size);
- CHECK(res);
- GamepadHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer();
- memset(hwbuf, 0, sizeof(GamepadHardwareBuffer));
- pad_states_.reset(new PadState[WebGamepads::itemsLengthCap]);
-
- polling_thread_.reset(new base::Thread("Gamepad polling thread"));
-#if defined(OS_LINUX)
- // On Linux, the data fetcher needs to watch file descriptors, so the message
- // loop needs to be a libevent loop.
- const base::MessageLoop::Type kMessageLoopType = base::MessageLoop::TYPE_IO;
-#elif defined(OS_ANDROID)
- // On Android, keeping a message loop of default type.
- const base::MessageLoop::Type kMessageLoopType =
- base::MessageLoop::TYPE_DEFAULT;
-#else
- // On Mac, the data fetcher uses IOKit which depends on CFRunLoop, so the
- // message loop needs to be a UI-type loop. On Windows it must be a UI loop
- // to properly pump the MessageWindow that captures device state.
- const base::MessageLoop::Type kMessageLoopType = base::MessageLoop::TYPE_UI;
-#endif
- polling_thread_->StartWithOptions(base::Thread::Options(kMessageLoopType, 0));
-
- polling_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&GamepadProvider::DoInitializePollingThread,
- base::Unretained(this), base::Passed(&fetcher)));
-}
-
-void GamepadProvider::DoInitializePollingThread(
- std::unique_ptr<GamepadDataFetcher> fetcher) {
- DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
- DCHECK(!data_fetcher_.get()); // Should only initialize once.
-
- if (!fetcher)
- fetcher.reset(new GamepadPlatformDataFetcher);
- data_fetcher_ = std::move(fetcher);
-}
-
-void GamepadProvider::SendPauseHint(bool paused) {
- DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
- if (data_fetcher_)
- data_fetcher_->PauseHint(paused);
-}
-
-bool GamepadProvider::PadState::Match(const WebGamepad& pad) const {
- return connected_ == pad.connected &&
- axes_length_ == pad.axesLength &&
- buttons_length_ == pad.buttonsLength &&
- memcmp(id_, pad.id, sizeof(id_)) == 0 &&
- memcmp(mapping_, pad.mapping, sizeof(mapping_)) == 0;
-}
-
-void GamepadProvider::PadState::SetPad(const WebGamepad& pad) {
- connected_ = pad.connected;
- axes_length_ = pad.axesLength;
- buttons_length_ = pad.buttonsLength;
- memcpy(id_, pad.id, sizeof(id_));
- memcpy(mapping_, pad.mapping, sizeof(mapping_));
-}
-
-void GamepadProvider::PadState::SetDisconnected() {
- connected_ = false;
- axes_length_ = 0;
- buttons_length_ = 0;
- memset(id_, 0, sizeof(id_));
- memset(mapping_, 0, sizeof(mapping_));
-}
-
-void GamepadProvider::PadState::AsWebGamepad(WebGamepad* pad) {
- pad->connected = connected_;
- pad->axesLength = axes_length_;
- pad->buttonsLength = buttons_length_;
- memcpy(pad->id, id_, sizeof(id_));
- memcpy(pad->mapping, mapping_, sizeof(mapping_));
- memset(pad->axes, 0, sizeof(pad->axes));
- memset(pad->buttons, 0, sizeof(pad->buttons));
-}
-
-void GamepadProvider::DoPoll() {
- DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
- DCHECK(have_scheduled_do_poll_);
- have_scheduled_do_poll_ = false;
-
- bool changed;
- GamepadHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer();
-
- ANNOTATE_BENIGN_RACE_SIZED(
- &hwbuf->buffer,
- sizeof(WebGamepads),
- "Racey reads are discarded");
-
- {
- base::AutoLock lock(devices_changed_lock_);
- changed = devices_changed_;
- devices_changed_ = false;
- }
-
- {
- base::AutoLock lock(shared_memory_lock_);
-
- // Acquire the SeqLock. There is only ever one writer to this data.
- // See gamepad_hardware_buffer.h.
- hwbuf->sequence.WriteBegin();
- data_fetcher_->GetGamepadData(&hwbuf->buffer, changed);
- hwbuf->sequence.WriteEnd();
- }
-
- if (ever_had_user_gesture_) {
- for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- WebGamepad& pad = hwbuf->buffer.items[i];
- PadState& state = pad_states_.get()[i];
- if (pad.connected && !state.connected()) {
- OnGamepadConnectionChange(true, i, pad);
- } else if (!pad.connected && state.connected()) {
- OnGamepadConnectionChange(false, i, pad);
- } else if (pad.connected && state.connected() && !state.Match(pad)) {
- WebGamepad old_pad;
- state.AsWebGamepad(&old_pad);
- OnGamepadConnectionChange(false, i, old_pad);
- OnGamepadConnectionChange(true, i, pad);
- }
- }
- }
-
- CheckForUserGesture();
-
- // Schedule our next interval of polling.
- ScheduleDoPoll();
-}
-
-void GamepadProvider::ScheduleDoPoll() {
- DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
- if (have_scheduled_do_poll_)
- return;
-
- {
- base::AutoLock lock(is_paused_lock_);
- if (is_paused_)
- return;
- }
-
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&GamepadProvider::DoPoll, Unretained(this)),
- base::TimeDelta::FromMilliseconds(kDesiredSamplingIntervalMs));
- have_scheduled_do_poll_ = true;
-}
-
-void GamepadProvider::OnGamepadConnectionChange(
- bool connected, int index, const WebGamepad& pad) {
- PadState& state = pad_states_.get()[index];
- if (connected)
- state.SetPad(pad);
- else
- state.SetDisconnected();
-
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&GamepadProvider::DispatchGamepadConnectionChange,
- base::Unretained(this),
- connected,
- index,
- pad));
-}
-
-void GamepadProvider::DispatchGamepadConnectionChange(
- bool connected, int index, const WebGamepad& pad) {
- if (connected)
- GamepadService::GetInstance()->OnGamepadConnected(index, pad);
- else
- GamepadService::GetInstance()->OnGamepadDisconnected(index, pad);
-}
-
-GamepadHardwareBuffer* GamepadProvider::SharedMemoryAsHardwareBuffer() {
- void* mem = gamepad_shared_memory_.memory();
- CHECK(mem);
- return static_cast<GamepadHardwareBuffer*>(mem);
-}
-
-void GamepadProvider::CheckForUserGesture() {
- base::AutoLock lock(user_gesture_lock_);
- if (user_gesture_observers_.empty() && ever_had_user_gesture_)
- return;
-
- bool had_gesture_before = ever_had_user_gesture_;
- const WebGamepads& pads = SharedMemoryAsHardwareBuffer()->buffer;
- if (GamepadsHaveUserGesture(pads)) {
- ever_had_user_gesture_ = true;
- for (size_t i = 0; i < user_gesture_observers_.size(); i++) {
- user_gesture_observers_[i].task_runner->PostTask(
- FROM_HERE, user_gesture_observers_[i].closure);
- }
- user_gesture_observers_.clear();
- }
- if (!had_gesture_before && ever_had_user_gesture_) {
- // Initialize pad_states_ for the first time.
- for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
- pad_states_.get()[i].SetPad(pads.items[i]);
- }
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_provider.h b/chromium/content/browser/gamepad/gamepad_provider.h
deleted file mode 100644
index 916138986aa..00000000000
--- a/chromium/content/browser/gamepad/gamepad_provider.h
+++ /dev/null
@@ -1,168 +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_GAMEPAD_GAMEPAD_PROVIDER_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory.h"
-#include "base/memory/weak_ptr.h"
-#include "base/synchronization/lock.h"
-#include "base/system_monitor/system_monitor.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-class Thread;
-}
-
-namespace content {
-
-class GamepadDataFetcher;
-struct GamepadHardwareBuffer;
-
-class CONTENT_EXPORT GamepadProvider :
- public base::SystemMonitor::DevicesChangedObserver {
- public:
- GamepadProvider();
-
- // Manually specifies the data fetcher. Used for testing.
- explicit GamepadProvider(std::unique_ptr<GamepadDataFetcher> fetcher);
-
- ~GamepadProvider() override;
-
- // Returns the shared memory handle of the gamepad data duplicated into the
- // given process.
- base::SharedMemoryHandle GetSharedMemoryHandleForProcess(
- base::ProcessHandle renderer_process);
-
- void GetCurrentGamepadData(blink::WebGamepads* data);
-
- // Pause and resume the background polling thread. Can be called from any
- // thread.
- void Pause();
- void Resume();
-
- // Registers the given closure for calling when the user has interacted with
- // the device. This callback will only be issued once.
- void RegisterForUserGesture(const base::Closure& closure);
-
- // base::SystemMonitor::DevicesChangedObserver implementation.
- void OnDevicesChanged(base::SystemMonitor::DeviceType type) override;
-
- private:
- void Initialize(std::unique_ptr<GamepadDataFetcher> fetcher);
-
- // Method for setting up the platform-specific data fetcher. Takes ownership
- // of |fetcher|.
- void DoInitializePollingThread(std::unique_ptr<GamepadDataFetcher> fetcher);
-
- // Method for sending pause hints to the low-level data fetcher. Runs on
- // polling_thread_.
- void SendPauseHint(bool paused);
-
- // Method for polling a GamepadDataFetcher. Runs on the polling_thread_.
- void DoPoll();
- void ScheduleDoPoll();
-
- void OnGamepadConnectionChange(bool connected,
- int index,
- const blink::WebGamepad& pad);
- void DispatchGamepadConnectionChange(bool connected,
- int index,
- const blink::WebGamepad& pad);
-
- GamepadHardwareBuffer* SharedMemoryAsHardwareBuffer();
-
- // Checks the gamepad state to see if the user has interacted with it.
- void CheckForUserGesture();
-
- enum { kDesiredSamplingIntervalMs = 16 };
-
- // Keeps track of when the background thread is paused. Access to is_paused_
- // must be guarded by is_paused_lock_.
- base::Lock is_paused_lock_;
- bool is_paused_;
-
- // Keep track of when a polling task is schedlued, so as to prevent us from
- // accidentally scheduling more than one at any time, when rapidly toggling
- // |is_paused_|.
- bool have_scheduled_do_poll_;
-
- // Lists all observers registered for user gestures, and the thread which
- // to issue the callbacks on. Since we always issue the callback on the
- // thread which the registration happened, and this class lives on the I/O
- // thread, the message loop proxies will normally just be the I/O thread.
- // However, this will be the main thread for unit testing.
- base::Lock user_gesture_lock_;
- struct ClosureAndThread {
- ClosureAndThread(const base::Closure& c,
- const scoped_refptr<base::SingleThreadTaskRunner>& m);
- ClosureAndThread(const ClosureAndThread& other);
- ~ClosureAndThread();
-
- base::Closure closure;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner;
- };
- typedef std::vector<ClosureAndThread> UserGestureObserverVector;
- UserGestureObserverVector user_gesture_observers_;
-
- // Updated based on notification from SystemMonitor when the system devices
- // have been updated, and this notification is passed on to the data fetcher
- // to enable it to avoid redundant (and possibly expensive) is-connected
- // tests. Access to devices_changed_ must be guarded by
- // devices_changed_lock_.
- base::Lock devices_changed_lock_;
- bool devices_changed_;
-
- bool ever_had_user_gesture_;
-
- class PadState {
- public:
- PadState() {
- SetDisconnected();
- }
-
- bool Match(const blink::WebGamepad& pad) const;
- void SetPad(const blink::WebGamepad& pad);
- void SetDisconnected();
- void AsWebGamepad(blink::WebGamepad* pad);
-
- bool connected() const { return connected_; }
-
- private:
- bool connected_;
- unsigned axes_length_;
- unsigned buttons_length_;
- blink::WebUChar id_[blink::WebGamepad::idLengthCap];
- blink::WebUChar mapping_[blink::WebGamepad::mappingLengthCap];
- };
-
- // Used to detect connections and disconnections.
- std::unique_ptr<PadState[]> pad_states_;
-
- // Only used on the polling thread.
- std::unique_ptr<GamepadDataFetcher> data_fetcher_;
-
- base::Lock shared_memory_lock_;
- base::SharedMemory gamepad_shared_memory_;
-
- // Polling is done on this background thread.
- std::unique_ptr<base::Thread> polling_thread_;
-
- static GamepadProvider* instance_;
-
- DISALLOW_COPY_AND_ASSIGN(GamepadProvider);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_PROVIDER_H_
diff --git a/chromium/content/browser/gamepad/gamepad_provider_unittest.cc b/chromium/content/browser/gamepad/gamepad_provider_unittest.cc
deleted file mode 100644
index e9675d6d9f7..00000000000
--- a/chromium/content/browser/gamepad/gamepad_provider_unittest.cc
+++ /dev/null
@@ -1,162 +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/gamepad/gamepad_provider.h"
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-#include "content/browser/gamepad/gamepad_test_helpers.h"
-#include "content/common/gamepad_hardware_buffer.h"
-#include "content/common/gamepad_messages.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-using blink::WebGamepads;
-
-// Helper class to generate and record user gesture callbacks.
-class UserGestureListener {
- public:
- UserGestureListener()
- : has_user_gesture_(false),
- weak_factory_(this) {
- }
-
- base::Closure GetClosure() {
- return base::Bind(&UserGestureListener::GotUserGesture,
- weak_factory_.GetWeakPtr());
- }
-
- bool has_user_gesture() const { return has_user_gesture_; }
-
- private:
- void GotUserGesture() {
- has_user_gesture_ = true;
- }
-
- bool has_user_gesture_;
- base::WeakPtrFactory<UserGestureListener> weak_factory_;
-};
-
-// Main test fixture
-class GamepadProviderTest : public testing::Test, public GamepadTestHelper {
- public:
- GamepadProvider* CreateProvider(const WebGamepads& test_data) {
- mock_data_fetcher_ = new MockGamepadDataFetcher(test_data);
- provider_.reset(new GamepadProvider(
- std::unique_ptr<GamepadDataFetcher>(mock_data_fetcher_)));
- return provider_.get();
- }
-
- protected:
- GamepadProviderTest() {
- }
-
- std::unique_ptr<GamepadProvider> provider_;
-
- // Pointer owned by the provider.
- MockGamepadDataFetcher* mock_data_fetcher_;
-
- DISALLOW_COPY_AND_ASSIGN(GamepadProviderTest);
-};
-
-// Crashes. http://crbug.com/106163
-// crbug.com/147549
-#if defined(OS_ANDROID)
-#define MAYBE_PollingAccess DISABLED_PollingAccess
-#else
-#define MAYBE_PollingAccess PollingAccess
-#endif
-TEST_F(GamepadProviderTest, MAYBE_PollingAccess) {
- WebGamepads test_data;
- test_data.length = 1;
- test_data.items[0].connected = true;
- test_data.items[0].timestamp = 0;
- test_data.items[0].buttonsLength = 1;
- test_data.items[0].axesLength = 2;
- test_data.items[0].buttons[0].value = 1.f;
- test_data.items[0].buttons[0].pressed = true;
- test_data.items[0].axes[0] = -1.f;
- test_data.items[0].axes[1] = .5f;
-
- GamepadProvider* provider = CreateProvider(test_data);
- provider->Resume();
-
- message_loop().RunUntilIdle();
-
- mock_data_fetcher_->WaitForDataRead();
-
- // Renderer-side, pull data out of poll buffer.
- base::SharedMemoryHandle handle = provider->GetSharedMemoryHandleForProcess(
- base::GetCurrentProcessHandle());
- std::unique_ptr<base::SharedMemory> shared_memory(
- new base::SharedMemory(handle, true));
- EXPECT_TRUE(shared_memory->Map(sizeof(GamepadHardwareBuffer)));
- void* mem = shared_memory->memory();
-
- GamepadHardwareBuffer* hwbuf = static_cast<GamepadHardwareBuffer*>(mem);
- // See gamepad_hardware_buffer.h for details on the read discipline.
- WebGamepads output;
-
- base::subtle::Atomic32 version;
- do {
- version = hwbuf->sequence.ReadBegin();
- memcpy(&output, &hwbuf->buffer, sizeof(output));
- } while (hwbuf->sequence.ReadRetry(version));
-
- EXPECT_EQ(1u, output.length);
- EXPECT_EQ(1u, output.items[0].buttonsLength);
- EXPECT_EQ(1.f, output.items[0].buttons[0].value);
- EXPECT_EQ(true, output.items[0].buttons[0].pressed);
- EXPECT_EQ(2u, output.items[0].axesLength);
- EXPECT_EQ(-1.f, output.items[0].axes[0]);
- EXPECT_EQ(0.5f, output.items[0].axes[1]);
-}
-
-// Tests that waiting for a user gesture works properly.
-TEST_F(GamepadProviderTest, UserGesture) {
- WebGamepads no_button_data;
- no_button_data.length = 1;
- no_button_data.items[0].connected = true;
- no_button_data.items[0].timestamp = 0;
- no_button_data.items[0].buttonsLength = 1;
- no_button_data.items[0].axesLength = 2;
- no_button_data.items[0].buttons[0].value = 0.f;
- no_button_data.items[0].buttons[0].pressed = false;
- no_button_data.items[0].axes[0] = 0.f;
- no_button_data.items[0].axes[1] = .4f;
-
- WebGamepads button_down_data = no_button_data;
- button_down_data.items[0].buttons[0].value = 1.f;
- button_down_data.items[0].buttons[0].pressed = true;
-
- UserGestureListener listener;
- GamepadProvider* provider = CreateProvider(no_button_data);
- provider->Resume();
-
- provider->RegisterForUserGesture(listener.GetClosure());
- mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
-
- // It should not have issued our callback.
- message_loop().RunUntilIdle();
- EXPECT_FALSE(listener.has_user_gesture());
-
- // Set a button down and wait for it to be read twice.
- mock_data_fetcher_->SetTestData(button_down_data);
- mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
-
- // It should have issued our callback.
- message_loop().RunUntilIdle();
- EXPECT_TRUE(listener.has_user_gesture());
-}
-
-} // namespace
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_service.cc b/chromium/content/browser/gamepad/gamepad_service.cc
index ef56d3176bf..8611278332a 100644
--- a/chromium/content/browser/gamepad/gamepad_service.cc
+++ b/chromium/content/browser/gamepad/gamepad_service.cc
@@ -8,12 +8,14 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
-#include "content/browser/gamepad/gamepad_consumer.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-#include "content/browser/gamepad/gamepad_provider.h"
+#include "content/browser/gamepad/gamepad_shared_buffer_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
+#include "device/gamepad/gamepad_consumer.h"
+#include "device/gamepad/gamepad_data_fetcher.h"
+#include "device/gamepad/gamepad_provider.h"
namespace content {
@@ -27,8 +29,10 @@ GamepadService::GamepadService()
SetInstance(this);
}
-GamepadService::GamepadService(std::unique_ptr<GamepadDataFetcher> fetcher)
- : provider_(new GamepadProvider(std::move(fetcher))),
+GamepadService::GamepadService(
+ std::unique_ptr<device::GamepadDataFetcher> fetcher)
+ : provider_(new device::GamepadProvider(
+ base::MakeUnique<GamepadSharedBufferImpl>(), this, std::move(fetcher))),
num_active_consumers_(0),
gesture_callback_pending_(false) {
SetInstance(this);
@@ -53,11 +57,12 @@ GamepadService* GamepadService::GetInstance() {
return g_gamepad_service;
}
-void GamepadService::ConsumerBecameActive(GamepadConsumer* consumer) {
+void GamepadService::ConsumerBecameActive(device::GamepadConsumer* consumer) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!provider_)
- provider_.reset(new GamepadProvider);
+ provider_.reset(new device::GamepadProvider(
+ base::MakeUnique<GamepadSharedBufferImpl>(), this));
std::pair<ConsumerSet::iterator, bool> insert_result =
consumers_.insert(consumer);
@@ -74,7 +79,7 @@ void GamepadService::ConsumerBecameActive(GamepadConsumer* consumer) {
provider_->Resume();
}
-void GamepadService::ConsumerBecameInactive(GamepadConsumer* consumer) {
+void GamepadService::ConsumerBecameInactive(device::GamepadConsumer* consumer) {
DCHECK(provider_);
DCHECK(num_active_consumers_ > 0);
DCHECK(consumers_.count(consumer) > 0);
@@ -85,7 +90,7 @@ void GamepadService::ConsumerBecameInactive(GamepadConsumer* consumer) {
provider_->Pause();
}
-void GamepadService::RemoveConsumer(GamepadConsumer* consumer) {
+void GamepadService::RemoveConsumer(device::GamepadConsumer* consumer) {
DCHECK(thread_checker_.CalledOnValidThread());
ConsumerSet::iterator it = consumers_.find(consumer);
@@ -104,6 +109,20 @@ void GamepadService::Terminate() {
provider_.reset();
}
+void GamepadService::OnGamepadConnectionChange(bool connected,
+ int index,
+ const blink::WebGamepad& pad) {
+ if (connected) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&GamepadService::OnGamepadConnected,
+ base::Unretained(this), index, pad));
+ } else {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&GamepadService::OnGamepadDisconnected,
+ base::Unretained(this), index, pad));
+ }
+}
+
void GamepadService::OnGamepadConnected(
int index,
const blink::WebGamepad& pad) {
diff --git a/chromium/content/browser/gamepad/gamepad_service.h b/chromium/content/browser/gamepad/gamepad_service.h
index d4536393630..b5c419b44d6 100644
--- a/chromium/content/browser/gamepad/gamepad_service.h
+++ b/chromium/content/browser/gamepad/gamepad_service.h
@@ -14,23 +14,28 @@
#include "base/memory/singleton.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
+#include "device/gamepad/gamepad_provider.h"
namespace blink {
class WebGamepad;
}
-namespace content {
-
+namespace device {
class GamepadConsumer;
class GamepadDataFetcher;
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
// when not in use).
-class CONTENT_EXPORT GamepadService {
+class CONTENT_EXPORT GamepadService
+ : public device::GamepadConnectionChangeClient {
public:
// Returns the GamepadService singleton.
static GamepadService* GetInstance();
@@ -44,21 +49,21 @@ class CONTENT_EXPORT GamepadService {
// gamepads.
//
// Must be called on the I/O thread.
- void ConsumerBecameActive(GamepadConsumer* consumer);
+ void ConsumerBecameActive(device::GamepadConsumer* consumer);
// Decrements the number of users of the provider. consumer will not be
// informed about connections until it's added back via ConsumerBecameActive.
// Must be matched with a ConsumerBecameActive call.
//
// Must be called on the I/O thread.
- void ConsumerBecameInactive(GamepadConsumer* consumer);
+ void ConsumerBecameInactive(device::GamepadConsumer* consumer);
// Decrements the number of users of the provider and removes consumer from
// the set of consumers. Should be matched with a a ConsumerBecameActive
// call.
//
// Must be called on the I/O thread.
- void RemoveConsumer(GamepadConsumer* consumer);
+ void RemoveConsumer(device::GamepadConsumer* consumer);
// Registers the given closure for calling when the user has interacted with
// the device. This callback will only be issued once. Should only be called
@@ -88,7 +93,8 @@ class CONTENT_EXPORT GamepadService {
// Constructor for testing. This specifies the data fetcher to use for a
// provider, bypassing the default platform one.
- GamepadService(std::unique_ptr<GamepadDataFetcher> fetcher);
+ GamepadService(
+ std::unique_ptr<device::GamepadDataFetcher> fetcher);
virtual ~GamepadService();
@@ -96,22 +102,24 @@ class CONTENT_EXPORT GamepadService {
void OnUserGesture();
+ void OnGamepadConnectionChange(bool connected,
+ int index,
+ const blink::WebGamepad& pad) override;
+
struct ConsumerInfo {
- ConsumerInfo(GamepadConsumer* consumer)
- : consumer(consumer),
- did_observe_user_gesture(false) {
- }
+ ConsumerInfo(device::GamepadConsumer* consumer)
+ : consumer(consumer), did_observe_user_gesture(false) {}
bool operator<(const ConsumerInfo& other) const {
return consumer < other.consumer;
}
- GamepadConsumer* consumer;
+ device::GamepadConsumer* consumer;
mutable bool is_active;
mutable bool did_observe_user_gesture;
};
- std::unique_ptr<GamepadProvider> provider_;
+ std::unique_ptr<device::GamepadProvider> provider_;
base::ThreadChecker thread_checker_;
diff --git a/chromium/content/browser/gamepad/gamepad_service_test_helpers.cc b/chromium/content/browser/gamepad/gamepad_service_test_helpers.cc
new file mode 100644
index 00000000000..195dd8f9d23
--- /dev/null
+++ b/chromium/content/browser/gamepad/gamepad_service_test_helpers.cc
@@ -0,0 +1,22 @@
+// 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/gamepad/gamepad_service_test_helpers.h"
+
+#include "content/browser/gamepad/gamepad_service.h"
+
+namespace content {
+
+GamepadServiceTestConstructor::GamepadServiceTestConstructor(
+ const blink::WebGamepads& test_data) {
+ data_fetcher_ = new device::MockGamepadDataFetcher(test_data);
+ gamepad_service_ = new GamepadService(
+ std::unique_ptr<device::GamepadDataFetcher>(data_fetcher_));
+}
+
+GamepadServiceTestConstructor::~GamepadServiceTestConstructor() {
+ delete gamepad_service_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_service_test_helpers.h b/chromium/content/browser/gamepad/gamepad_service_test_helpers.h
new file mode 100644
index 00000000000..273a42d3214
--- /dev/null
+++ b/chromium/content/browser/gamepad/gamepad_service_test_helpers.h
@@ -0,0 +1,38 @@
+// 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_GAMEPAD_GAMEPAD_SERVICE_TEST_HELPERS_H_
+#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_SERVICE_TEST_HELPERS_H_
+
+#include "base/macros.h"
+#include "device/gamepad/gamepad_test_helpers.h"
+#include "third_party/WebKit/public/platform/WebGamepads.h"
+
+namespace content {
+
+class GamepadService;
+
+// Constructs a GamepadService with a mock data source. This bypasses the
+// global singleton for the gamepad service.
+class GamepadServiceTestConstructor : public device::GamepadTestHelper {
+ public:
+ explicit GamepadServiceTestConstructor(const blink::WebGamepads& test_data);
+ ~GamepadServiceTestConstructor() override;
+
+ GamepadService* gamepad_service() { return gamepad_service_; }
+ device::MockGamepadDataFetcher* data_fetcher() { return data_fetcher_; }
+
+ private:
+ // Owning pointer (can't be a scoped_ptr due to private destructor).
+ GamepadService* gamepad_service_;
+
+ // Pointer owned by the provider (which is owned by the gamepad service).
+ device::MockGamepadDataFetcher* data_fetcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(GamepadServiceTestConstructor);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_SERVICE_TEST_HELPERS_H_
diff --git a/chromium/content/browser/gamepad/gamepad_service_unittest.cc b/chromium/content/browser/gamepad/gamepad_service_unittest.cc
index db16d6b5d59..70943459a23 100644
--- a/chromium/content/browser/gamepad/gamepad_service_unittest.cc
+++ b/chromium/content/browser/gamepad/gamepad_service_unittest.cc
@@ -10,9 +10,9 @@
#include "base/macros.h"
#include "base/run_loop.h"
-#include "content/browser/gamepad/gamepad_consumer.h"
-#include "content/browser/gamepad/gamepad_test_helpers.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "device/gamepad/gamepad_consumer.h"
+#include "device/gamepad/gamepad_test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -23,7 +23,7 @@ static const int kNumberOfGamepads = blink::WebGamepads::itemsLengthCap;
using blink::WebGamepads;
-class ConnectionListener : public GamepadConsumer {
+class ConnectionListener : public device::GamepadConsumer {
public:
ConnectionListener() {
ClearCounters();
@@ -69,7 +69,7 @@ class GamepadServiceTest : public testing::Test {
void SetUp() override;
private:
- MockGamepadDataFetcher* fetcher_;
+ device::MockGamepadDataFetcher* fetcher_;
GamepadService* service_;
std::unique_ptr<ConnectionListener> connection_listener_;
TestBrowserThreadBundle browser_thread_;
@@ -93,8 +93,9 @@ GamepadServiceTest::~GamepadServiceTest() {
}
void GamepadServiceTest::SetUp() {
- fetcher_ = new MockGamepadDataFetcher(test_data_);
- service_ = new GamepadService(std::unique_ptr<GamepadDataFetcher>(fetcher_));
+ fetcher_ = new device::MockGamepadDataFetcher(test_data_);
+ service_ = new GamepadService(
+ std::unique_ptr<device::GamepadDataFetcher>(fetcher_));
connection_listener_.reset((new ConnectionListener));
service_->ConsumerBecameActive(connection_listener_.get());
}
diff --git a/chromium/content/browser/gamepad/gamepad_shared_buffer_impl.cc b/chromium/content/browser/gamepad/gamepad_shared_buffer_impl.cc
new file mode 100644
index 00000000000..03911cb06a1
--- /dev/null
+++ b/chromium/content/browser/gamepad/gamepad_shared_buffer_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/gamepad/gamepad_shared_buffer_impl.h"
+
+#include "content/common/gamepad_hardware_buffer.h"
+
+namespace content {
+
+GamepadSharedBufferImpl::GamepadSharedBufferImpl() {
+ size_t data_size = sizeof(GamepadHardwareBuffer);
+ bool res = shared_memory_.CreateAndMapAnonymous(data_size);
+ CHECK(res);
+
+ void* mem = shared_memory_.memory();
+ DCHECK(mem);
+ new (mem) GamepadHardwareBuffer();
+}
+
+GamepadSharedBufferImpl::~GamepadSharedBufferImpl() {
+}
+
+base::SharedMemory* GamepadSharedBufferImpl::shared_memory() {
+ return &shared_memory_;
+}
+
+blink::WebGamepads* GamepadSharedBufferImpl::buffer() {
+ return &(hardware_buffer()->buffer);
+}
+
+GamepadHardwareBuffer* GamepadSharedBufferImpl::hardware_buffer() {
+ void* mem = shared_memory_.memory();
+ DCHECK(mem);
+ return static_cast<GamepadHardwareBuffer*>(mem);
+}
+
+void GamepadSharedBufferImpl::WriteBegin() {
+ hardware_buffer()->sequence.WriteBegin();
+}
+
+void GamepadSharedBufferImpl::WriteEnd() {
+ hardware_buffer()->sequence.WriteEnd();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_shared_buffer_impl.h b/chromium/content/browser/gamepad/gamepad_shared_buffer_impl.h
new file mode 100644
index 00000000000..fd2fa42eb95
--- /dev/null
+++ b/chromium/content/browser/gamepad/gamepad_shared_buffer_impl.h
@@ -0,0 +1,35 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_SHARED_BUFFER_IMPL_H_
+#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_SHARED_BUFFER_IMPL_H_
+
+#include "device/gamepad/gamepad_shared_buffer.h"
+#include "third_party/WebKit/public/platform/WebGamepads.h"
+
+namespace content {
+
+struct GamepadHardwareBuffer;
+
+class GamepadSharedBufferImpl : public device::GamepadSharedBuffer {
+ public:
+ GamepadSharedBufferImpl();
+ ~GamepadSharedBufferImpl() override;
+
+ base::SharedMemory* shared_memory() override;
+ blink::WebGamepads* buffer() override;
+ GamepadHardwareBuffer* hardware_buffer();
+
+ void WriteBegin() override;
+ void WriteEnd() override;
+
+ private:
+ base::SharedMemory shared_memory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GamepadSharedBufferImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_SHARED_BUFFER_IMPL_H_
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings.cc b/chromium/content/browser/gamepad/gamepad_standard_mappings.cc
deleted file mode 100644
index 687d4ce154d..00000000000
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings.cc
+++ /dev/null
@@ -1,64 +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/gamepad/gamepad_standard_mappings.h"
-
-namespace content {
-
-blink::WebGamepadButton AxisToButton(float input) {
- float value = (input + 1.f) / 2.f;
- return blink::WebGamepadButton(
- value > kDefaultButtonPressedThreshold, value);
-}
-
-blink::WebGamepadButton AxisNegativeAsButton(float input) {
- float value = (input < -0.5f) ? 1.f : 0.f;
- return blink::WebGamepadButton(
- value > kDefaultButtonPressedThreshold, value);
-}
-
-blink::WebGamepadButton AxisPositiveAsButton(float input) {
- float value = (input > 0.5f) ? 1.f : 0.f;
- return blink::WebGamepadButton(
- value > kDefaultButtonPressedThreshold, value);
-}
-
-blink::WebGamepadButton ButtonFromButtonAndAxis(
- blink::WebGamepadButton button, float axis) {
- float value = (axis + 1.f) / 2.f;
- return blink::WebGamepadButton(button.pressed, value);
-}
-
-blink::WebGamepadButton NullButton() {
- return blink::WebGamepadButton(false, 0.0);
-}
-
-void DpadFromAxis(blink::WebGamepad* mapped, float dir) {
- bool up = false;
- bool right = false;
- bool down = false;
- bool left = false;
-
- // Dpad is mapped as a direction on one axis, where -1 is up and it
- // increases clockwise to 1, which is up + left. It's set to a large (> 1.f)
- // number when nothing is depressed, except on start up, sometimes it's 0.0
- // for no data, rather than the large number.
- if (dir != 0.0f) {
- up = (dir >= -1.f && dir < -0.7f) || (dir >= .95f && dir <= 1.f);
- right = dir >= -.75f && dir < -.1f;
- down = dir >= -.2f && dir < .45f;
- left = dir >= .4f && dir <= 1.f;
- }
-
- mapped->buttons[BUTTON_INDEX_DPAD_UP].pressed = up;
- mapped->buttons[BUTTON_INDEX_DPAD_UP].value = up ? 1.f : 0.f;
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT].pressed = right;
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT].value = right ? 1.f : 0.f;
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN].pressed = down;
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN].value = down ? 1.f : 0.f;
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT].pressed = left;
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT].value = left ? 1.f : 0.f;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings.h b/chromium/content/browser/gamepad/gamepad_standard_mappings.h
deleted file mode 100644
index d4908eff442..00000000000
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings.h
+++ /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.
-
-#ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_STANDARD_MAPPINGS_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_STANDARD_MAPPINGS_H_
-
-#include "base/strings/string_piece.h"
-#include "content/common/gamepad_hardware_buffer.h"
-
-namespace content {
-
-typedef void (*GamepadStandardMappingFunction)(
- const blink::WebGamepad& original,
- blink::WebGamepad* mapped);
-
-GamepadStandardMappingFunction GetGamepadStandardMappingFunction(
- const base::StringPiece& vendor_id,
- const base::StringPiece& product_id);
-
-// This defines our canonical mapping order for gamepad-like devices. If these
-// items cannot all be satisfied, it is a case-by-case judgement as to whether
-// it is better to leave the device unmapped, or to partially map it. In
-// general, err towards leaving it *unmapped* so that content can handle
-// appropriately.
-
-// A Java counterpart will be generated for this enum.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.input
-// GENERATED_JAVA_PREFIX_TO_STRIP: BUTTON_INDEX_
-enum CanonicalButtonIndex {
- BUTTON_INDEX_PRIMARY,
- BUTTON_INDEX_SECONDARY,
- BUTTON_INDEX_TERTIARY,
- BUTTON_INDEX_QUATERNARY,
- BUTTON_INDEX_LEFT_SHOULDER,
- BUTTON_INDEX_RIGHT_SHOULDER,
- BUTTON_INDEX_LEFT_TRIGGER,
- BUTTON_INDEX_RIGHT_TRIGGER,
- BUTTON_INDEX_BACK_SELECT,
- BUTTON_INDEX_START,
- BUTTON_INDEX_LEFT_THUMBSTICK,
- BUTTON_INDEX_RIGHT_THUMBSTICK,
- BUTTON_INDEX_DPAD_UP,
- BUTTON_INDEX_DPAD_DOWN,
- BUTTON_INDEX_DPAD_LEFT,
- BUTTON_INDEX_DPAD_RIGHT,
- BUTTON_INDEX_META,
- BUTTON_INDEX_COUNT
-};
-
-// A Java counterpart will be generated for this enum.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.input
-// GENERATED_JAVA_PREFIX_TO_STRIP: AXIS_INDEX_
-enum CanonicalAxisIndex {
- AXIS_INDEX_LEFT_STICK_X,
- AXIS_INDEX_LEFT_STICK_Y,
- AXIS_INDEX_RIGHT_STICK_X,
- AXIS_INDEX_RIGHT_STICK_Y,
- AXIS_INDEX_COUNT
-};
-
-// Matches XInput's trigger deadzone
-const float kDefaultButtonPressedThreshold = 30.f/255.f;
-
-// Common mapping functions
-blink::WebGamepadButton AxisToButton(float input);
-blink::WebGamepadButton AxisNegativeAsButton(float input);
-blink::WebGamepadButton AxisPositiveAsButton(float input);
-blink::WebGamepadButton ButtonFromButtonAndAxis(
- blink::WebGamepadButton button, float axis);
-blink::WebGamepadButton NullButton();
-void DpadFromAxis(blink::WebGamepad* mapped, float dir);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_STANDARD_MAPPINGS_H_
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc b/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc
deleted file mode 100644
index ecff74b3723..00000000000
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc
+++ /dev/null
@@ -1,336 +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 <stddef.h>
-
-#include "base/macros.h"
-#include "content/browser/gamepad/gamepad_standard_mappings.h"
-
-namespace content {
-
-namespace {
-
-void MapperXInputStyleGamepad(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[8];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperLakeviewResearch(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[4]);
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; // no Meta on this device
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperPlaystationSixAxis(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[15];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[12];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[12]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[13]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisToButton(input.axes[8]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisToButton(input.axes[10]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = AxisToButton(input.axes[9]);
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[16];
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperDualshock4(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- enum Dualshock4Buttons {
- DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT,
- DUALSHOCK_BUTTON_COUNT
- };
-
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
- mapped->buttons[DUALSHOCK_BUTTON_TOUCHPAD] = input.buttons[13];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
-
- mapped->buttonsLength = DUALSHOCK_BUTTON_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperIBuffalo(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[1]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[1]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[0]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[0]);
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = 2;
-}
-
-
-void MapperXGEAR(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[4]);
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[2];
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; // no Meta on this device
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperDragonRiseGeneric(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[5]);
- mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0];
- mapped->axes[AXIS_INDEX_LEFT_STICK_Y] = input.axes[1];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; // no Meta on this device
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperOnLiveWireless(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[8];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = NullButton();
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[6];
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperNvShield(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[6];
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperOUYA(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = NullButton();
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[15];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperRazerServal(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[6]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperMogaPro(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[6]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-struct MappingData {
- const char* const vendor_id;
- const char* const product_id;
- GamepadStandardMappingFunction function;
-} AvailableMappings[] = {
- // http://www.linux-usb.org/usb.ids
- {"0079", "0006", MapperDragonRiseGeneric}, // DragonRise Generic USB
- {"045e", "028e", MapperXInputStyleGamepad}, // Xbox 360 Wired
- {"045e", "028f", MapperXInputStyleGamepad}, // Xbox 360 Wireless
- {"045e", "0719", MapperXInputStyleGamepad}, // Xbox 360 Wireless
- {"046d", "c21d", MapperXInputStyleGamepad}, // Logitech F310
- {"046d", "c21e", MapperXInputStyleGamepad}, // Logitech F510
- {"046d", "c21f", MapperXInputStyleGamepad}, // Logitech F710
- {"054c", "0268", MapperPlaystationSixAxis}, // Playstation SIXAXIS
- {"054c", "05c4", MapperDualshock4}, // Playstation Dualshock 4
- {"0583", "2060", MapperIBuffalo}, // iBuffalo Classic
- {"0925", "0005", MapperLakeviewResearch}, // SmartJoy PLUS Adapter
- {"0925", "8866", MapperLakeviewResearch}, // WiseGroup MP-8866
- {"0955", "7210", MapperNvShield}, // Nvidia Shield gamepad
- {"0b05", "4500", MapperADT1}, // Nexus Player Controller
- {"0e8f", "0003", MapperXGEAR}, // XFXforce XGEAR PS2 Controller
- {"1532", "0900", MapperRazerServal}, // Razer Serval Controller
- {"18d1", "2c40", MapperADT1}, // ADT-1 Controller
- {"20d6", "6271", MapperMogaPro}, // Moga Pro Controller (HID mode)
- {"2378", "1008", MapperOnLiveWireless}, // OnLive Controller (Bluetooth)
- {"2378", "100a", MapperOnLiveWireless}, // OnLive Controller (Wired)
- {"2836", "0001", MapperOUYA}, // OUYA Controller
-};
-
-} // namespace
-
-GamepadStandardMappingFunction GetGamepadStandardMappingFunction(
- const base::StringPiece& vendor_id,
- const base::StringPiece& product_id) {
- for (size_t i = 0; i < arraysize(AvailableMappings); ++i) {
- MappingData& item = AvailableMappings[i];
- if (vendor_id == item.vendor_id && product_id == item.product_id)
- return item.function;
- }
- return NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm b/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm
deleted file mode 100644
index f10e319102a..00000000000
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm
+++ /dev/null
@@ -1,396 +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 <stddef.h>
-
-#include "base/macros.h"
-#include "content/browser/gamepad/gamepad_standard_mappings.h"
-
-namespace content {
-
-namespace {
-
-void MapperXbox360Gamepad(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = input.buttons[12];
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[10];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperPlaystationSixAxis(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[15];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[12];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[11];
-
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] =
- ButtonFromButtonAndAxis(input.buttons[8], input.axes[14]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] =
- ButtonFromButtonAndAxis(input.buttons[9], input.axes[15]);
-
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[2];
-
- // The SixAxis Dpad is pressure sensitive.
- mapped->buttons[BUTTON_INDEX_DPAD_UP] =
- ButtonFromButtonAndAxis(input.buttons[4], input.axes[10]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] =
- ButtonFromButtonAndAxis(input.buttons[6], input.axes[12]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] =
- ButtonFromButtonAndAxis(input.buttons[7], input.axes[13]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- ButtonFromButtonAndAxis(input.buttons[5], input.axes[11]);
-
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[16];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperDualshock4(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- enum Dualshock4Buttons {
- DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT,
- DUALSHOCK_BUTTON_COUNT
- };
-
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
- mapped->buttons[DUALSHOCK_BUTTON_TOUCHPAD] = input.buttons[13];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = DUALSHOCK_BUTTON_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperIBuffalo(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[1]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[1]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[0]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[0]);
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = 2;
-}
-
-void MapperDirectInputStyle(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperMacallyIShock(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- enum IShockButtons {
- ISHOCK_BUTTON_C = BUTTON_INDEX_COUNT,
- ISHOCK_BUTTON_D,
- ISHOCK_BUTTON_E,
- ISHOCK_BUTTON_COUNT,
- };
-
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[12];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[15];
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[16];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[17];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[11];
- mapped->buttons[ISHOCK_BUTTON_C] = input.buttons[8];
- mapped->buttons[ISHOCK_BUTTON_D] = input.buttons[18];
- mapped->buttons[ISHOCK_BUTTON_E] = input.buttons[19];
- mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0];
- mapped->axes[AXIS_INDEX_LEFT_STICK_Y] = input.axes[1];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = -input.axes[5];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[6];
-
- mapped->buttonsLength = ISHOCK_BUTTON_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperXGEAR(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
- DpadFromAxis(mapped, input.axes[9]);
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[5];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[2];
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperSmartJoyPLUS(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
- DpadFromAxis(mapped, input.axes[9]);
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperDragonRiseGeneric(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- DpadFromAxis(mapped, input.axes[9]);
- mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0];
- mapped->axes[AXIS_INDEX_LEFT_STICK_Y] = input.axes[1];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[2];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperOnLiveWireless(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = NullButton();
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperNvShield(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[8];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperOUYA(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = NullButton();
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[15];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperRazerServal(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperMogaPro(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-struct MappingData {
- const char* const vendor_id;
- const char* const product_id;
- GamepadStandardMappingFunction function;
-} AvailableMappings[] = {
- // http://www.linux-usb.org/usb.ids
- {"0079", "0006", MapperDragonRiseGeneric}, // DragonRise Generic USB
- {"045e", "028e", MapperXbox360Gamepad}, // Xbox 360 Wired
- {"045e", "028f", MapperXbox360Gamepad}, // Xbox 360 Wireless
- {"045e", "0719", MapperXbox360Gamepad}, // Xbox 360 Wireless
- {"046d", "c216", MapperDirectInputStyle}, // Logitech F310, D mode
- {"046d", "c218", MapperDirectInputStyle}, // Logitech F510, D mode
- {"046d", "c219", MapperDirectInputStyle}, // Logitech F710, D mode
- {"054c", "0268", MapperPlaystationSixAxis}, // Playstation SIXAXIS
- {"054c", "05c4", MapperDualshock4}, // Playstation Dualshock 4
- {"0583", "2060", MapperIBuffalo}, // iBuffalo Classic
- {"0925", "0005", MapperSmartJoyPLUS}, // SmartJoy PLUS Adapter
- {"0955", "7210", MapperNvShield}, // Nvidia Shield gamepad
- {"0b05", "4500", MapperADT1}, // Nexus Player Controller
- {"0e8f", "0003", MapperXGEAR}, // XFXforce XGEAR PS2 Controller
- {"1532", "0900", MapperRazerServal}, // Razer Serval Controller
- {"18d1", "2c40", MapperADT1}, // ADT-1 Controller
- {"20d6", "6271", MapperMogaPro}, // Moga Pro Controller (HID mode)
- {"2222", "0060", MapperDirectInputStyle}, // Macally iShockX, analog mode
- {"2222", "4010", MapperMacallyIShock}, // Macally iShock
- {"2378", "1008", MapperOnLiveWireless}, // OnLive Controller (Bluetooth)
- {"2378", "100a", MapperOnLiveWireless}, // OnLive Controller (Wired)
- {"2836", "0001", MapperOUYA}, // OUYA Controller
-};
-
-} // namespace
-
-GamepadStandardMappingFunction GetGamepadStandardMappingFunction(
- const base::StringPiece& vendor_id,
- const base::StringPiece& product_id) {
- for (size_t i = 0; i < arraysize(AvailableMappings); ++i) {
- MappingData& item = AvailableMappings[i];
- if (vendor_id == item.vendor_id && product_id == item.product_id)
- return item.function;
- }
- return NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc b/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc
deleted file mode 100644
index efdcc1333cb..00000000000
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "content/browser/gamepad/gamepad_standard_mappings.h"
-
-namespace content {
-
-namespace {
-
-void MapperLogitechDualAction(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void Mapper2Axes8Keys(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[1]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[1]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[0]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[0]);
-
- // Missing buttons
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = blink::WebGamepadButton();
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = blink::WebGamepadButton();
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = blink::WebGamepadButton();
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = blink::WebGamepadButton();
- mapped->buttons[BUTTON_INDEX_META] = blink::WebGamepadButton();
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1;
- mapped->axesLength = 0;
-}
-
-void MapperDualshock4(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- enum Dualshock4Buttons {
- DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT,
- DUALSHOCK_BUTTON_COUNT
- };
-
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
- mapped->buttons[DUALSHOCK_BUTTON_TOUCHPAD] = input.buttons[13];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = DUALSHOCK_BUTTON_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperIBuffalo(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[1]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[1]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[0]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[0]);
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = 2;
-}
-
-void MapperOnLiveWireless(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = NullButton();
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperNvShield(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[8];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperOUYA(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[2];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[5];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = NullButton();
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_META] = input.buttons[15];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT;
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperRazerServal(const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[10];
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-void MapperMogaPro(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
- *mapped = input;
- mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
- mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
- mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
- mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
- mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
- mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[3]);
- mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
- mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
- mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- DpadFromAxis(mapped, input.axes[9]);
-
- mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
- mapped->axesLength = AXIS_INDEX_COUNT;
-}
-
-struct MappingData {
- const char* const vendor_id;
- const char* const product_id;
- GamepadStandardMappingFunction function;
-} AvailableMappings[] = {
- // http://www.linux-usb.org/usb.ids
- {"0079", "0011", Mapper2Axes8Keys}, // 2Axes 8Keys Game Pad
- {"046d", "c216", MapperLogitechDualAction}, // Logitech DualAction
- {"054c", "05c4", MapperDualshock4}, // Playstation Dualshock 4
- {"0583", "2060", MapperIBuffalo}, // iBuffalo Classic
- {"0955", "7210", MapperNvShield}, // Nvidia Shield gamepad
- {"0b05", "4500", MapperADT1}, // Nexus Player Controller
- {"1532", "0900", MapperRazerServal}, // Razer Serval Controller
- {"18d1", "2c40", MapperADT1}, // ADT-1 Controller
- {"20d6", "6271", MapperMogaPro}, // Moga Pro Controller (HID mode)
- {"2378", "1008", MapperOnLiveWireless}, // OnLive Controller (Bluetooth)
- {"2378", "100a", MapperOnLiveWireless}, // OnLive Controller (Wired)
- {"2836", "0001", MapperOUYA}, // OUYA Controller
-};
-
-} // namespace
-
-GamepadStandardMappingFunction GetGamepadStandardMappingFunction(
- const base::StringPiece& vendor_id,
- const base::StringPiece& product_id) {
- for (size_t i = 0; i < arraysize(AvailableMappings); ++i) {
- MappingData& item = AvailableMappings[i];
- if (vendor_id == item.vendor_id && product_id == item.product_id)
- return item.function;
- }
- return NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_test_helpers.cc b/chromium/content/browser/gamepad/gamepad_test_helpers.cc
deleted file mode 100644
index ed78e2e5004..00000000000
--- a/chromium/content/browser/gamepad/gamepad_test_helpers.cc
+++ /dev/null
@@ -1,64 +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/gamepad/gamepad_test_helpers.h"
-
-#include "content/browser/gamepad/gamepad_service.h"
-
-namespace content {
-
-MockGamepadDataFetcher::MockGamepadDataFetcher(
- const blink::WebGamepads& test_data)
- : test_data_(test_data),
- read_data_(false, false) {
-}
-
-MockGamepadDataFetcher::~MockGamepadDataFetcher() {
-}
-
-void MockGamepadDataFetcher::GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) {
- {
- base::AutoLock lock(lock_);
- *pads = test_data_;
- }
- read_data_.Signal();
-}
-
-void MockGamepadDataFetcher::WaitForDataRead() {
- return read_data_.Wait();
-}
-
-void MockGamepadDataFetcher::WaitForDataReadAndCallbacksIssued() {
- // The provider will read the data on the background thread (setting the
- // event) and *then* will issue the callback on the client thread. Waiting for
- // it to read twice is a simple way to ensure that it was able to issue
- // callbacks for the first read (if it issued one).
- WaitForDataRead();
- WaitForDataRead();
-}
-
-void MockGamepadDataFetcher::SetTestData(const blink::WebGamepads& new_data) {
- base::AutoLock lock(lock_);
- test_data_ = new_data;
-}
-
-GamepadTestHelper::GamepadTestHelper() {
-}
-
-GamepadTestHelper::~GamepadTestHelper() {
-}
-
-GamepadServiceTestConstructor::GamepadServiceTestConstructor(
- const blink::WebGamepads& test_data) {
- data_fetcher_ = new MockGamepadDataFetcher(test_data);
- gamepad_service_ =
- new GamepadService(std::unique_ptr<GamepadDataFetcher>(data_fetcher_));
-}
-
-GamepadServiceTestConstructor::~GamepadServiceTestConstructor() {
- delete gamepad_service_;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_test_helpers.h b/chromium/content/browser/gamepad/gamepad_test_helpers.h
deleted file mode 100644
index 4b44f2b7fb8..00000000000
--- a/chromium/content/browser/gamepad/gamepad_test_helpers.h
+++ /dev/null
@@ -1,91 +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_GAMEPAD_GAMEPAD_TEST_HELPERS_H_
-#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_TEST_HELPERS_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-
-namespace content {
-
-class GamepadService;
-
-// Data fetcher that returns canned data for the gamepad provider.
-class MockGamepadDataFetcher : public GamepadDataFetcher {
- public:
- // Initializes the fetcher with the given gamepad data, which will be
- // returned when the provider queries us.
- explicit MockGamepadDataFetcher(const blink::WebGamepads& test_data);
-
- ~MockGamepadDataFetcher() override;
-
- // GamepadDataFetcher.
- void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) override;
-
- // Blocks the current thread until the GamepadProvider reads from this
- // fetcher on the background thread.
- void WaitForDataRead();
-
- // Blocks the current thread until the GamepadProvider reads from this
- // fetcher on the background thread and issued all callbacks related to the
- // read on the client's thread.
- void WaitForDataReadAndCallbacksIssued();
-
- // Updates the test data.
- void SetTestData(const blink::WebGamepads& new_data);
-
- private:
- base::Lock lock_;
- blink::WebGamepads test_data_;
- base::WaitableEvent read_data_;
-
- DISALLOW_COPY_AND_ASSIGN(MockGamepadDataFetcher);
-};
-
-// Base class for the other test helpers. This just sets up the system monitor.
-class GamepadTestHelper {
- public:
- GamepadTestHelper();
- virtual ~GamepadTestHelper();
-
- base::MessageLoop& message_loop() { return message_loop_; }
-
- private:
- // This must be constructed before the system monitor.
- base::MessageLoop message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(GamepadTestHelper);
-};
-
-// Constructs a GamepadService with a mock data source. This bypasses the
-// global singleton for the gamepad service.
-class GamepadServiceTestConstructor : public GamepadTestHelper {
- public:
- explicit GamepadServiceTestConstructor(const blink::WebGamepads& test_data);
- ~GamepadServiceTestConstructor() override;
-
- GamepadService* gamepad_service() { return gamepad_service_; }
- MockGamepadDataFetcher* data_fetcher() { return data_fetcher_; }
-
- private:
- // Owning pointer (can't be a scoped_ptr due to private destructor).
- GamepadService* gamepad_service_;
-
- // Pointer owned by the provider (which is owned by the gamepad service).
- MockGamepadDataFetcher* data_fetcher_;
-
- DISALLOW_COPY_AND_ASSIGN(GamepadServiceTestConstructor);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_GAMEPAD_TEST_HELPERS_H_
diff --git a/chromium/content/browser/gamepad/raw_input_data_fetcher_win.cc b/chromium/content/browser/gamepad/raw_input_data_fetcher_win.cc
deleted file mode 100644
index 765e0d7fa33..00000000000
--- a/chromium/content/browser/gamepad/raw_input_data_fetcher_win.cc
+++ /dev/null
@@ -1,532 +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/gamepad/raw_input_data_fetcher_win.h"
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/gamepad_hardware_buffer.h"
-#include "content/common/gamepad_messages.h"
-
-namespace content {
-
-using namespace blink;
-
-namespace {
-
-float NormalizeAxis(long value, long min, long max) {
- return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
-}
-
-unsigned long GetBitmask(unsigned short bits) {
- return (1 << bits) - 1;
-}
-
-// From the HID Usage Tables specification.
-USHORT DeviceUsages[] = {
- 0x04, // Joysticks
- 0x05, // Gamepads
- 0x08, // Multi Axis
-};
-
-const uint32_t kAxisMinimumUsageNumber = 0x30;
-const uint32_t kGameControlsUsagePage = 0x05;
-const uint32_t kButtonUsagePage = 0x09;
-
-} // namespace
-
-RawGamepadInfo::RawGamepadInfo() {
-}
-
-RawGamepadInfo::~RawGamepadInfo() {
-}
-
-RawInputDataFetcher::RawInputDataFetcher()
- : hid_dll_(base::FilePath(FILE_PATH_LITERAL("hid.dll"))),
- rawinput_available_(GetHidDllFunctions()),
- filter_xinput_(true),
- events_monitored_(false) {
-}
-
-RawInputDataFetcher::~RawInputDataFetcher() {
- ClearControllers();
- DCHECK(!window_);
- DCHECK(!events_monitored_);
-}
-
-void RawInputDataFetcher::WillDestroyCurrentMessageLoop() {
- StopMonitor();
-}
-
-RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) {
- size_t usage_count = arraysize(DeviceUsages);
- std::unique_ptr<RAWINPUTDEVICE[]> devices(new RAWINPUTDEVICE[usage_count]);
- for (size_t i = 0; i < usage_count; ++i) {
- devices[i].dwFlags = flags;
- devices[i].usUsagePage = 1;
- devices[i].usUsage = DeviceUsages[i];
- devices[i].hwndTarget = (flags & RIDEV_REMOVE) ? 0 : window_->hwnd();
- }
- return devices.release();
-}
-
-void RawInputDataFetcher::StartMonitor() {
- if (!rawinput_available_ || events_monitored_)
- return;
-
- if (!window_) {
- window_.reset(new base::win::MessageWindow());
- if (!window_->Create(base::Bind(&RawInputDataFetcher::HandleMessage,
- base::Unretained(this)))) {
- PLOG(ERROR) << "Failed to create the raw input window";
- window_.reset();
- return;
- }
- }
-
- // Register to receive raw HID input.
- std::unique_ptr<RAWINPUTDEVICE[]> devices(
- GetRawInputDevices(RIDEV_INPUTSINK));
- if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages),
- sizeof(RAWINPUTDEVICE))) {
- PLOG(ERROR) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK";
- window_.reset();
- return;
- }
-
- // Start observing message loop destruction if we start monitoring the first
- // event.
- if (!events_monitored_)
- base::MessageLoop::current()->AddDestructionObserver(this);
-
- events_monitored_ = true;
-}
-
-void RawInputDataFetcher::StopMonitor() {
- if (!rawinput_available_ || !events_monitored_)
- return;
-
- // Stop receiving raw input.
- DCHECK(window_);
- std::unique_ptr<RAWINPUTDEVICE[]> devices(GetRawInputDevices(RIDEV_REMOVE));
-
- if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages),
- sizeof(RAWINPUTDEVICE))) {
- PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE";
- }
-
- events_monitored_ = false;
- window_.reset();
-
- // Stop observing message loop destruction if no event is being monitored.
- base::MessageLoop::current()->RemoveDestructionObserver(this);
-}
-
-void RawInputDataFetcher::ClearControllers() {
- while (!controllers_.empty()) {
- RawGamepadInfo* gamepad_info = controllers_.begin()->second;
- controllers_.erase(gamepad_info->handle);
- delete gamepad_info;
- }
-}
-
-std::vector<RawGamepadInfo*> RawInputDataFetcher::EnumerateDevices() {
- std::vector<RawGamepadInfo*> valid_controllers;
-
- ClearControllers();
-
- UINT count = 0;
- UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST));
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputDeviceList() failed";
- return valid_controllers;
- }
- DCHECK_EQ(0u, result);
-
- std::unique_ptr<RAWINPUTDEVICELIST[]> device_list(
- new RAWINPUTDEVICELIST[count]);
- result = GetRawInputDeviceList(device_list.get(), &count,
- sizeof(RAWINPUTDEVICELIST));
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputDeviceList() failed";
- return valid_controllers;
- }
- DCHECK_EQ(count, result);
-
- for (UINT i = 0; i < count; ++i) {
- if (device_list[i].dwType == RIM_TYPEHID) {
- HANDLE device_handle = device_list[i].hDevice;
- RawGamepadInfo* gamepad_info = ParseGamepadInfo(device_handle);
- if (gamepad_info) {
- controllers_[device_handle] = gamepad_info;
- valid_controllers.push_back(gamepad_info);
- }
- }
- }
- return valid_controllers;
-}
-
-RawGamepadInfo* RawInputDataFetcher::GetGamepadInfo(HANDLE handle) {
- std::map<HANDLE, RawGamepadInfo*>::iterator it = controllers_.find(handle);
- if (it != controllers_.end())
- return it->second;
-
- return NULL;
-}
-
-RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
- UINT size = 0;
-
- // Do we already have this device in the map?
- if (GetGamepadInfo(hDevice))
- return NULL;
-
- // Query basic device info.
- UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO,
- NULL, &size);
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
- return NULL;
- }
- DCHECK_EQ(0u, result);
-
- std::unique_ptr<uint8_t[]> di_buffer(new uint8_t[size]);
- RID_DEVICE_INFO* device_info =
- reinterpret_cast<RID_DEVICE_INFO*>(di_buffer.get());
- result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO,
- di_buffer.get(), &size);
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
- return NULL;
- }
- DCHECK_EQ(size, result);
-
- // Make sure this device is of a type that we want to observe.
- bool valid_type = false;
- for (USHORT device_usage : DeviceUsages) {
- if (device_info->hid.usUsage == device_usage) {
- valid_type = true;
- break;
- }
- }
-
- if (!valid_type)
- return NULL;
-
- std::unique_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo);
- gamepad_info->handle = hDevice;
- gamepad_info->report_id = 0;
- gamepad_info->vendor_id = device_info->hid.dwVendorId;
- gamepad_info->product_id = device_info->hid.dwProductId;
- gamepad_info->buttons_length = 0;
- ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons));
- gamepad_info->axes_length = 0;
- ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes));
-
- // Query device identifier
- result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME,
- NULL, &size);
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
- return NULL;
- }
- DCHECK_EQ(0u, result);
-
- std::unique_ptr<wchar_t[]> name_buffer(new wchar_t[size]);
- result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME,
- name_buffer.get(), &size);
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
- return NULL;
- }
- DCHECK_EQ(size, result);
-
- // The presence of "IG_" in the device name indicates that this is an XInput
- // Gamepad. Skip enumerating these devices and let the XInput path handle it.
- // http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014.aspx
- if (filter_xinput_ && wcsstr( name_buffer.get(), L"IG_" ) )
- return NULL;
-
- // Get a friendly device name
- BOOLEAN got_product_string = FALSE;
- HANDLE hid_handle = CreateFile(name_buffer.get(), GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
- if (hid_handle) {
- got_product_string = hidd_get_product_string_(hid_handle, gamepad_info->id,
- sizeof(gamepad_info->id));
- CloseHandle(hid_handle);
- }
-
- if (!got_product_string)
- swprintf(gamepad_info->id, WebGamepad::idLengthCap, L"Unknown Gamepad");
-
- // Query device capabilities.
- result = GetRawInputDeviceInfo(hDevice, RIDI_PREPARSEDDATA,
- NULL, &size);
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
- return NULL;
- }
- DCHECK_EQ(0u, result);
-
- gamepad_info->ppd_buffer.reset(new uint8_t[size]);
- gamepad_info->preparsed_data =
- reinterpret_cast<PHIDP_PREPARSED_DATA>(gamepad_info->ppd_buffer.get());
- result = GetRawInputDeviceInfo(hDevice, RIDI_PREPARSEDDATA,
- gamepad_info->ppd_buffer.get(), &size);
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
- return NULL;
- }
- DCHECK_EQ(size, result);
-
- HIDP_CAPS caps;
- NTSTATUS status = hidp_get_caps_(gamepad_info->preparsed_data, &caps);
- DCHECK_EQ(HIDP_STATUS_SUCCESS, status);
-
- // Query button information.
- USHORT count = caps.NumberInputButtonCaps;
- if (count > 0) {
- std::unique_ptr<HIDP_BUTTON_CAPS[]> button_caps(
- new HIDP_BUTTON_CAPS[count]);
- status = hidp_get_button_caps_(
- HidP_Input, button_caps.get(), &count, gamepad_info->preparsed_data);
- DCHECK_EQ(HIDP_STATUS_SUCCESS, status);
-
- for (uint32_t i = 0; i < count; ++i) {
- if (button_caps[i].Range.UsageMin <= WebGamepad::buttonsLengthCap &&
- button_caps[i].UsagePage == kButtonUsagePage) {
- uint32_t max_index =
- std::min(WebGamepad::buttonsLengthCap,
- static_cast<size_t>(button_caps[i].Range.UsageMax));
- gamepad_info->buttons_length = std::max(
- gamepad_info->buttons_length, max_index);
- }
- }
- }
-
- // Query axis information.
- count = caps.NumberInputValueCaps;
- std::unique_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[count]);
- status = hidp_get_value_caps_(HidP_Input, axes_caps.get(), &count,
- gamepad_info->preparsed_data);
-
- bool mapped_all_axes = true;
-
- for (UINT i = 0; i < count; i++) {
- uint32_t axis_index = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber;
- if (axis_index < WebGamepad::axesLengthCap) {
- gamepad_info->axes[axis_index].caps = axes_caps[i];
- gamepad_info->axes[axis_index].value = 0;
- gamepad_info->axes[axis_index].active = true;
- gamepad_info->axes[axis_index].bitmask = GetBitmask(axes_caps[i].BitSize);
- gamepad_info->axes_length =
- std::max(gamepad_info->axes_length, axis_index + 1);
- } else {
- mapped_all_axes = false;
- }
- }
-
- if (!mapped_all_axes) {
- // For axes who's usage puts them outside the standard axesLengthCap range.
- uint32_t next_index = 0;
- for (UINT i = 0; i < count; i++) {
- uint32_t usage = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber;
- if (usage >= WebGamepad::axesLengthCap &&
- axes_caps[i].UsagePage <= kGameControlsUsagePage) {
-
- for (; next_index < WebGamepad::axesLengthCap; ++next_index) {
- if (!gamepad_info->axes[next_index].active)
- break;
- }
- if (next_index < WebGamepad::axesLengthCap) {
- gamepad_info->axes[next_index].caps = axes_caps[i];
- gamepad_info->axes[next_index].value = 0;
- gamepad_info->axes[next_index].active = true;
- gamepad_info->axes[next_index].bitmask = GetBitmask(
- axes_caps[i].BitSize);
- gamepad_info->axes_length =
- std::max(gamepad_info->axes_length, next_index + 1);
- }
- }
-
- if (next_index >= WebGamepad::axesLengthCap)
- break;
- }
- }
-
- return gamepad_info.release();
-}
-
-void RawInputDataFetcher::UpdateGamepad(
- RAWINPUT* input,
- RawGamepadInfo* gamepad_info) {
- NTSTATUS status;
-
- gamepad_info->report_id++;
-
- // Query button state.
- if (gamepad_info->buttons_length) {
- // Clear the button state
- ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons));
- ULONG buttons_length = 0;
-
- hidp_get_usages_ex_(HidP_Input,
- 0,
- NULL,
- &buttons_length,
- gamepad_info->preparsed_data,
- reinterpret_cast<PCHAR>(input->data.hid.bRawData),
- input->data.hid.dwSizeHid);
-
- std::unique_ptr<USAGE_AND_PAGE[]> usages(
- new USAGE_AND_PAGE[buttons_length]);
- status =
- hidp_get_usages_ex_(HidP_Input,
- 0,
- usages.get(),
- &buttons_length,
- gamepad_info->preparsed_data,
- reinterpret_cast<PCHAR>(input->data.hid.bRawData),
- input->data.hid.dwSizeHid);
-
- if (status == HIDP_STATUS_SUCCESS) {
- // Set each reported button to true.
- for (uint32_t j = 0; j < buttons_length; j++) {
- int32_t button_index = usages[j].Usage - 1;
- if (usages[j].UsagePage == kButtonUsagePage &&
- button_index >= 0 &&
- button_index <
- static_cast<int>(blink::WebGamepad::buttonsLengthCap)) {
- gamepad_info->buttons[button_index] = true;
- }
- }
- }
- }
-
- // Query axis state.
- ULONG axis_value = 0;
- LONG scaled_axis_value = 0;
- for (uint32_t i = 0; i < gamepad_info->axes_length; i++) {
- RawGamepadAxis* axis = &gamepad_info->axes[i];
-
- // If the min is < 0 we have to query the scaled value, otherwise we need
- // the normal unscaled value.
- if (axis->caps.LogicalMin < 0) {
- status = hidp_get_scaled_usage_value_(HidP_Input, axis->caps.UsagePage, 0,
- axis->caps.Range.UsageMin, &scaled_axis_value,
- gamepad_info->preparsed_data,
- reinterpret_cast<PCHAR>(input->data.hid.bRawData),
- input->data.hid.dwSizeHid);
- if (status == HIDP_STATUS_SUCCESS) {
- axis->value = NormalizeAxis(scaled_axis_value,
- axis->caps.PhysicalMin, axis->caps.PhysicalMax);
- }
- } else {
- status = hidp_get_usage_value_(HidP_Input, axis->caps.UsagePage, 0,
- axis->caps.Range.UsageMin, &axis_value,
- gamepad_info->preparsed_data,
- reinterpret_cast<PCHAR>(input->data.hid.bRawData),
- input->data.hid.dwSizeHid);
- if (status == HIDP_STATUS_SUCCESS) {
- axis->value = NormalizeAxis(axis_value & axis->bitmask,
- axis->caps.LogicalMin & axis->bitmask,
- axis->caps.LogicalMax & axis->bitmask);
- }
- }
- }
-}
-
-LRESULT RawInputDataFetcher::OnInput(HRAWINPUT input_handle) {
- // Get the size of the input record.
- UINT size = 0;
- UINT result = GetRawInputData(
- input_handle, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputData() failed";
- return 0;
- }
- DCHECK_EQ(0u, result);
-
- // Retrieve the input record.
- std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]);
- RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get());
- result = GetRawInputData(
- input_handle, RID_INPUT, buffer.get(), &size, sizeof(RAWINPUTHEADER));
- if (result == static_cast<UINT>(-1)) {
- PLOG(ERROR) << "GetRawInputData() failed";
- return 0;
- }
- DCHECK_EQ(size, result);
-
- // Notify the observer about events generated locally.
- if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) {
- RawGamepadInfo* gamepad = GetGamepadInfo(input->header.hDevice);
- if (gamepad)
- UpdateGamepad(input, gamepad);
- }
-
- return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
-}
-
-bool RawInputDataFetcher::HandleMessage(UINT message,
- WPARAM wparam,
- LPARAM lparam,
- LRESULT* result) {
- switch (message) {
- case WM_INPUT:
- *result = OnInput(reinterpret_cast<HRAWINPUT>(lparam));
- return true;
-
- default:
- return false;
- }
-}
-
-bool RawInputDataFetcher::GetHidDllFunctions() {
- hidp_get_caps_ = NULL;
- hidp_get_button_caps_ = NULL;
- hidp_get_value_caps_ = NULL;
- hidp_get_usages_ex_ = NULL;
- hidp_get_usage_value_ = NULL;
- hidp_get_scaled_usage_value_ = NULL;
- hidd_get_product_string_ = NULL;
-
- if (!hid_dll_.is_valid()) return false;
-
- hidp_get_caps_ = reinterpret_cast<HidPGetCapsFunc>(
- hid_dll_.GetFunctionPointer("HidP_GetCaps"));
- if (!hidp_get_caps_)
- return false;
- hidp_get_button_caps_ = reinterpret_cast<HidPGetButtonCapsFunc>(
- hid_dll_.GetFunctionPointer("HidP_GetButtonCaps"));
- if (!hidp_get_button_caps_)
- return false;
- hidp_get_value_caps_ = reinterpret_cast<HidPGetValueCapsFunc>(
- hid_dll_.GetFunctionPointer("HidP_GetValueCaps"));
- if (!hidp_get_value_caps_)
- return false;
- hidp_get_usages_ex_ = reinterpret_cast<HidPGetUsagesExFunc>(
- hid_dll_.GetFunctionPointer("HidP_GetUsagesEx"));
- if (!hidp_get_usages_ex_)
- return false;
- hidp_get_usage_value_ = reinterpret_cast<HidPGetUsageValueFunc>(
- hid_dll_.GetFunctionPointer("HidP_GetUsageValue"));
- if (!hidp_get_usage_value_)
- return false;
- hidp_get_scaled_usage_value_ = reinterpret_cast<HidPGetScaledUsageValueFunc>(
- hid_dll_.GetFunctionPointer("HidP_GetScaledUsageValue"));
- if (!hidp_get_scaled_usage_value_)
- return false;
- hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>(
- hid_dll_.GetFunctionPointer("HidD_GetProductString"));
- if (!hidd_get_product_string_)
- return false;
-
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gamepad/raw_input_data_fetcher_win.h b/chromium/content/browser/gamepad/raw_input_data_fetcher_win.h
deleted file mode 100644
index b65e6c9b9fa..00000000000
--- a/chromium/content/browser/gamepad/raw_input_data_fetcher_win.h
+++ /dev/null
@@ -1,144 +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_GAMEPAD_RAW_INPUT_DATA_FETCHER_WIN_H_
-#define CONTENT_BROWSER_GAMEPAD_RAW_INPUT_DATA_FETCHER_WIN_H_
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <Unknwn.h>
-#include <WinDef.h>
-#include <windows.h>
-#include <hidsdi.h>
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/scoped_native_library.h"
-#include "base/win/message_window.h"
-#include "build/build_config.h"
-#include "content/browser/gamepad/gamepad_data_fetcher.h"
-#include "content/browser/gamepad/gamepad_standard_mappings.h"
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-
-namespace content {
-
-struct RawGamepadAxis {
- HIDP_VALUE_CAPS caps;
- float value;
- bool active;
- unsigned long bitmask;
-};
-
-struct RawGamepadInfo {
- RawGamepadInfo();
- ~RawGamepadInfo();
-
- HANDLE handle;
- std::unique_ptr<uint8_t[]> ppd_buffer;
- PHIDP_PREPARSED_DATA preparsed_data;
-
- uint32_t report_id;
- uint32_t vendor_id;
- uint32_t product_id;
-
- wchar_t id[blink::WebGamepad::idLengthCap];
-
- uint32_t buttons_length;
- bool buttons[blink::WebGamepad::buttonsLengthCap];
-
- uint32_t axes_length;
- RawGamepadAxis axes[blink::WebGamepad::axesLengthCap];
-};
-
-class RawInputDataFetcher
- : public base::SupportsWeakPtr<RawInputDataFetcher>,
- public base::MessageLoop::DestructionObserver {
- public:
- explicit RawInputDataFetcher();
- ~RawInputDataFetcher() override;
-
- // DestructionObserver overrides.
- void WillDestroyCurrentMessageLoop() override;
-
- bool Available() { return rawinput_available_; }
- void StartMonitor();
- void StopMonitor();
-
- std::vector<RawGamepadInfo*> EnumerateDevices();
- RawGamepadInfo* GetGamepadInfo(HANDLE handle);
-
- private:
- RawGamepadInfo* ParseGamepadInfo(HANDLE hDevice);
- void UpdateGamepad(RAWINPUT* input, RawGamepadInfo* gamepad_info);
- // Handles WM_INPUT messages.
- LRESULT OnInput(HRAWINPUT input_handle);
- // Handles messages received by |window_|.
- bool HandleMessage(UINT message,
- WPARAM wparam,
- LPARAM lparam,
- LRESULT* result);
- RAWINPUTDEVICE* GetRawInputDevices(DWORD flags);
- void ClearControllers();
-
- // Function types we use from hid.dll.
- typedef NTSTATUS (__stdcall *HidPGetCapsFunc)(
- PHIDP_PREPARSED_DATA PreparsedData, PHIDP_CAPS Capabilities);
- typedef NTSTATUS (__stdcall *HidPGetButtonCapsFunc)(
- HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps,
- PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
- typedef NTSTATUS (__stdcall *HidPGetValueCapsFunc)(
- HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps,
- PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
- typedef NTSTATUS(__stdcall* HidPGetUsagesExFunc)(
- HIDP_REPORT_TYPE ReportType,
- USHORT LinkCollection,
- PUSAGE_AND_PAGE ButtonList,
- ULONG* UsageLength,
- PHIDP_PREPARSED_DATA PreparsedData,
- PCHAR Report,
- ULONG ReportLength);
- typedef NTSTATUS (__stdcall *HidPGetUsageValueFunc)(
- HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection,
- USAGE Usage, PULONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData,
- PCHAR Report, ULONG ReportLength);
- typedef NTSTATUS (__stdcall *HidPGetScaledUsageValueFunc)(
- HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection,
- USAGE Usage, PLONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData,
- PCHAR Report, ULONG ReportLength);
- typedef BOOLEAN (__stdcall *HidDGetStringFunc)(
- HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength);
-
- // Get functions from dynamically loaded hid.dll. Returns true if loading was
- // successful.
- bool GetHidDllFunctions();
-
- base::ScopedNativeLibrary hid_dll_;
- std::unique_ptr<base::win::MessageWindow> window_;
- bool rawinput_available_;
- bool filter_xinput_;
- bool events_monitored_;
-
- std::map<HANDLE, RawGamepadInfo*> controllers_;
-
- // Function pointers to HID functionality, retrieved in
- // |GetHidDllFunctions|.
- HidPGetCapsFunc hidp_get_caps_;
- HidPGetButtonCapsFunc hidp_get_button_caps_;
- HidPGetValueCapsFunc hidp_get_value_caps_;
- HidPGetUsagesExFunc hidp_get_usages_ex_;
- HidPGetUsageValueFunc hidp_get_usage_value_;
- HidPGetScaledUsageValueFunc hidp_get_scaled_usage_value_;
- HidDGetStringFunc hidd_get_product_string_;
-
- DISALLOW_COPY_AND_ASSIGN(RawInputDataFetcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GAMEPAD_RAW_INPUT_DATA_FETCHER_WIN_H_
diff --git a/chromium/content/browser/gamepad/xbox_data_fetcher_mac.cc b/chromium/content/browser/gamepad/xbox_data_fetcher_mac.cc
deleted file mode 100644
index 7ef35318d18..00000000000
--- a/chromium/content/browser/gamepad/xbox_data_fetcher_mac.cc
+++ /dev/null
@@ -1,809 +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/gamepad/xbox_data_fetcher_mac.h"
-
-#include <algorithm>
-#include <cmath>
-#include <limits>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/usb/IOUSBLib.h>
-#include <IOKit/usb/USB.h>
-
-#include "base/logging.h"
-#include "base/mac/foundation_util.h"
-
-namespace {
-const int kVendorMicrosoft = 0x045e;
-const int kProductXbox360Controller = 0x028e;
-const int kProductXboxOneController = 0x02d1;
-
-const int kXbox360ReadEndpoint = 1;
-const int kXbox360ControlEndpoint = 2;
-
-const int kXboxOneReadEndpoint = 2;
-const int kXboxOneControlEndpoint = 1;
-
-enum {
- STATUS_MESSAGE_BUTTONS = 0,
- STATUS_MESSAGE_LED = 1,
-
- // Apparently this message tells you if the rumble pack is disabled in the
- // controller. If the rumble pack is disabled, vibration control messages
- // have no effect.
- STATUS_MESSAGE_RUMBLE = 3,
-};
-
-enum {
- XBOX_ONE_STATUS_MESSAGE_BUTTONS = 0x20,
-};
-
-enum {
- CONTROL_MESSAGE_SET_RUMBLE = 0,
- CONTROL_MESSAGE_SET_LED = 1,
-};
-
-#pragma pack(push, 1)
-struct Xbox360ButtonData {
- bool dpad_up : 1;
- bool dpad_down : 1;
- bool dpad_left : 1;
- bool dpad_right : 1;
-
- bool start : 1;
- bool back : 1;
- bool stick_left_click : 1;
- bool stick_right_click : 1;
-
- bool bumper_left : 1;
- bool bumper_right : 1;
- bool guide : 1;
- bool dummy1 : 1; // Always 0.
-
- bool a : 1;
- bool b : 1;
- bool x : 1;
- bool y : 1;
-
- uint8_t trigger_left;
- uint8_t trigger_right;
-
- int16_t stick_left_x;
- int16_t stick_left_y;
- int16_t stick_right_x;
- int16_t stick_right_y;
-
- // Always 0.
- uint32_t dummy2;
- uint16_t dummy3;
-};
-
-struct XboxOneButtonData {
- bool sync : 1;
- bool dummy1 : 1; // Always 0.
- bool start : 1;
- bool back : 1;
-
- bool a : 1;
- bool b : 1;
- bool x : 1;
- bool y : 1;
-
- bool dpad_up : 1;
- bool dpad_down : 1;
- bool dpad_left : 1;
- bool dpad_right : 1;
-
- bool bumper_left : 1;
- bool bumper_right : 1;
- bool stick_left_click : 1;
- bool stick_right_click : 1;
-
- uint16_t trigger_left;
- uint16_t trigger_right;
-
- int16_t stick_left_x;
- int16_t stick_left_y;
- int16_t stick_right_x;
- int16_t stick_right_y;
-};
-#pragma pack(pop)
-
-static_assert(sizeof(Xbox360ButtonData) == 18, "xbox button data wrong size");
-static_assert(sizeof(XboxOneButtonData) == 14, "xbox button data wrong size");
-
-// From MSDN:
-// http://msdn.microsoft.com/en-us/library/windows/desktop/ee417001(v=vs.85).aspx#dead_zone
-const int16_t kLeftThumbDeadzone = 7849;
-const int16_t kRightThumbDeadzone = 8689;
-const uint8_t kXbox360TriggerDeadzone = 30;
-const uint16_t kXboxOneTriggerMax = 1023;
-const uint16_t kXboxOneTriggerDeadzone = 120;
-
-void NormalizeAxis(int16_t x,
- int16_t y,
- int16_t deadzone,
- float* x_out,
- float* y_out) {
- float x_val = x;
- float y_val = y;
-
- // Determine how far the stick is pushed.
- float real_magnitude = std::sqrt(x_val * x_val + y_val * y_val);
-
- // Check if the controller is outside a circular dead zone.
- if (real_magnitude > deadzone) {
- // Clip the magnitude at its expected maximum value.
- float magnitude = std::min(32767.0f, real_magnitude);
-
- // Adjust magnitude relative to the end of the dead zone.
- magnitude -= deadzone;
-
- // Normalize the magnitude with respect to its expected range giving a
- // magnitude value of 0.0 to 1.0
- float ratio = (magnitude / (32767 - deadzone)) / real_magnitude;
-
- // Y is negated because xbox controllers have an opposite sign from
- // the 'standard controller' recommendations.
- *x_out = x_val * ratio;
- *y_out = -y_val * ratio;
- } else {
- // If the controller is in the deadzone zero out the magnitude.
- *x_out = *y_out = 0.0f;
- }
-}
-
-float NormalizeTrigger(uint8_t value) {
- return value < kXbox360TriggerDeadzone
- ? 0
- : static_cast<float>(value - kXbox360TriggerDeadzone) /
- (std::numeric_limits<uint8_t>::max() -
- kXbox360TriggerDeadzone);
-}
-
-float NormalizeXboxOneTrigger(uint16_t value) {
- return value < kXboxOneTriggerDeadzone ? 0 :
- static_cast<float>(value - kXboxOneTriggerDeadzone) /
- (kXboxOneTriggerMax - kXboxOneTriggerDeadzone);
-}
-
-void NormalizeXbox360ButtonData(const Xbox360ButtonData& data,
- XboxController::Data* normalized_data) {
- normalized_data->buttons[0] = data.a;
- normalized_data->buttons[1] = data.b;
- normalized_data->buttons[2] = data.x;
- normalized_data->buttons[3] = data.y;
- normalized_data->buttons[4] = data.bumper_left;
- normalized_data->buttons[5] = data.bumper_right;
- normalized_data->buttons[6] = data.back;
- normalized_data->buttons[7] = data.start;
- normalized_data->buttons[8] = data.stick_left_click;
- normalized_data->buttons[9] = data.stick_right_click;
- normalized_data->buttons[10] = data.dpad_up;
- normalized_data->buttons[11] = data.dpad_down;
- normalized_data->buttons[12] = data.dpad_left;
- normalized_data->buttons[13] = data.dpad_right;
- normalized_data->buttons[14] = data.guide;
- normalized_data->triggers[0] = NormalizeTrigger(data.trigger_left);
- normalized_data->triggers[1] = NormalizeTrigger(data.trigger_right);
- NormalizeAxis(data.stick_left_x,
- data.stick_left_y,
- kLeftThumbDeadzone,
- &normalized_data->axes[0],
- &normalized_data->axes[1]);
- NormalizeAxis(data.stick_right_x,
- data.stick_right_y,
- kRightThumbDeadzone,
- &normalized_data->axes[2],
- &normalized_data->axes[3]);
-}
-
-void NormalizeXboxOneButtonData(const XboxOneButtonData& data,
- XboxController::Data* normalized_data) {
- normalized_data->buttons[0] = data.a;
- normalized_data->buttons[1] = data.b;
- normalized_data->buttons[2] = data.x;
- normalized_data->buttons[3] = data.y;
- normalized_data->buttons[4] = data.bumper_left;
- normalized_data->buttons[5] = data.bumper_right;
- normalized_data->buttons[6] = data.back;
- normalized_data->buttons[7] = data.start;
- normalized_data->buttons[8] = data.stick_left_click;
- normalized_data->buttons[9] = data.stick_right_click;
- normalized_data->buttons[10] = data.dpad_up;
- normalized_data->buttons[11] = data.dpad_down;
- normalized_data->buttons[12] = data.dpad_left;
- normalized_data->buttons[13] = data.dpad_right;
- normalized_data->buttons[14] = data.sync;
- normalized_data->triggers[0] = NormalizeXboxOneTrigger(data.trigger_left);
- normalized_data->triggers[1] = NormalizeXboxOneTrigger(data.trigger_right);
- NormalizeAxis(data.stick_left_x,
- data.stick_left_y,
- kLeftThumbDeadzone,
- &normalized_data->axes[0],
- &normalized_data->axes[1]);
- NormalizeAxis(data.stick_right_x,
- data.stick_right_y,
- kRightThumbDeadzone,
- &normalized_data->axes[2],
- &normalized_data->axes[3]);
-}
-
-} // namespace
-
-XboxController::XboxController(Delegate* delegate)
- : device_(NULL),
- interface_(NULL),
- device_is_open_(false),
- interface_is_open_(false),
- read_buffer_size_(0),
- led_pattern_(LED_NUM_PATTERNS),
- location_id_(0),
- delegate_(delegate),
- controller_type_(UNKNOWN_CONTROLLER),
- read_endpoint_(0),
- control_endpoint_(0) {
-}
-
-XboxController::~XboxController() {
- if (source_)
- CFRunLoopSourceInvalidate(source_);
- if (interface_ && interface_is_open_)
- (*interface_)->USBInterfaceClose(interface_);
- if (device_ && device_is_open_)
- (*device_)->USBDeviceClose(device_);
-}
-
-bool XboxController::OpenDevice(io_service_t service) {
- IOCFPlugInInterface **plugin;
- SInt32 score; // Unused, but required for IOCreatePlugInInterfaceForService.
- kern_return_t kr =
- IOCreatePlugInInterfaceForService(service,
- kIOUSBDeviceUserClientTypeID,
- kIOCFPlugInInterfaceID,
- &plugin,
- &score);
- if (kr != KERN_SUCCESS)
- return false;
- base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> plugin_ref(plugin);
-
- HRESULT res =
- (*plugin)->QueryInterface(plugin,
- CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID320),
- (LPVOID *)&device_);
- if (!SUCCEEDED(res) || !device_)
- return false;
-
- UInt16 vendor_id;
- kr = (*device_)->GetDeviceVendor(device_, &vendor_id);
- if (kr != KERN_SUCCESS || vendor_id != kVendorMicrosoft)
- return false;
-
- UInt16 product_id;
- kr = (*device_)->GetDeviceProduct(device_, &product_id);
- if (kr != KERN_SUCCESS)
- return false;
-
- IOUSBFindInterfaceRequest request;
- switch (product_id) {
- case kProductXbox360Controller:
- controller_type_ = XBOX_360_CONTROLLER;
- read_endpoint_ = kXbox360ReadEndpoint;
- control_endpoint_ = kXbox360ControlEndpoint;
- request.bInterfaceClass = 255;
- request.bInterfaceSubClass = 93;
- request.bInterfaceProtocol = 1;
- request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
- break;
- case kProductXboxOneController:
- controller_type_ = XBOX_ONE_CONTROLLER;
- read_endpoint_ = kXboxOneReadEndpoint;
- control_endpoint_ = kXboxOneControlEndpoint;
- request.bInterfaceClass = 255;
- request.bInterfaceSubClass = 71;
- request.bInterfaceProtocol = 208;
- request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
- break;
- default:
- return false;
- }
-
- // Open the device and configure it.
- kr = (*device_)->USBDeviceOpen(device_);
- if (kr != KERN_SUCCESS)
- return false;
- device_is_open_ = true;
-
- // Xbox controllers have one configuration option which has configuration
- // value 1. Try to set it and fail if it couldn't be configured.
- IOUSBConfigurationDescriptorPtr config_desc;
- kr = (*device_)->GetConfigurationDescriptorPtr(device_, 0, &config_desc);
- if (kr != KERN_SUCCESS)
- return false;
- kr = (*device_)->SetConfiguration(device_, config_desc->bConfigurationValue);
- if (kr != KERN_SUCCESS)
- return false;
-
- // The device has 4 interfaces. They are as follows:
- // Protocol 1:
- // - Endpoint 1 (in) : Controller events, including button presses.
- // - Endpoint 2 (out): Rumble pack and LED control
- // Protocol 2 has a single endpoint to read from a connected ChatPad device.
- // Protocol 3 is used by a connected headset device.
- // The device also has an interface on subclass 253, protocol 10 with no
- // endpoints. It is unused.
- //
- // We don't currently support the ChatPad or headset, so protocol 1 is the
- // only protocol we care about.
- //
- // For more detail, see
- // https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL
- io_iterator_t iter;
- kr = (*device_)->CreateInterfaceIterator(device_, &request, &iter);
- if (kr != KERN_SUCCESS)
- return false;
- base::mac::ScopedIOObject<io_iterator_t> iter_ref(iter);
-
- // There should be exactly one USB interface which matches the requested
- // settings.
- io_service_t usb_interface = IOIteratorNext(iter);
- if (!usb_interface)
- return false;
-
- // We need to make an InterfaceInterface to communicate with the device
- // endpoint. This is the same process as earlier: first make a
- // PluginInterface from the io_service then make the InterfaceInterface from
- // that.
- IOCFPlugInInterface **plugin_interface;
- kr = IOCreatePlugInInterfaceForService(usb_interface,
- kIOUSBInterfaceUserClientTypeID,
- kIOCFPlugInInterfaceID,
- &plugin_interface,
- &score);
- if (kr != KERN_SUCCESS || !plugin_interface)
- return false;
- base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> interface_ref(
- plugin_interface);
-
- // Release the USB interface, and any subsequent interfaces returned by the
- // iterator. (There shouldn't be any, but in case a future device does
- // contain more interfaces, this will serve to avoid memory leaks.)
- do {
- IOObjectRelease(usb_interface);
- } while ((usb_interface = IOIteratorNext(iter)));
-
- // Actually create the interface.
- res = (*plugin_interface)->QueryInterface(
- plugin_interface,
- CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID300),
- (LPVOID *)&interface_);
-
- if (!SUCCEEDED(res) || !interface_)
- return false;
-
- // Actually open the interface.
- kr = (*interface_)->USBInterfaceOpen(interface_);
- if (kr != KERN_SUCCESS)
- return false;
- interface_is_open_ = true;
-
- CFRunLoopSourceRef source_ref;
- kr = (*interface_)->CreateInterfaceAsyncEventSource(interface_, &source_ref);
- if (kr != KERN_SUCCESS || !source_ref)
- return false;
- source_.reset(source_ref);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), source_, kCFRunLoopDefaultMode);
-
- // The interface should have two pipes. Pipe 1 with direction kUSBIn and pipe
- // 2 with direction kUSBOut. Both pipes should have type kUSBInterrupt.
- uint8_t num_endpoints;
- kr = (*interface_)->GetNumEndpoints(interface_, &num_endpoints);
- if (kr != KERN_SUCCESS || num_endpoints < 2)
- return false;
-
- for (int i = 1; i <= 2; i++) {
- uint8_t direction;
- uint8_t number;
- uint8_t transfer_type;
- uint16_t max_packet_size;
- uint8_t interval;
-
- kr = (*interface_)->GetPipeProperties(interface_,
- i,
- &direction,
- &number,
- &transfer_type,
- &max_packet_size,
- &interval);
- if (kr != KERN_SUCCESS || transfer_type != kUSBInterrupt) {
- return false;
- }
- if (i == read_endpoint_) {
- if (direction != kUSBIn)
- return false;
- read_buffer_.reset(new uint8_t[max_packet_size]);
- read_buffer_size_ = max_packet_size;
- QueueRead();
- } else if (i == control_endpoint_) {
- if (direction != kUSBOut)
- return false;
- if (controller_type_ == XBOX_ONE_CONTROLLER)
- WriteXboxOneInit();
- }
- }
-
- // The location ID is unique per controller, and can be used to track
- // controllers through reconnections (though if a controller is detached from
- // one USB hub and attached to another, the location ID will change).
- kr = (*device_)->GetLocationID(device_, &location_id_);
- if (kr != KERN_SUCCESS)
- return false;
-
- return true;
-}
-
-void XboxController::SetLEDPattern(LEDPattern pattern) {
- led_pattern_ = pattern;
- const UInt8 length = 3;
-
- // This buffer will be released in WriteComplete when WritePipeAsync
- // finishes.
- UInt8* buffer = new UInt8[length];
- buffer[0] = static_cast<UInt8>(CONTROL_MESSAGE_SET_LED);
- buffer[1] = length;
- buffer[2] = static_cast<UInt8>(pattern);
- kern_return_t kr = (*interface_)->WritePipeAsync(interface_,
- control_endpoint_,
- buffer,
- (UInt32)length,
- WriteComplete,
- buffer);
- if (kr != KERN_SUCCESS) {
- delete[] buffer;
- IOError();
- return;
- }
-}
-
-int XboxController::GetVendorId() const {
- return kVendorMicrosoft;
-}
-
-int XboxController::GetProductId() const {
- if (controller_type_ == XBOX_360_CONTROLLER)
- return kProductXbox360Controller;
- else
- return kProductXboxOneController;
-}
-
-XboxController::ControllerType XboxController::GetControllerType() const {
- return controller_type_;
-}
-
-void XboxController::WriteComplete(void* context, IOReturn result, void* arg0) {
- UInt8* buffer = static_cast<UInt8*>(context);
- delete[] buffer;
-
- // Ignoring any errors sending data, because they will usually only occur
- // when the device is disconnected, in which case it really doesn't matter if
- // the data got to the controller or not.
- if (result != kIOReturnSuccess)
- return;
-}
-
-void XboxController::GotData(void* context, IOReturn result, void* arg0) {
- size_t bytes_read = reinterpret_cast<size_t>(arg0);
- XboxController* controller = static_cast<XboxController*>(context);
-
- if (result != kIOReturnSuccess) {
- // This will happen if the device was disconnected. The gamepad has
- // probably been destroyed by a meteorite.
- controller->IOError();
- return;
- }
-
- if (controller->GetControllerType() == XBOX_360_CONTROLLER)
- controller->ProcessXbox360Packet(bytes_read);
- else
- controller->ProcessXboxOnePacket(bytes_read);
-
- // Queue up another read.
- controller->QueueRead();
-}
-
-void XboxController::ProcessXbox360Packet(size_t length) {
- if (length < 2)
- return;
- DCHECK(length <= read_buffer_size_);
- if (length > read_buffer_size_) {
- IOError();
- return;
- }
- uint8_t* buffer = read_buffer_.get();
-
- if (buffer[1] != length)
- // Length in packet doesn't match length reported by USB.
- return;
-
- uint8_t type = buffer[0];
- buffer += 2;
- length -= 2;
- switch (type) {
- case STATUS_MESSAGE_BUTTONS: {
- if (length != sizeof(Xbox360ButtonData))
- return;
- Xbox360ButtonData* data = reinterpret_cast<Xbox360ButtonData*>(buffer);
- Data normalized_data;
- NormalizeXbox360ButtonData(*data, &normalized_data);
- delegate_->XboxControllerGotData(this, normalized_data);
- break;
- }
- case STATUS_MESSAGE_LED:
- if (length != 3)
- return;
- // The controller sends one of these messages every time the LED pattern
- // is set, as well as once when it is plugged in.
- if (led_pattern_ == LED_NUM_PATTERNS && buffer[0] < LED_NUM_PATTERNS)
- led_pattern_ = static_cast<LEDPattern>(buffer[0]);
- break;
- default:
- // Unknown packet: ignore!
- break;
- }
-}
-
-void XboxController::ProcessXboxOnePacket(size_t length) {
- if (length < 2)
- return;
- DCHECK(length <= read_buffer_size_);
- if (length > read_buffer_size_) {
- IOError();
- return;
- }
- uint8_t* buffer = read_buffer_.get();
-
- uint8_t type = buffer[0];
- buffer += 4;
- length -= 4;
- switch (type) {
- case XBOX_ONE_STATUS_MESSAGE_BUTTONS: {
- if (length != sizeof(XboxOneButtonData))
- return;
- XboxOneButtonData* data = reinterpret_cast<XboxOneButtonData*>(buffer);
- Data normalized_data;
- NormalizeXboxOneButtonData(*data, &normalized_data);
- delegate_->XboxControllerGotData(this, normalized_data);
- break;
- }
- default:
- // Unknown packet: ignore!
- break;
- }
-}
-
-void XboxController::QueueRead() {
- kern_return_t kr = (*interface_)->ReadPipeAsync(interface_,
- read_endpoint_,
- read_buffer_.get(),
- read_buffer_size_,
- GotData,
- this);
- if (kr != KERN_SUCCESS)
- IOError();
-}
-
-void XboxController::IOError() {
- delegate_->XboxControllerError(this);
-}
-
-void XboxController::WriteXboxOneInit() {
- const UInt8 length = 2;
-
- // This buffer will be released in WriteComplete when WritePipeAsync
- // finishes.
- UInt8* buffer = new UInt8[length];
- buffer[0] = 0x05;
- buffer[1] = 0x20;
- kern_return_t kr = (*interface_)->WritePipeAsync(interface_,
- control_endpoint_,
- buffer,
- (UInt32)length,
- WriteComplete,
- buffer);
- if (kr != KERN_SUCCESS) {
- delete[] buffer;
- IOError();
- return;
- }
-}
-
-//-----------------------------------------------------------------------------
-
-XboxDataFetcher::XboxDataFetcher(Delegate* delegate)
- : delegate_(delegate),
- listening_(false),
- source_(NULL),
- port_(NULL) {
-}
-
-XboxDataFetcher::~XboxDataFetcher() {
- while (!controllers_.empty()) {
- RemoveController(*controllers_.begin());
- }
- UnregisterFromNotifications();
-}
-
-void XboxDataFetcher::DeviceAdded(void* context, io_iterator_t iterator) {
- DCHECK(context);
- XboxDataFetcher* fetcher = static_cast<XboxDataFetcher*>(context);
- io_service_t ref;
- while ((ref = IOIteratorNext(iterator))) {
- base::mac::ScopedIOObject<io_service_t> scoped_ref(ref);
- XboxController* controller = new XboxController(fetcher);
- if (controller->OpenDevice(ref)) {
- fetcher->AddController(controller);
- } else {
- delete controller;
- }
- }
-}
-
-void XboxDataFetcher::DeviceRemoved(void* context, io_iterator_t iterator) {
- DCHECK(context);
- XboxDataFetcher* fetcher = static_cast<XboxDataFetcher*>(context);
- io_service_t ref;
- while ((ref = IOIteratorNext(iterator))) {
- base::mac::ScopedIOObject<io_service_t> scoped_ref(ref);
- base::ScopedCFTypeRef<CFNumberRef> number(
- base::mac::CFCastStrict<CFNumberRef>(
- IORegistryEntryCreateCFProperty(ref,
- CFSTR(kUSBDevicePropertyLocationID),
- kCFAllocatorDefault,
- kNilOptions)));
- UInt32 location_id = 0;
- CFNumberGetValue(number, kCFNumberSInt32Type, &location_id);
- fetcher->RemoveControllerByLocationID(location_id);
- }
-}
-
-bool XboxDataFetcher::RegisterForNotifications() {
- if (listening_)
- return true;
- port_ = IONotificationPortCreate(kIOMasterPortDefault);
- if (!port_)
- return false;
- source_ = IONotificationPortGetRunLoopSource(port_);
- if (!source_)
- return false;
- CFRunLoopAddSource(CFRunLoopGetCurrent(), source_, kCFRunLoopDefaultMode);
-
- listening_ = true;
-
- if (!RegisterForDeviceNotifications(
- kVendorMicrosoft, kProductXboxOneController,
- &xbox_one_device_added_iter_,
- &xbox_one_device_removed_iter_))
- return false;
-
- if (!RegisterForDeviceNotifications(
- kVendorMicrosoft, kProductXbox360Controller,
- &xbox_360_device_added_iter_,
- &xbox_360_device_removed_iter_))
- return false;
-
- return true;
-}
-
-bool XboxDataFetcher::RegisterForDeviceNotifications(
- int vendor_id,
- int product_id,
- base::mac::ScopedIOObject<io_iterator_t>* added_iter,
- base::mac::ScopedIOObject<io_iterator_t>* removed_iter) {
- base::ScopedCFTypeRef<CFNumberRef> vendor_cf(CFNumberCreate(
- kCFAllocatorDefault, kCFNumberSInt32Type, &vendor_id));
- base::ScopedCFTypeRef<CFNumberRef> product_cf(CFNumberCreate(
- kCFAllocatorDefault, kCFNumberSInt32Type, &product_id));
- base::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict(
- IOServiceMatching(kIOUSBDeviceClassName));
- if (!matching_dict)
- return false;
- CFDictionarySetValue(matching_dict, CFSTR(kUSBVendorID), vendor_cf);
- CFDictionarySetValue(matching_dict, CFSTR(kUSBProductID), product_cf);
-
- // IOServiceAddMatchingNotification() releases the dictionary when it's done.
- // Retain it before each call to IOServiceAddMatchingNotification to keep
- // things balanced.
- CFRetain(matching_dict);
- io_iterator_t device_added_iter;
- IOReturn ret;
- ret = IOServiceAddMatchingNotification(port_,
- kIOFirstMatchNotification,
- matching_dict,
- DeviceAdded,
- this,
- &device_added_iter);
- added_iter->reset(device_added_iter);
- if (ret != kIOReturnSuccess) {
- LOG(ERROR) << "Error listening for Xbox controller add events: " << ret;
- return false;
- }
- DeviceAdded(this, added_iter->get());
-
- CFRetain(matching_dict);
- io_iterator_t device_removed_iter;
- ret = IOServiceAddMatchingNotification(port_,
- kIOTerminatedNotification,
- matching_dict,
- DeviceRemoved,
- this,
- &device_removed_iter);
- removed_iter->reset(device_removed_iter);
- if (ret != kIOReturnSuccess) {
- LOG(ERROR) << "Error listening for Xbox controller remove events: " << ret;
- return false;
- }
- DeviceRemoved(this, removed_iter->get());
- return true;
-}
-
-void XboxDataFetcher::UnregisterFromNotifications() {
- if (!listening_)
- return;
- listening_ = false;
- if (source_)
- CFRunLoopSourceInvalidate(source_);
- if (port_)
- IONotificationPortDestroy(port_);
- port_ = NULL;
-}
-
-XboxController* XboxDataFetcher::ControllerForLocation(UInt32 location_id) {
- for (std::set<XboxController*>::iterator i = controllers_.begin();
- i != controllers_.end();
- ++i) {
- if ((*i)->location_id() == location_id)
- return *i;
- }
- return NULL;
-}
-
-void XboxDataFetcher::AddController(XboxController* controller) {
- DCHECK(!ControllerForLocation(controller->location_id()))
- << "Controller with location ID " << controller->location_id()
- << " already exists in the set of controllers.";
- controllers_.insert(controller);
- delegate_->XboxDeviceAdd(controller);
-}
-
-void XboxDataFetcher::RemoveController(XboxController* controller) {
- delegate_->XboxDeviceRemove(controller);
- controllers_.erase(controller);
- delete controller;
-}
-
-void XboxDataFetcher::RemoveControllerByLocationID(uint32_t location_id) {
- XboxController* controller = NULL;
- for (std::set<XboxController*>::iterator i = controllers_.begin();
- i != controllers_.end();
- ++i) {
- if ((*i)->location_id() == location_id) {
- controller = *i;
- break;
- }
- }
- if (controller)
- RemoveController(controller);
-}
-
-void XboxDataFetcher::XboxControllerGotData(XboxController* controller,
- const XboxController::Data& data) {
- delegate_->XboxValueChanged(controller, data);
-}
-
-void XboxDataFetcher::XboxControllerError(XboxController* controller) {
- RemoveController(controller);
-}
diff --git a/chromium/content/browser/gamepad/xbox_data_fetcher_mac.h b/chromium/content/browser/gamepad/xbox_data_fetcher_mac.h
deleted file mode 100644
index e4b98ff7fe2..00000000000
--- a/chromium/content/browser/gamepad/xbox_data_fetcher_mac.h
+++ /dev/null
@@ -1,190 +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_GAMEPAD_XBOX_DATA_FETCHER_MAC_H_
-#define CONTENT_BROWSER_GAMEPAD_XBOX_DATA_FETCHER_MAC_H_
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOKitLib.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <set>
-
-#include "base/mac/scoped_cftyperef.h"
-#include "base/mac/scoped_ioobject.h"
-#include "base/mac/scoped_ioplugininterface.h"
-#include "base/macros.h"
-
-class XboxController {
- public:
- enum ControllerType {
- UNKNOWN_CONTROLLER,
- XBOX_360_CONTROLLER,
- XBOX_ONE_CONTROLLER
- };
-
- enum LEDPattern {
- LED_OFF = 0,
-
- // 2 quick flashes, then a series of slow flashes (about 1 per second).
- LED_FLASH = 1,
-
- // Flash three times then hold the LED on. This is the standard way to tell
- // the player which player number they are.
- LED_FLASH_TOP_LEFT = 2,
- LED_FLASH_TOP_RIGHT = 3,
- LED_FLASH_BOTTOM_LEFT = 4,
- LED_FLASH_BOTTOM_RIGHT = 5,
-
- // Simply turn on the specified LED and turn all other LEDs off.
- LED_HOLD_TOP_LEFT = 6,
- LED_HOLD_TOP_RIGHT = 7,
- LED_HOLD_BOTTOM_LEFT = 8,
- LED_HOLD_BOTTOM_RIGHT = 9,
-
- LED_ROTATE = 10,
-
- LED_FLASH_FAST = 11,
- LED_FLASH_SLOW = 12, // Flash about once per 3 seconds
-
- // Flash alternating LEDs for a few seconds, then flash all LEDs about once
- // per second
- LED_ALTERNATE_PATTERN = 13,
-
- // 14 is just another boring flashing speed.
-
- // Flash all LEDs once then go black.
- LED_FLASH_ONCE = 15,
-
- LED_NUM_PATTERNS
- };
-
- struct Data {
- bool buttons[15];
- float triggers[2];
- float axes[4];
- };
-
- class Delegate {
- public:
- virtual void XboxControllerGotData(XboxController* controller,
- const Data& data) = 0;
- virtual void XboxControllerError(XboxController* controller) = 0;
- };
-
- explicit XboxController(Delegate* delegate_);
- virtual ~XboxController();
-
- bool OpenDevice(io_service_t service);
-
- void SetLEDPattern(LEDPattern pattern);
-
- UInt32 location_id() { return location_id_; }
- int GetVendorId() const;
- int GetProductId() const;
- ControllerType GetControllerType() const;
-
- private:
- static void WriteComplete(void* context, IOReturn result, void* arg0);
- static void GotData(void* context, IOReturn result, void* arg0);
-
- void ProcessXbox360Packet(size_t length);
- void ProcessXboxOnePacket(size_t length);
- void QueueRead();
-
- void IOError();
-
- void WriteXboxOneInit();
-
- // Handle for the USB device. IOUSBDeviceStruct320 is the latest version of
- // the device API that is supported on Mac OS 10.6.
- base::mac::ScopedIOPluginInterface<struct IOUSBDeviceStruct320> device_;
-
- // Handle for the interface on the device which sends button and analog data.
- // The other interfaces (for the ChatPad and headset) are ignored.
- base::mac::ScopedIOPluginInterface<struct IOUSBInterfaceStruct300> interface_;
-
- bool device_is_open_;
- bool interface_is_open_;
-
- base::ScopedCFTypeRef<CFRunLoopSourceRef> source_;
-
- // This will be set to the max packet size reported by the interface, which
- // is 32 bytes. I would have expected USB to do message framing itself, but
- // somehow we still sometimes (rarely!) get packets off the interface which
- // aren't correctly framed. The 360 controller frames its packets with a 2
- // byte header (type, total length) so we can reframe the packet data
- // ourselves.
- uint16_t read_buffer_size_;
- std::unique_ptr<uint8_t[]> read_buffer_;
-
- // The pattern that the LEDs on the device are currently displaying, or
- // LED_NUM_PATTERNS if unknown.
- LEDPattern led_pattern_;
-
- UInt32 location_id_;
-
- Delegate* delegate_;
-
- ControllerType controller_type_;
- int read_endpoint_;
- int control_endpoint_;
-
- DISALLOW_COPY_AND_ASSIGN(XboxController);
-};
-
-class XboxDataFetcher : public XboxController::Delegate {
- public:
- class Delegate {
- public:
- virtual void XboxDeviceAdd(XboxController* device) = 0;
- virtual void XboxDeviceRemove(XboxController* device) = 0;
- virtual void XboxValueChanged(XboxController* device,
- const XboxController::Data& data) = 0;
- };
-
- explicit XboxDataFetcher(Delegate* delegate);
- virtual ~XboxDataFetcher();
-
- bool RegisterForNotifications();
- bool RegisterForDeviceNotifications(
- int vendor_id,
- int product_id,
- base::mac::ScopedIOObject<io_iterator_t>* added_iter,
- base::mac::ScopedIOObject<io_iterator_t>* removed_iter);
- void UnregisterFromNotifications();
-
- XboxController* ControllerForLocation(UInt32 location_id);
-
- private:
- static void DeviceAdded(void* context, io_iterator_t iterator);
- static void DeviceRemoved(void* context, io_iterator_t iterator);
- void AddController(XboxController* controller);
- void RemoveController(XboxController* controller);
- void RemoveControllerByLocationID(uint32_t id);
- void XboxControllerGotData(XboxController* controller,
- const XboxController::Data& data) override;
- void XboxControllerError(XboxController* controller) override;
-
- Delegate* delegate_;
-
- std::set<XboxController*> controllers_;
-
- bool listening_;
-
- // port_ owns source_, so this doesn't need to be a ScopedCFTypeRef, but we
- // do need to maintain a reference to it so we can invalidate it.
- CFRunLoopSourceRef source_;
- IONotificationPortRef port_;
- base::mac::ScopedIOObject<io_iterator_t> xbox_360_device_added_iter_;
- base::mac::ScopedIOObject<io_iterator_t> xbox_360_device_removed_iter_;
- base::mac::ScopedIOObject<io_iterator_t> xbox_one_device_added_iter_;
- base::mac::ScopedIOObject<io_iterator_t> xbox_one_device_removed_iter_;
-
- DISALLOW_COPY_AND_ASSIGN(XboxDataFetcher);
-};
-
-#endif // CONTENT_BROWSER_GAMEPAD_XBOX_DATA_FETCHER_MAC_H_
diff --git a/chromium/content/browser/geolocation/geolocation_provider_impl.cc b/chromium/content/browser/geolocation/geolocation_provider_impl.cc
index f3d6e37e062..df8fd635bdf 100644
--- a/chromium/content/browser/geolocation/geolocation_provider_impl.cc
+++ b/chromium/content/browser/geolocation/geolocation_provider_impl.cc
@@ -14,6 +14,8 @@
#include "base/single_thread_task_runner.h"
#include "content/browser/geolocation/location_arbitrator_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/geolocation_delegate.h"
namespace content {
@@ -174,7 +176,14 @@ std::unique_ptr<LocationArbitrator>
GeolocationProviderImpl::CreateArbitrator() {
LocationArbitratorImpl::LocationUpdateCallback callback = base::Bind(
&GeolocationProviderImpl::OnLocationUpdate, base::Unretained(this));
- return base::WrapUnique(new LocationArbitratorImpl(callback));
+
+ // Use the embedder's Delegate or fall back to the default one.
+ delegate_.reset(GetContentClient()->browser()->CreateGeolocationDelegate());
+ if (!delegate_)
+ delegate_.reset(new GeolocationDelegate);
+
+ return base::WrapUnique(
+ new LocationArbitratorImpl(callback, delegate_.get()));
}
} // namespace content
diff --git a/chromium/content/browser/geolocation/geolocation_provider_impl.h b/chromium/content/browser/geolocation/geolocation_provider_impl.h
index b7c7e9dcbc9..3a6e77950ef 100644
--- a/chromium/content/browser/geolocation/geolocation_provider_impl.h
+++ b/chromium/content/browser/geolocation/geolocation_provider_impl.h
@@ -22,6 +22,7 @@ template<typename Type> struct DefaultSingletonTraits;
}
namespace content {
+class GeolocationDelegate;
class LocationArbitrator;
class CONTENT_EXPORT GeolocationProviderImpl
@@ -91,6 +92,9 @@ class CONTENT_EXPORT GeolocationProviderImpl
// True only in testing, where we want to use a custom position.
bool ignore_location_updates_;
+ // The system provided Delegate for the |arbitrator_|.
+ std::unique_ptr<GeolocationDelegate> delegate_;
+
// Only to be used on the geolocation thread.
std::unique_ptr<LocationArbitrator> arbitrator_;
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.cc b/chromium/content/browser/geolocation/geolocation_service_impl.cc
index 5424c141e58..e05dda47cdc 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl.cc
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.cc
@@ -122,7 +122,7 @@ void GeolocationServiceImpl::SetHighAccuracy(bool high_accuracy) {
}
void GeolocationServiceImpl::QueryNextPosition(
- const PositionCallback& callback) {
+ const QueryNextPositionCallback& callback) {
if (!position_callback_.is_null()) {
DVLOG(1) << "Overlapped call to QueryNextPosition!";
OnConnectionError(); // Simulate a connection error.
@@ -188,7 +188,7 @@ void GeolocationServiceImpl::OnLocationUpdate(const Geoposition& position) {
void GeolocationServiceImpl::ReportCurrentPosition() {
position_callback_.Run(current_position_.Clone());
- position_callback_.reset();
+ position_callback_.Reset();
has_position_to_report_ = false;
}
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.h b/chromium/content/browser/geolocation/geolocation_service_impl.h
index df37f882217..9265db3bd72 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl.h
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.h
@@ -41,11 +41,9 @@ class GeolocationServiceImpl : public blink::mojom::GeolocationService {
void ClearOverride();
private:
- typedef mojo::Callback<void(blink::mojom::GeopositionPtr)> PositionCallback;
-
// blink::mojom::GeolocationService:
void SetHighAccuracy(bool high_accuracy) override;
- void QueryNextPosition(const PositionCallback& callback) override;
+ void QueryNextPosition(const QueryNextPositionCallback& callback) override;
void OnConnectionError();
@@ -64,7 +62,7 @@ class GeolocationServiceImpl : public blink::mojom::GeolocationService {
base::Closure update_callback_;
// The callback passed to QueryNextPosition.
- PositionCallback position_callback_;
+ QueryNextPositionCallback position_callback_;
// Valid iff SetOverride() has been called and ClearOverride() has not
// subsequently been called.
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.cc b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
index d6cb78b1657..372951ef51f 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
@@ -8,10 +8,11 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "content/browser/geolocation/network_location_provider.h"
#include "content/public/browser/access_token_store.h"
-#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/geolocation_delegate.h"
#include "content/public/common/content_client.h"
#include "url/gurl.h"
@@ -28,15 +29,16 @@ const int64_t LocationArbitratorImpl::kFixStaleTimeoutMilliseconds =
11 * base::Time::kMillisecondsPerSecond;
LocationArbitratorImpl::LocationArbitratorImpl(
- const LocationUpdateCallback& callback)
- : arbitrator_update_callback_(callback),
+ const LocationUpdateCallback& callback,
+ GeolocationDelegate* delegate)
+ : delegate_(delegate),
+ arbitrator_update_callback_(callback),
provider_update_callback_(
base::Bind(&LocationArbitratorImpl::OnLocationUpdate,
base::Unretained(this))),
position_provider_(NULL),
is_permission_granted_(false),
- is_running_(false) {
-}
+ is_running_(false) {}
LocationArbitratorImpl::~LocationArbitratorImpl() {
}
@@ -52,31 +54,35 @@ void LocationArbitratorImpl::OnPermissionGranted() {
}
void LocationArbitratorImpl::StartProviders(bool enable_high_accuracy) {
- // GetAccessTokenStore() will return NULL for embedders not implementing
- // the AccessTokenStore class, so we report an error to avoid JavaScript
- // requests of location to wait eternally for a reply.
- AccessTokenStore* access_token_store = GetAccessTokenStore();
- if (!access_token_store) {
- Geoposition position;
- position.error_code = Geoposition::ERROR_CODE_PERMISSION_DENIED;
- arbitrator_update_callback_.Run(position);
- return;
- }
-
// Stash options as OnAccessTokenStoresLoaded has not yet been called.
is_running_ = true;
enable_high_accuracy_ = enable_high_accuracy;
+
if (providers_.empty()) {
- DCHECK(DefaultNetworkProviderURL().is_valid());
- access_token_store->LoadAccessTokens(
- base::Bind(&LocationArbitratorImpl::OnAccessTokenStoresLoaded,
- base::Unretained(this)));
- } else {
- DoStartProviders();
+ RegisterSystemProvider();
+
+ AccessTokenStore* access_token_store = GetAccessTokenStore();
+ if (access_token_store && delegate_->UseNetworkLocationProviders()) {
+ DCHECK(DefaultNetworkProviderURL().is_valid());
+ token_store_callback_.Reset(
+ base::Bind(&LocationArbitratorImpl::OnAccessTokenStoresLoaded,
+ base::Unretained(this)));
+ access_token_store->LoadAccessTokens(token_store_callback_.callback());
+ return;
+ }
}
+ DoStartProviders();
}
void LocationArbitratorImpl::DoStartProviders() {
+ if (providers_.empty()) {
+ // If no providers are available, we report an error to avoid
+ // callers waiting indefinitely for a reply.
+ Geoposition position;
+ position.error_code = Geoposition::ERROR_CODE_PERMISSION_DENIED;
+ arbitrator_update_callback_.Run(position);
+ return;
+ }
for (const auto& provider : providers_)
provider->StartProvider(enable_high_accuracy_);
}
@@ -95,11 +101,6 @@ void LocationArbitratorImpl::StopProviders() {
void LocationArbitratorImpl::OnAccessTokenStoresLoaded(
AccessTokenStore::AccessTokenMap access_token_map,
net::URLRequestContextGetter* context_getter) {
- if (!is_running_ || !providers_.empty()) {
- // A second StartProviders() call may have arrived before the first
- // completed.
- return;
- }
// If there are no access tokens, boot strap it with the default server URL.
if (access_token_map.empty())
access_token_map[DefaultNetworkProviderURL()];
@@ -107,23 +108,25 @@ void LocationArbitratorImpl::OnAccessTokenStoresLoaded(
RegisterProvider(NewNetworkLocationProvider(
GetAccessTokenStore(), context_getter, entry.first, entry.second));
}
-
- LocationProvider* provider =
- GetContentClient()->browser()->OverrideSystemLocationProvider();
- if (!provider)
- provider = NewSystemLocationProvider();
- RegisterProvider(provider);
DoStartProviders();
}
void LocationArbitratorImpl::RegisterProvider(
- LocationProvider* provider) {
+ std::unique_ptr<LocationProvider> provider) {
if (!provider)
return;
provider->SetUpdateCallback(provider_update_callback_);
if (is_permission_granted_)
provider->OnPermissionGranted();
- providers_.push_back(provider);
+ providers_.push_back(std::move(provider));
+}
+
+void LocationArbitratorImpl::RegisterSystemProvider() {
+ std::unique_ptr<LocationProvider> provider =
+ base::WrapUnique(delegate_->OverrideSystemLocationProvider());
+ if (!provider)
+ provider = NewSystemLocationProvider();
+ RegisterProvider(std::move(provider));
}
void LocationArbitratorImpl::OnLocationUpdate(const LocationProvider* provider,
@@ -139,7 +142,7 @@ void LocationArbitratorImpl::OnLocationUpdate(const LocationProvider* provider,
}
AccessTokenStore* LocationArbitratorImpl::NewAccessTokenStore() {
- return GetContentClient()->browser()->CreateAccessTokenStore();
+ return delegate_->CreateAccessTokenStore();
}
AccessTokenStore* LocationArbitratorImpl::GetAccessTokenStore() {
@@ -148,7 +151,8 @@ AccessTokenStore* LocationArbitratorImpl::GetAccessTokenStore() {
return access_token_store_.get();
}
-LocationProvider* LocationArbitratorImpl::NewNetworkLocationProvider(
+std::unique_ptr<LocationProvider>
+LocationArbitratorImpl::NewNetworkLocationProvider(
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
@@ -157,16 +161,17 @@ LocationProvider* LocationArbitratorImpl::NewNetworkLocationProvider(
// Android uses its own SystemLocationProvider.
return NULL;
#else
- return new NetworkLocationProvider(access_token_store, context, url,
- access_token);
+ return base::WrapUnique(new NetworkLocationProvider(
+ access_token_store, context, url, access_token));
#endif
}
-LocationProvider* LocationArbitratorImpl::NewSystemLocationProvider() {
+std::unique_ptr<LocationProvider>
+LocationArbitratorImpl::NewSystemLocationProvider() {
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
return NULL;
#else
- return content::NewSystemLocationProvider();
+ return base::WrapUnique(content::NewSystemLocationProvider());
#endif
}
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.h b/chromium/content/browser/geolocation/location_arbitrator_impl.h
index 60c9ac57a90..c2cbf23e78f 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.h
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.h
@@ -6,8 +6,10 @@
#define CONTENT_BROWSER_GEOLOCATION_LOCATION_ARBITRATOR_IMPL_H_
#include <stdint.h>
+#include <vector>
#include "base/callback_forward.h"
+#include "base/cancelable_callback.h"
#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "base/strings/string16.h"
@@ -15,6 +17,7 @@
#include "content/browser/geolocation/location_arbitrator.h"
#include "content/common/content_export.h"
#include "content/public/browser/access_token_store.h"
+#include "content/public/browser/geolocation_provider.h"
#include "content/public/browser/location_provider.h"
#include "content/public/common/geoposition.h"
#include "net/url_request/url_request_context_getter.h"
@@ -25,6 +28,7 @@ class URLRequestContextGetter;
namespace content {
class AccessTokenStore;
+class GeolocationDelegate;
class LocationProvider;
// This class is responsible for handling updates from multiple underlying
@@ -39,7 +43,8 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
typedef base::Callback<void(const Geoposition&)> LocationUpdateCallback;
- explicit LocationArbitratorImpl(const LocationUpdateCallback& callback);
+ LocationArbitratorImpl(const LocationUpdateCallback& callback,
+ GeolocationDelegate* delegate);
~LocationArbitratorImpl() override;
static GURL DefaultNetworkProviderURL();
@@ -56,18 +61,22 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
// These functions are useful for injection of dependencies in derived
// testing classes.
virtual AccessTokenStore* NewAccessTokenStore();
- virtual LocationProvider* NewNetworkLocationProvider(
+ virtual std::unique_ptr<LocationProvider> NewNetworkLocationProvider(
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
const base::string16& access_token);
- virtual LocationProvider* NewSystemLocationProvider();
+ virtual std::unique_ptr<LocationProvider> NewSystemLocationProvider();
virtual base::Time GetTimeNow() const;
+ GeolocationDelegate* GetDelegateForTesting() { return delegate_; }
+
private:
- // Takes ownership of |provider| on entry; it will either be added to
- // |providers_| or deleted on error (e.g. it fails to start).
- void RegisterProvider(LocationProvider* provider);
+ // Provider will either be added to |providers_| or
+ // deleted on error (e.g. it fails to start).
+ void RegisterProvider(std::unique_ptr<LocationProvider> provider);
+
+ void RegisterSystemProvider();
void OnAccessTokenStoresLoaded(
AccessTokenStore::AccessTokenMap access_token_map,
net::URLRequestContextGetter* context_getter);
@@ -84,10 +93,18 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
const Geoposition& new_position,
bool from_same_provider) const;
+ GeolocationDelegate* delegate_;
+
scoped_refptr<AccessTokenStore> access_token_store_;
LocationUpdateCallback arbitrator_update_callback_;
LocationProvider::LocationProviderUpdateCallback provider_update_callback_;
- ScopedVector<LocationProvider> providers_;
+
+ // The CancelableCallback will prevent OnAccessTokenStoresLoaded from being
+ // called multiple times by calling Reset() at the time of binding.
+ base::CancelableCallback<void(AccessTokenStore::AccessTokenMap,
+ net::URLRequestContextGetter*)>
+ token_store_callback_;
+ std::vector<std::unique_ptr<LocationProvider>> providers_;
bool enable_high_accuracy_;
// The provider which supplied the current |position_|
const LocationProvider* position_provider_;
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
index 93b1645b65a..706f28a5b08 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
@@ -7,9 +7,12 @@
#include <memory>
#include "base/bind.h"
+#include "base/memory/ptr_util.h"
#include "content/browser/geolocation/fake_access_token_store.h"
#include "content/browser/geolocation/mock_location_provider.h"
+#include "content/public/browser/geolocation_delegate.h"
#include "content/public/common/geoposition.h"
+#include "content/test/test_content_browser_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -64,16 +67,42 @@ void SetReferencePosition(MockLocationProvider* provider) {
namespace {
+class FakeGeolocationDelegate : public GeolocationDelegate {
+ public:
+ FakeGeolocationDelegate() = default;
+
+ bool UseNetworkLocationProviders() override { return use_network_; }
+ void set_use_network(bool use_network) { use_network_ = use_network; }
+
+ LocationProvider* OverrideSystemLocationProvider() override {
+ if (!system_location_provider_)
+ system_location_provider_ = base::WrapUnique(new MockLocationProvider);
+ return system_location_provider_.get();
+ }
+
+ LocationProvider* system_location_provider() const {
+ return system_location_provider_.get();
+ }
+
+ private:
+ bool use_network_ = true;
+ std::unique_ptr<LocationProvider> system_location_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeGeolocationDelegate);
+};
+
class TestingLocationArbitrator : public LocationArbitratorImpl {
public:
TestingLocationArbitrator(
const LocationArbitratorImpl::LocationUpdateCallback& callback,
- AccessTokenStore* access_token_store)
- : LocationArbitratorImpl(callback),
- cell_(NULL),
- gps_(NULL),
- access_token_store_(access_token_store) {
- }
+ AccessTokenStore* access_token_store,
+ GeolocationDelegate* delegate,
+ bool is_fake_delegate)
+ : LocationArbitratorImpl(callback, delegate),
+ is_fake_delegate_(is_fake_delegate),
+ cell_(nullptr),
+ gps_(nullptr),
+ access_token_store_(access_token_store) {}
base::Time GetTimeNow() const override { return GetTimeNowForTest(); }
@@ -81,22 +110,40 @@ class TestingLocationArbitrator : public LocationArbitratorImpl {
return access_token_store_.get();
}
- LocationProvider* NewNetworkLocationProvider(
+ std::unique_ptr<LocationProvider> NewNetworkLocationProvider(
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
const base::string16& access_token) override {
- return new MockLocationProvider(&cell_);
+ cell_ = new MockLocationProvider;
+ return base::WrapUnique(cell_);
+ }
+
+ std::unique_ptr<LocationProvider> NewSystemLocationProvider() override {
+ gps_ = new MockLocationProvider;
+ return base::WrapUnique(gps_);
}
- LocationProvider* NewSystemLocationProvider() override {
- return new MockLocationProvider(&gps_);
+ FakeGeolocationDelegate* GetFakeGeolocationDelegate() {
+ DCHECK(is_fake_delegate_);
+ return static_cast<FakeGeolocationDelegate*>(GetDelegateForTesting());
}
+ LocationProvider* GetLocationProvider() {
+ if (is_fake_delegate_)
+ return GetFakeGeolocationDelegate()->system_location_provider();
+ return GetDelegateForTesting()->OverrideSystemLocationProvider();
+ }
+
+ const bool is_fake_delegate_;
+
// Two location providers, with nice short names to make the tests more
// readable. Note |gps_| will only be set when there is a high accuracy
// observer registered (and |cell_| when there's at least one observer of any
// type).
+
+ // TODO(mvanouwerkerk): rename |cell_| to |network_location_provider_| and
+ // |gps_| to |system_location_provider_|
MockLocationProvider* cell_;
MockLocationProvider* gps_;
scoped_refptr<AccessTokenStore> access_token_store_;
@@ -110,11 +157,20 @@ class GeolocationLocationArbitratorTest : public testing::Test {
void SetUp() override {
access_token_store_ = new NiceMock<FakeAccessTokenStore>;
observer_.reset(new MockLocationObserver);
- LocationArbitratorImpl::LocationUpdateCallback callback =
+ }
+
+ // There are two types of test cases: those using FakeGeolocationDelegate and
+ // the ones exercising whatever the embedder provides. Test cases call this
+ // method to choose the appropriate one.
+ void InitializeArbitrator(bool use_fake_delegate) {
+ delegate_.reset(use_fake_delegate ? new FakeGeolocationDelegate()
+ : new GeolocationDelegate);
+ const LocationArbitratorImpl::LocationUpdateCallback callback =
base::Bind(&MockLocationObserver::OnLocationUpdate,
base::Unretained(observer_.get()));
- arbitrator_.reset(new TestingLocationArbitrator(
- callback, access_token_store_.get()));
+ arbitrator_.reset(
+ new TestingLocationArbitrator(callback, access_token_store_.get(),
+ delegate_.get(), use_fake_delegate));
}
// testing::Test
@@ -144,20 +200,28 @@ class GeolocationLocationArbitratorTest : public testing::Test {
return arbitrator_->gps_;
}
+ MockLocationProvider* GetSystemLocationProviderOverride() {
+ return static_cast<MockLocationProvider*>(
+ arbitrator_->GetLocationProvider());
+ }
+
scoped_refptr<FakeAccessTokenStore> access_token_store_;
std::unique_ptr<MockLocationObserver> observer_;
std::unique_ptr<TestingLocationArbitrator> arbitrator_;
+ std::unique_ptr<GeolocationDelegate> delegate_;
base::MessageLoop loop_;
};
TEST_F(GeolocationLocationArbitratorTest, CreateDestroy) {
EXPECT_TRUE(access_token_store_.get());
- EXPECT_TRUE(arbitrator_ != NULL);
+ InitializeArbitrator(true /* use_fake_delegate */);
+ EXPECT_TRUE(arbitrator_);
arbitrator_.reset();
SUCCEED();
}
TEST_F(GeolocationLocationArbitratorTest, OnPermissionGranted) {
+ InitializeArbitrator(false /* use_fake_delegate */);
EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted());
arbitrator_->OnPermissionGranted();
EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted());
@@ -165,22 +229,25 @@ TEST_F(GeolocationLocationArbitratorTest, OnPermissionGranted) {
// motions to create the provider (see next test).
EXPECT_FALSE(cell());
EXPECT_FALSE(gps());
+ EXPECT_FALSE(GetSystemLocationProviderOverride());
}
TEST_F(GeolocationLocationArbitratorTest, NormalUsage) {
+ InitializeArbitrator(false /* use_fake_delegate */);
ASSERT_TRUE(access_token_store_.get());
- ASSERT_TRUE(arbitrator_ != NULL);
+ ASSERT_TRUE(arbitrator_);
EXPECT_FALSE(cell());
EXPECT_FALSE(gps());
+ EXPECT_FALSE(GetSystemLocationProviderOverride());
arbitrator_->StartProviders(false);
EXPECT_TRUE(access_token_store_->access_token_map_.empty());
- EXPECT_TRUE(access_token_store_->access_token_map_.empty());
access_token_store_->NotifyDelegateTokensLoaded();
ASSERT_TRUE(cell());
EXPECT_TRUE(gps());
+ EXPECT_FALSE(GetSystemLocationProviderOverride());
EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_);
EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_);
EXPECT_FALSE(observer_->last_position_.Validate());
@@ -202,11 +269,82 @@ TEST_F(GeolocationLocationArbitratorTest, NormalUsage) {
EXPECT_TRUE(cell()->is_permission_granted_);
}
+TEST_F(GeolocationLocationArbitratorTest, CustomSystemProviderOnly) {
+ InitializeArbitrator(true /* use_fake_delegate */);
+ arbitrator_->GetFakeGeolocationDelegate()->set_use_network(false);
+ ASSERT_TRUE(arbitrator_);
+
+ EXPECT_FALSE(cell());
+ EXPECT_FALSE(gps());
+ arbitrator_->StartProviders(false);
+
+ ASSERT_FALSE(cell());
+ EXPECT_FALSE(gps());
+ ASSERT_TRUE(GetSystemLocationProviderOverride());
+ EXPECT_EQ(MockLocationProvider::LOW_ACCURACY,
+ GetSystemLocationProviderOverride()->state_);
+ EXPECT_FALSE(observer_->last_position_.Validate());
+ EXPECT_EQ(Geoposition::ERROR_CODE_NONE, observer_->last_position_.error_code);
+
+ SetReferencePosition(GetSystemLocationProviderOverride());
+
+ EXPECT_TRUE(observer_->last_position_.Validate() ||
+ observer_->last_position_.error_code !=
+ Geoposition::ERROR_CODE_NONE);
+ EXPECT_EQ(GetSystemLocationProviderOverride()->position_.latitude,
+ observer_->last_position_.latitude);
+
+ EXPECT_FALSE(GetSystemLocationProviderOverride()->is_permission_granted_);
+ EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted());
+ arbitrator_->OnPermissionGranted();
+ EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted());
+ EXPECT_TRUE(GetSystemLocationProviderOverride()->is_permission_granted_);
+}
+
+TEST_F(GeolocationLocationArbitratorTest,
+ CustomSystemAndDefaultNetworkProviders) {
+ InitializeArbitrator(true /* use_fake_delegate */);
+ arbitrator_->GetFakeGeolocationDelegate()->set_use_network(true);
+ ASSERT_TRUE(arbitrator_);
+
+ EXPECT_FALSE(cell());
+ EXPECT_FALSE(gps());
+ arbitrator_->StartProviders(false);
+
+ EXPECT_TRUE(access_token_store_->access_token_map_.empty());
+
+ access_token_store_->NotifyDelegateTokensLoaded();
+
+ ASSERT_TRUE(cell());
+ EXPECT_FALSE(gps());
+ ASSERT_TRUE(GetSystemLocationProviderOverride());
+ EXPECT_EQ(MockLocationProvider::LOW_ACCURACY,
+ GetSystemLocationProviderOverride()->state_);
+ EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_);
+ EXPECT_FALSE(observer_->last_position_.Validate());
+ EXPECT_EQ(Geoposition::ERROR_CODE_NONE, observer_->last_position_.error_code);
+
+ SetReferencePosition(cell());
+
+ EXPECT_TRUE(observer_->last_position_.Validate() ||
+ observer_->last_position_.error_code !=
+ Geoposition::ERROR_CODE_NONE);
+ EXPECT_EQ(cell()->position_.latitude, observer_->last_position_.latitude);
+
+ EXPECT_FALSE(cell()->is_permission_granted_);
+ EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted());
+ arbitrator_->OnPermissionGranted();
+ EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted());
+ EXPECT_TRUE(cell()->is_permission_granted_);
+}
+
TEST_F(GeolocationLocationArbitratorTest, SetObserverOptions) {
+ InitializeArbitrator(false /* use_fake_delegate */);
arbitrator_->StartProviders(false);
access_token_store_->NotifyDelegateTokensLoaded();
ASSERT_TRUE(cell());
ASSERT_TRUE(gps());
+ EXPECT_FALSE(GetSystemLocationProviderOverride());
EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_);
EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_);
SetReferencePosition(cell());
@@ -215,13 +353,16 @@ TEST_F(GeolocationLocationArbitratorTest, SetObserverOptions) {
arbitrator_->StartProviders(true);
EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, cell()->state_);
EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, gps()->state_);
+ EXPECT_FALSE(GetSystemLocationProviderOverride());
}
TEST_F(GeolocationLocationArbitratorTest, Arbitration) {
+ InitializeArbitrator(false /* use_fake_delegate */);
arbitrator_->StartProviders(false);
access_token_store_->NotifyDelegateTokensLoaded();
ASSERT_TRUE(cell());
ASSERT_TRUE(gps());
+ EXPECT_FALSE(GetSystemLocationProviderOverride());
SetPositionFix(cell(), 1, 2, 150);
@@ -294,10 +435,12 @@ TEST_F(GeolocationLocationArbitratorTest, Arbitration) {
}
TEST_F(GeolocationLocationArbitratorTest, TwoOneShotsIsNewPositionBetter) {
+ InitializeArbitrator(false /* use_fake_delegate */);
arbitrator_->StartProviders(false);
access_token_store_->NotifyDelegateTokensLoaded();
ASSERT_TRUE(cell());
ASSERT_TRUE(gps());
+ EXPECT_FALSE(GetSystemLocationProviderOverride());
// Set the initial position.
SetPositionFix(cell(), 3, 139, 100);
@@ -308,9 +451,8 @@ TEST_F(GeolocationLocationArbitratorTest, TwoOneShotsIsNewPositionBetter) {
// To test 240956, perform a throwaway alloc.
// This convinces the allocator to put the providers in a new memory location.
- MockLocationProvider* fakeMockProvider = NULL;
- LocationProvider* fakeProvider =
- new MockLocationProvider(&fakeMockProvider);
+ std::unique_ptr<MockLocationProvider> dummy_provider(
+ new MockLocationProvider);
arbitrator_->StartProviders(false);
access_token_store_->NotifyDelegateTokensLoaded();
@@ -321,9 +463,6 @@ TEST_F(GeolocationLocationArbitratorTest, TwoOneShotsIsNewPositionBetter) {
// Update with a less accurate position to verify 240956.
SetPositionFix(cell(), 3, 139, 150);
CheckLastPositionInfo(3, 139, 150);
-
- // No delete required for fakeMockProvider. It points to fakeProvider.
- delete fakeProvider;
}
} // namespace content
diff --git a/chromium/content/browser/geolocation/mock_location_provider.cc b/chromium/content/browser/geolocation/mock_location_provider.cc
index f289a1e6871..55b79a6b352 100644
--- a/chromium/content/browser/geolocation/mock_location_provider.cc
+++ b/chromium/content/browser/geolocation/mock_location_provider.cc
@@ -16,22 +16,13 @@
#include "base/threading/thread_task_runner_handle.h"
namespace content {
-MockLocationProvider* MockLocationProvider::instance_ = NULL;
-MockLocationProvider::MockLocationProvider(MockLocationProvider** self_ref)
+MockLocationProvider::MockLocationProvider()
: state_(STOPPED),
is_permission_granted_(false),
- self_ref_(self_ref),
- provider_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
- CHECK(self_ref_);
- CHECK(*self_ref_ == NULL);
- *self_ref_ = this;
-}
+ provider_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
-MockLocationProvider::~MockLocationProvider() {
- CHECK(*self_ref_ == this);
- *self_ref_ = NULL;
-}
+MockLocationProvider::~MockLocationProvider() {}
void MockLocationProvider::HandlePositionChanged(const Geoposition& position) {
if (provider_task_runner_->BelongsToCurrentThread()) {
@@ -70,9 +61,7 @@ class AutoMockLocationProvider : public MockLocationProvider {
public:
AutoMockLocationProvider(bool has_valid_location,
bool requires_permission_to_start)
- : MockLocationProvider(&instance_),
- weak_factory_(this),
- requires_permission_to_start_(requires_permission_to_start),
+ : requires_permission_to_start_(requires_permission_to_start),
listeners_updated_(false) {
if (has_valid_location) {
position_.accuracy = 3;
@@ -105,17 +94,19 @@ class AutoMockLocationProvider : public MockLocationProvider {
listeners_updated_ = true;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&MockLocationProvider::HandlePositionChanged,
- weak_factory_.GetWeakPtr(), position_));
+ base::Unretained(this), position_));
}
}
- base::WeakPtrFactory<MockLocationProvider> weak_factory_;
+ private:
const bool requires_permission_to_start_;
bool listeners_updated_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutoMockLocationProvider);
};
LocationProvider* NewMockLocationProvider() {
- return new MockLocationProvider(&MockLocationProvider::instance_);
+ return new MockLocationProvider;
}
LocationProvider* NewAutoSuccessMockLocationProvider() {
diff --git a/chromium/content/browser/geolocation/mock_location_provider.h b/chromium/content/browser/geolocation/mock_location_provider.h
index ec1a9777313..7c3372e2919 100644
--- a/chromium/content/browser/geolocation/mock_location_provider.h
+++ b/chromium/content/browser/geolocation/mock_location_provider.h
@@ -19,9 +19,9 @@ namespace content {
// Mock implementation of a location provider for testing.
class MockLocationProvider : public LocationProviderBase {
public:
- // Will update |*self_ref| to point to |this| on construction, and to NULL
- // on destruction.
- explicit MockLocationProvider(MockLocationProvider** self_ref);
+ enum State { STOPPED, LOW_ACCURACY, HIGH_ACCURACY } state_;
+
+ MockLocationProvider();
~MockLocationProvider() override;
// Updates listeners with the new position.
@@ -33,16 +33,11 @@ class MockLocationProvider : public LocationProviderBase {
void GetPosition(Geoposition* position) override;
void OnPermissionGranted() override;
- Geoposition position_;
- enum State { STOPPED, LOW_ACCURACY, HIGH_ACCURACY } state_;
bool is_permission_granted_;
- MockLocationProvider** self_ref_;
-
+ Geoposition position_;
scoped_refptr<base::SingleThreadTaskRunner> provider_task_runner_;
- // Set when an instance of the mock is created via a factory function.
- static MockLocationProvider* instance_;
-
+ private:
DISALLOW_COPY_AND_ASSIGN(MockLocationProvider);
};
diff --git a/chromium/content/browser/geolocation/network_location_provider_unittest.cc b/chromium/content/browser/geolocation/network_location_provider_unittest.cc
index ebbf582160a..68973fffbad 100644
--- a/chromium/content/browser/geolocation/network_location_provider_unittest.cc
+++ b/chromium/content/browser/geolocation/network_location_provider_unittest.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <memory>
+#include <utility>
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
@@ -175,13 +176,13 @@ class GeolocationNetworkProviderTest : public testing::Test {
int ap_count, int start_index, base::ListValue* wifi_access_point_list) {
std::vector<std::string> wifi_data;
for (int i = 0; i < ap_count; ++i) {
- base::DictionaryValue* ap = new base::DictionaryValue();
+ std::unique_ptr<base::DictionaryValue> ap(new base::DictionaryValue());
ap->SetString("macAddress", base::StringPrintf("%02d-34-56-78-54-32", i));
ap->SetInteger("signalStrength", start_index + ap_count - i);
ap->SetInteger("age", 0);
ap->SetInteger("channel", IndexToChannel(i));
ap->SetInteger("signalToNoiseRatio", i + 42);
- wifi_access_point_list->Append(ap);
+ wifi_access_point_list->Append(std::move(ap));
}
}
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 a7687ee30fa..aff2083e6de 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -95,15 +95,15 @@ BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest(
int gpu_client_id,
uint64_t gpu_client_tracing_id,
int gpu_host_id)
- : event_(false, false),
+ : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
cause_for_gpu_launch_(cause),
gpu_client_id_(gpu_client_id),
gpu_client_tracing_id_(gpu_client_tracing_id),
gpu_host_id_(gpu_host_id),
reused_gpu_process_(false),
finished_(false),
- main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
-}
+ main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() {
// TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
@@ -226,7 +226,9 @@ void BrowserGpuChannelHostFactory::Terminate() {
BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
: gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
gpu_client_tracing_id_(ChildProcessHost::kBrowserTracingProcessId),
- shutdown_event_(new base::WaitableEvent(true, false)),
+ shutdown_event_(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED)),
gpu_memory_buffer_manager_(
new BrowserGpuMemoryBufferManager(gpu_client_id_,
gpu_client_tracing_id_)),
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 3d6c3d465bf..a8acccd1838 100644
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -42,19 +42,6 @@ void HostCreateGpuMemoryBuffer(
surface_handle, callback);
}
-void HostCreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- GpuProcessHost* host,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- const BrowserGpuMemoryBufferManager::CreateCallback& callback) {
- host->CreateGpuMemoryBufferFromHandle(handle, id, size, format, client_id,
- callback);
-}
-
void GpuMemoryBufferDeleted(
scoped_refptr<base::SingleThreadTaskRunner> destruction_task_runner,
const gpu::GpuMemoryBufferImpl::DestructionCallback& destruction_callback,
@@ -84,13 +71,10 @@ GpuMemoryBufferConfigurationSet GetNativeGpuMemoryBufferConfigurations() {
if (BrowserGpuMemoryBufferManager::IsNativeGpuMemoryBuffersEnabled()) {
const gfx::BufferFormat kNativeFormats[] = {
- gfx::BufferFormat::R_8,
- gfx::BufferFormat::BGR_565,
- gfx::BufferFormat::RGBA_4444,
- gfx::BufferFormat::RGBA_8888,
- gfx::BufferFormat::BGRA_8888,
- gfx::BufferFormat::UYVY_422,
- gfx::BufferFormat::YUV_420_BIPLANAR};
+ gfx::BufferFormat::R_8, gfx::BufferFormat::BGR_565,
+ gfx::BufferFormat::RGBA_4444, gfx::BufferFormat::RGBA_8888,
+ gfx::BufferFormat::BGRA_8888, gfx::BufferFormat::UYVY_422,
+ gfx::BufferFormat::YVU_420, gfx::BufferFormat::YUV_420_BIPLANAR};
const gfx::BufferUsage kNativeUsages[] = {
gfx::BufferUsage::GPU_READ, gfx::BufferUsage::SCANOUT,
gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
@@ -107,16 +91,16 @@ GpuMemoryBufferConfigurationSet GetNativeGpuMemoryBufferConfigurations() {
// Disable native buffers only when using Mesa.
bool force_native_gpu_read_write_formats =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kUseGL) != gfx::kGLImplementationOSMesaName;
+ switches::kUseGL) != gl::kGLImplementationOSMesaName;
#else
bool force_native_gpu_read_write_formats = false;
#endif
if (force_native_gpu_read_write_formats) {
const gfx::BufferFormat kGPUReadWriteFormats[] = {
- gfx::BufferFormat::BGR_565, gfx::BufferFormat::RGBA_8888,
- gfx::BufferFormat::RGBX_8888, gfx::BufferFormat::BGRA_8888,
- gfx::BufferFormat::BGRX_8888, gfx::BufferFormat::UYVY_422,
- gfx::BufferFormat::YUV_420_BIPLANAR};
+ gfx::BufferFormat::BGR_565, gfx::BufferFormat::RGBA_8888,
+ gfx::BufferFormat::RGBX_8888, gfx::BufferFormat::BGRA_8888,
+ gfx::BufferFormat::BGRX_8888, gfx::BufferFormat::UYVY_422,
+ gfx::BufferFormat::YVU_420, gfx::BufferFormat::YUV_420_BIPLANAR};
const gfx::BufferUsage kGPUReadWriteUsages[] = {
gfx::BufferUsage::GPU_READ, gfx::BufferUsage::SCANOUT};
for (auto& format : kGPUReadWriteFormats) {
@@ -140,7 +124,8 @@ struct BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferRequest {
gfx::BufferUsage usage,
int client_id,
gpu::SurfaceHandle surface_handle)
- : event(true, false),
+ : event(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
size(size),
format(format),
usage(usage),
@@ -197,7 +182,7 @@ BrowserGpuMemoryBufferManager* BrowserGpuMemoryBufferManager::current() {
bool BrowserGpuMemoryBufferManager::IsNativeGpuMemoryBuffersEnabled() {
// Disable native buffers when using Mesa.
if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kUseGL) == gfx::kGLImplementationOSMesaName) {
+ switches::kUseGL) == gl::kGLImplementationOSMesaName) {
return false;
}
@@ -489,47 +474,18 @@ void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferFromHandleOnIO(
gfx::GpuMemoryBufferId new_id = content::GetNextGenericSharedMemoryId();
- // Use service side allocation for native types.
- if (request->handle.type != gfx::SHARED_MEMORY_BUFFER) {
- // Early out if service side allocation is not supported.
- if (request->handle.type != gpu::GetNativeGpuMemoryBufferType() ||
- !IsNativeGpuMemoryBufferConfiguration(request->format,
- request->usage)) {
- request->event.Signal();
- return;
- }
- // Note: Unretained is safe as this is only used for synchronous allocation
- // from a non-IO thread.
- CreateGpuMemoryBufferOnIO(
- base::Bind(&HostCreateGpuMemoryBufferFromHandle, request->handle),
- new_id, request->size, request->format, request->usage,
- request->client_id, false,
- base::Bind(
- &BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO,
- base::Unretained(this), base::Unretained(request)));
- return;
- }
-
- DCHECK(gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
- << static_cast<int>(request->usage);
-
BufferMap& buffers = clients_[request->client_id];
-
- // Allocate shared memory buffer.
auto insert_result = buffers.insert(std::make_pair(
- new_id, BufferInfo(request->size, gfx::SHARED_MEMORY_BUFFER,
+ new_id, BufferInfo(request->size, request->handle.type,
request->format, request->usage, 0)));
DCHECK(insert_result.second);
- gfx::GpuMemoryBufferHandle handle;
+ gfx::GpuMemoryBufferHandle handle = request->handle;
handle.id = new_id;
- handle.handle = request->handle.handle;
- handle.offset = request->handle.offset;
- handle.stride = request->handle.stride;
// Note: Unretained is safe as IO thread is stopped before manager is
// destroyed.
- request->result = gpu::GpuMemoryBufferImplSharedMemory::CreateFromHandle(
+ request->result = gpu::GpuMemoryBufferImpl::CreateFromHandle(
handle, request->size, request->format, request->usage,
base::Bind(
&GpuMemoryBufferDeleted,
@@ -728,4 +684,23 @@ uint64_t BrowserGpuMemoryBufferManager::ClientIdToTracingProcessId(
client_id);
}
+BrowserGpuMemoryBufferManager::BufferInfo::BufferInfo() = default;
+
+BrowserGpuMemoryBufferManager::BufferInfo::BufferInfo(
+ const gfx::Size& size,
+ gfx::GpuMemoryBufferType type,
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage,
+ int gpu_host_id)
+ : size(size),
+ type(type),
+ format(format),
+ usage(usage),
+ gpu_host_id(gpu_host_id) {}
+
+BrowserGpuMemoryBufferManager::BufferInfo::BufferInfo(const BufferInfo& other) =
+ default;
+
+BrowserGpuMemoryBufferManager::BufferInfo::~BufferInfo() {}
+
} // namespace content
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 f3f4fa33890..87166e22bab 100644
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
@@ -102,27 +102,20 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager
private:
struct BufferInfo {
- BufferInfo()
- : type(gfx::EMPTY_BUFFER),
- format(gfx::BufferFormat::RGBA_8888),
- usage(gfx::BufferUsage::GPU_READ),
- gpu_host_id(0) {}
+ BufferInfo();
BufferInfo(const gfx::Size& size,
gfx::GpuMemoryBufferType type,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- int gpu_host_id)
- : size(size),
- type(type),
- format(format),
- usage(usage),
- gpu_host_id(gpu_host_id) {}
+ int gpu_host_id);
+ BufferInfo(const BufferInfo& other);
+ ~BufferInfo();
gfx::Size size;
- gfx::GpuMemoryBufferType type;
- gfx::BufferFormat format;
- gfx::BufferUsage usage;
- int gpu_host_id;
+ gfx::GpuMemoryBufferType type = gfx::EMPTY_BUFFER;
+ gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888;
+ gfx::BufferUsage usage = gfx::BufferUsage::GPU_READ;
+ int gpu_host_id = 0;
};
struct CreateGpuMemoryBufferRequest;
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index 09018f7e4eb..0d45e84b8bf 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -6,6 +6,9 @@
#include <stddef.h>
+#include <memory>
+#include <utility>
+
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/logging.h"
@@ -380,7 +383,8 @@ base::Value* GetProblems() {
for (size_t i = 0; !eof; ++i) {
const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i, &eof);
if (gpu_feature_info.disabled) {
- base::DictionaryValue* problem = new base::DictionaryValue();
+ std::unique_ptr<base::DictionaryValue> problem(
+ new base::DictionaryValue());
problem->SetString(
"description", gpu_feature_info.disabled_description);
problem->Set("crBugs", new base::ListValue());
@@ -389,7 +393,7 @@ base::Value* GetProblems() {
disabled_features->AppendString(gpu_feature_info.name);
problem->Set("affectedGpuSettings", disabled_features);
problem->SetString("tag", "disabledFeatures");
- problem_list->Append(problem);
+ problem_list->Append(std::move(problem));
}
}
return problem_list;
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 e324279ca04..bd9e61b6a34 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,9 @@
#include "content/browser/gpu/gpu_data_manager_impl_private.h"
+#include <memory>
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
@@ -13,7 +16,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
-#include "base/sys_info.h"
#include "base/trace_event/trace_event.h"
#include "base/version.h"
#include "build/build_config.h"
@@ -50,7 +52,7 @@
#include "ui/gfx/android/device_display_info.h"
#endif // OS_ANDROID
#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
-#include "content/common/mojo/mojo_shell_connection_impl.h"
+#include "services/shell/runner/common/client_util.h"
#endif
namespace content {
@@ -72,6 +74,9 @@ enum WinSubVersion {
kWinVista,
kWin7,
kWin8,
+ kWin8_1,
+ kWin10,
+ kWin10_TH2,
kNumWinSubVersions
};
@@ -79,21 +84,28 @@ int GetGpuBlacklistHistogramValueWin(GpuFeatureStatus status) {
static WinSubVersion sub_version = kNumWinSubVersions;
if (sub_version == kNumWinSubVersions) {
sub_version = kWinOthers;
- std::string version_str = base::SysInfo::OperatingSystemVersion();
- size_t pos = version_str.find_first_not_of("0123456789.");
- if (pos != std::string::npos)
- version_str = version_str.substr(0, pos);
- Version os_version(version_str);
- if (os_version.IsValid() && os_version.components().size() >= 2) {
- const std::vector<uint32_t>& version_numbers = os_version.components();
- if (version_numbers[0] == 5)
- sub_version = kWinXP;
- else if (version_numbers[0] == 6 && version_numbers[1] == 0)
- sub_version = kWinVista;
- else if (version_numbers[0] == 6 && version_numbers[1] == 1)
+ switch (base::win::GetVersion()) {
+ case base::win::VERSION_PRE_XP:
+ case base::win::VERSION_XP:
+ case base::win::VERSION_SERVER_2003:
+ case base::win::VERSION_VISTA:
+ case base::win::VERSION_WIN_LAST:
+ break;
+ case base::win::VERSION_WIN7:
sub_version = kWin7;
- else if (version_numbers[0] == 6 && version_numbers[1] == 2)
+ break;
+ case base::win::VERSION_WIN8:
sub_version = kWin8;
+ break;
+ case base::win::VERSION_WIN8_1:
+ sub_version = kWin8_1;
+ break;
+ case base::win::VERSION_WIN10:
+ sub_version = kWin10;
+ break;
+ case base::win::VERSION_WIN10_TH2:
+ sub_version = kWin10_TH2;
+ break;
}
}
int entry_index = static_cast<int>(sub_version) * kGpuFeatureNumStatus;
@@ -258,7 +270,7 @@ enum BlockStatusHistogram {
bool ShouldDisableHardwareAcceleration() {
#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
// TODO(rjkroege): Remove this when https://crbug.com/602519 is fixed.
- if (IsRunningInMojoShell())
+ if (shell::ShellIsRemote())
return true;
#endif
return base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -515,8 +527,11 @@ void GpuDataManagerImplPrivate::Initialize() {
}
gpu::GPUInfo gpu_info;
- if (command_line->GetSwitchValueASCII(
- switches::kUseGL) == gfx::kGLImplementationOSMesaName) {
+ const bool force_osmesa =
+ (command_line->GetSwitchValueASCII(switches::kUseGL) ==
+ gl::kGLImplementationOSMesaName) ||
+ command_line->HasSwitch(switches::kOverrideUseGLWithOSMesaForTests);
+ if (force_osmesa) {
// If using the OSMesa GL implementation, use fake vendor and device ids to
// make sure it never gets blacklisted. This is better than simply
// cancelling GPUInfo gathering as it allows us to proceed with loading the
@@ -527,7 +542,11 @@ void GpuDataManagerImplPrivate::Initialize() {
// Also declare the driver_vendor to be osmesa to be able to specify
// exceptions based on driver_vendor==osmesa for some blacklist rules.
- gpu_info.driver_vendor = gfx::kGLImplementationOSMesaName;
+ gpu_info.driver_vendor = gl::kGLImplementationOSMesaName;
+
+ // We are not going to call CollectBasicGraphicsInfo.
+ // So mark it as collected.
+ gpu_info.basic_info_state = gpu::kCollectInfoSuccess;
} else {
TRACE_EVENT0("startup",
"GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
@@ -694,8 +713,8 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
IsFeatureBlacklisted(
gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) &&
(use_gl == "any")) {
- command_line->AppendSwitchASCII(
- switches::kUseGL, gfx::kGLImplementationOSMesaName);
+ command_line->AppendSwitchASCII(switches::kUseGL,
+ gl::kGLImplementationOSMesaName);
} else if (!use_gl.empty()) {
command_line->AppendSwitchASCII(switches::kUseGL, use_gl);
}
@@ -902,11 +921,11 @@ void GpuDataManagerImplPrivate::ProcessCrashed(
base::ListValue* GpuDataManagerImplPrivate::GetLogMessages() const {
base::ListValue* value = new base::ListValue;
for (size_t ii = 0; ii < log_messages_.size(); ++ii) {
- base::DictionaryValue* dict = new base::DictionaryValue();
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetInteger("level", log_messages_[ii].level);
dict->SetString("header", log_messages_[ii].header);
dict->SetString("message", log_messages_[ii].message);
- value->Append(dict);
+ value->Append(std::move(dict));
}
return value;
}
@@ -923,6 +942,16 @@ void GpuDataManagerImplPrivate::HandleGpuSwitch() {
bool GpuDataManagerImplPrivate::UpdateActiveGpu(uint32_t vendor_id,
uint32_t device_id) {
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+
+ // For tests, only the gpu process is allowed to detect the active gpu device
+ // using information on the actual loaded GL driver.
+ if (command_line->HasSwitch(switches::kGpuTestingVendorId) &&
+ command_line->HasSwitch(switches::kGpuTestingDeviceId)) {
+ return false;
+ }
+
if (gpu_info_.gpu.vendor_id == vendor_id &&
gpu_info_.gpu.device_id == device_id) {
// The primary GPU is active.
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index 8dc9358228b..731c4abbae5 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -276,8 +276,8 @@ const char* BufferFormatToString(gfx::BufferFormat format) {
return "BGRX_8888";
case gfx::BufferFormat::BGRA_8888:
return "BGRA_8888";
- case gfx::BufferFormat::YUV_420:
- return "YUV_420";
+ case gfx::BufferFormat::YVU_420:
+ return "YVU_420";
case gfx::BufferFormat::YUV_420_BIPLANAR:
return "YUV_420_BIPLANAR";
case gfx::BufferFormat::UYVY_422:
@@ -444,13 +444,12 @@ void GpuMessageHandler::OnCallAsync(const base::ListValue* args) {
// call BrowserBridge.onCallAsyncReply with result
if (ret) {
- web_ui()->CallJavascriptFunction("browserBridge.onCallAsyncReply",
- *requestId,
- *ret);
+ web_ui()->CallJavascriptFunctionUnsafe("browserBridge.onCallAsyncReply",
+ *requestId, *ret);
delete ret;
} else {
- web_ui()->CallJavascriptFunction("browserBridge.onCallAsyncReply",
- *requestId);
+ web_ui()->CallJavascriptFunctionUnsafe("browserBridge.onCallAsyncReply",
+ *requestId);
}
}
@@ -520,8 +519,8 @@ void GpuMessageHandler::OnGpuInfoUpdate() {
gpu_info_val->Set("gpuMemoryBufferInfo", GpuMemoryBufferInfo());
// Send GPU Info to javascript.
- web_ui()->CallJavascriptFunction("browserBridge.onGpuInfoUpdate",
- *(gpu_info_val.get()));
+ web_ui()->CallJavascriptFunctionUnsafe("browserBridge.onGpuInfoUpdate",
+ *(gpu_info_val.get()));
}
void GpuMessageHandler::OnGpuSwitched() {
diff --git a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
index 039febd685c..016e49169b5 100644
--- a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -40,9 +40,8 @@ scoped_refptr<content::ContextProviderCommandBuffer> CreateContext(
return make_scoped_refptr(new content::ContextProviderCommandBuffer(
std::move(gpu_channel_host), gpu::GPU_STREAM_DEFAULT,
gpu::GpuStreamPriority::NORMAL, gpu::kNullSurfaceHandle, GURL(),
- gfx::PreferIntegratedGpu, automatic_flushes, support_locking,
- gpu::SharedMemoryLimits(), attributes, nullptr,
- content::command_buffer_metrics::OFFSCREEN_CONTEXT_FOR_TESTING));
+ automatic_flushes, support_locking, gpu::SharedMemoryLimits(), attributes,
+ nullptr, content::command_buffer_metrics::OFFSCREEN_CONTEXT_FOR_TESTING));
}
class ContextTestBase : public content::ContentBrowserTest {
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index fd436ae8598..90078102647 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -6,6 +6,8 @@
#include <stddef.h>
+#include <algorithm>
+#include <list>
#include <utility>
#include "base/base64.h"
@@ -16,18 +18,22 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/metrics/histogram.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram_macros.h"
#include "base/sha1.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "components/tracing/tracing_switches.h"
+#include "components/tracing/common/tracing_switches.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/gpu/shader_disk_cache.h"
-#include "content/browser/mojo/mojo_application_host.h"
+#include "content/browser/mojo/constants.h"
+#include "content/browser/mojo/mojo_child_connection.h"
+#include "content/browser/mojo/mojo_shell_context.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/establish_channel_params.h"
@@ -43,6 +49,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/mojo_channel_switches.h"
+#include "content/public/common/mojo_shell_connection.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandbox_type.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
@@ -52,6 +59,10 @@
#include "ipc/ipc_switches.h"
#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/public/cpp/interface_registry.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/latency_info.h"
#include "ui/gl/gl_switches.h"
@@ -188,7 +199,7 @@ class GpuSandboxedProcessLauncherDelegate
#if defined(OS_WIN)
bool ShouldSandbox() override {
bool sandbox = !cmd_line_->HasSwitch(switches::kDisableGpuSandbox);
- if(! sandbox) {
+ if (!sandbox) {
DVLOG(1) << "GPU sandbox is disabled";
}
return sandbox;
@@ -205,7 +216,7 @@ class GpuSandboxedProcessLauncherDelegate
bool PreSpawnTarget(sandbox::TargetPolicy* policy) override {
if (base::win::GetVersion() > base::win::VERSION_XP) {
if (cmd_line_->GetSwitchValueASCII(switches::kUseGL) ==
- gfx::kGLImplementationDesktopName) {
+ gl::kGLImplementationDesktopName) {
// Open GL path.
policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
sandbox::USER_LIMITED);
@@ -407,7 +418,8 @@ GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind)
kind_(kind),
process_launched_(false),
initialized_(false),
- uma_memory_stats_received_(false) {
+ uma_memory_stats_received_(false),
+ child_token_(mojo::edk::GenerateRandomToken()) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSingleProcess) ||
base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -431,7 +443,8 @@ GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind)
FROM_HERE,
base::Bind(base::IgnoreResult(&GpuProcessHostUIShim::Create), host_id));
- process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_GPU, this));
+ process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_GPU, this,
+ child_token_));
}
GpuProcessHost::~GpuProcessHost() {
@@ -543,18 +556,22 @@ bool GpuProcessHost::Init() {
if (channel_id.empty())
return false;
- DCHECK(!mojo_application_host_);
- mojo_application_host_.reset(new MojoApplicationHost);
+ DCHECK(!mojo_child_connection_);
+ mojo_child_connection_.reset(new MojoChildConnection(
+ kGpuMojoApplicationName,
+ "",
+ child_token_,
+ MojoShellContext::GetConnectorForIOThread()));
gpu::GpuPreferences gpu_preferences = GetGpuPreferencesFromCommandLine();
if (in_process_) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(g_gpu_main_thread_factory);
- in_process_gpu_thread_.reset(
- g_gpu_main_thread_factory(InProcessChildThreadParams(
- channel_id, base::MessageLoop::current()->task_runner(),
- std::string(), mojo_application_host_->GetToken()),
- gpu_preferences));
+ in_process_gpu_thread_.reset(g_gpu_main_thread_factory(
+ InProcessChildThreadParams(
+ channel_id, base::ThreadTaskRunnerHandle::Get(), std::string(),
+ mojo_child_connection_->shell_client_token()),
+ gpu_preferences));
base::Thread::Options options;
#if defined(OS_WIN)
// WGL needs to create its own window and pump messages on it.
@@ -629,7 +646,7 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceCreatedChildWindow,
OnAcceleratedSurfaceCreatedChildWindow)
#endif
-
+ IPC_MESSAGE_HANDLER(GpuHostMsg_FieldTrialActivated, OnFieldTrialActivated);
IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message))
IPC_END_MESSAGE_MAP()
@@ -747,30 +764,6 @@ void GpuProcessHost::CreateGpuMemoryBuffer(
}
}
-void GpuProcessHost::CreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- int client_id,
- const CreateGpuMemoryBufferCallback& callback) {
- TRACE_EVENT0("gpu", "GpuProcessHost::CreateGpuMemoryBufferFromHandle");
-
- DCHECK(CalledOnValidThread());
-
- GpuMsg_CreateGpuMemoryBufferFromHandle_Params params;
- params.handle = handle;
- params.id = id;
- params.size = size;
- params.format = format;
- params.client_id = client_id;
- if (Send(new GpuMsg_CreateGpuMemoryBufferFromHandle(params))) {
- create_gpu_memory_buffer_requests_.push(callback);
- } else {
- callback.Run(gfx::GpuMemoryBufferHandle());
- }
-}
-
void GpuProcessHost::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
int client_id,
const gpu::SyncToken& sync_token) {
@@ -879,19 +872,25 @@ void GpuProcessHost::OnDidLoseContext(bool offscreen,
return;
}
- GpuDataManagerImpl::DomainGuilt guilt;
+ GpuDataManagerImpl::DomainGuilt guilt =
+ GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
switch (reason) {
case gpu::error::kGuilty:
guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
break;
+ // Treat most other error codes as though they had unknown provenance.
+ // In practice this doesn't affect the user experience. A lost context
+ // of either known or unknown guilt still causes user-level 3D APIs
+ // (e.g. WebGL) to be blocked on that domain until the user manually
+ // reenables them.
case gpu::error::kUnknown:
- guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
+ case gpu::error::kOutOfMemory:
+ case gpu::error::kMakeCurrentFailed:
+ case gpu::error::kGpuChannelLost:
+ case gpu::error::kInvalidGpuMessage:
break;
case gpu::error::kInnocent:
return;
- default:
- NOTREACHED();
- return;
}
GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(url, guilt);
@@ -908,6 +907,13 @@ void GpuProcessHost::OnGpuMemoryUmaStatsReceived(
uma_memory_stats_ = stats;
}
+void GpuProcessHost::OnFieldTrialActivated(const std::string& trial_name) {
+ // Activate the trial in the browser process to match its state in the
+ // GPU process. This is done by calling FindFullName which finalizes the group
+ // and activates the trial.
+ base::FieldTrialList::FindFullName(trial_name);
+}
+
void GpuProcessHost::OnProcessLaunched() {
UMA_HISTOGRAM_TIMES("GPU.GPUProcessLaunchTime",
base::TimeTicks::Now() - init_start_time_);
@@ -925,8 +931,12 @@ void GpuProcessHost::OnProcessCrashed(int exit_code) {
process_->GetTerminationStatus(true /* known_dead */, NULL));
}
-ServiceRegistry* GpuProcessHost::GetServiceRegistry() {
- return mojo_application_host_->service_registry();
+shell::InterfaceRegistry* GpuProcessHost::GetInterfaceRegistry() {
+ return mojo_child_connection_->connection()->GetInterfaceRegistry();
+}
+
+shell::InterfaceProvider* GpuProcessHost::GetRemoteInterfaces() {
+ return mojo_child_connection_->connection()->GetRemoteInterfaces();
}
GpuProcessHost::GpuProcessKind GpuProcessHost::kind() {
@@ -984,12 +994,11 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id,
cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
cmd_line->AppendSwitchASCII(switches::kMojoApplicationChannelToken,
- mojo_application_host_->GetToken());
+ mojo_child_connection_->shell_client_token());
BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(cmd_line);
#if defined(OS_WIN)
- if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument())
- cmd_line->AppendArg(switches::kPrefetchArgumentGpu);
+ cmd_line->AppendArg(switches::kPrefetchArgumentGpu);
#endif // defined(OS_WIN)
if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED)
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index 4ed7f2c7a43..ee9ce1ed7ca 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -49,7 +49,7 @@ namespace content {
class BrowserChildProcessHostImpl;
class GpuMainThread;
class InProcessChildThreadParams;
-class MojoApplicationHost;
+class MojoChildConnection;
class RenderWidgetHostViewFrameSubscriber;
class ShaderDiskCache;
@@ -106,7 +106,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
GpuMainThreadFactoryFunction create);
// BrowserChildProcessHostDelegate implementation.
- ServiceRegistry* GetServiceRegistry() override;
+ shell::InterfaceRegistry* GetInterfaceRegistry() override;
+ shell::InterfaceProvider* GetRemoteInterfaces() override;
// Get the GPU process host for the GPU process with the given ID. Returns
// null if the process no longer exists.
@@ -138,16 +139,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
gpu::SurfaceHandle surface_handle,
const CreateGpuMemoryBufferCallback& callback);
- // Tells the GPU process to create a new GPU memory buffer from an existing
- // handle.
- void CreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- int client_id,
- const CreateGpuMemoryBufferCallback& callback);
-
// Tells the GPU process to destroy GPU memory buffer.
void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
int client_id,
@@ -201,6 +192,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
const GURL& url);
void OnDidDestroyOffscreenContext(const GURL& url);
void OnGpuMemoryUmaStatsReceived(const gpu::GPUMemoryUmaStats& stats);
+ void OnFieldTrialActivated(const std::string& trial_name);
#if defined(OS_WIN)
void OnAcceleratedSurfaceCreatedChildWindow(
@@ -299,8 +291,9 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
std::string shader_prefix_key_;
// Browser-side Mojo endpoint which sets up a Mojo channel with the child
- // process and contains the browser's ServiceRegistry.
- std::unique_ptr<MojoApplicationHost> mojo_application_host_;
+ // process and contains the browser's InterfaceRegistry.
+ const std::string child_token_;
+ std::unique_ptr<MojoChildConnection> mojo_child_connection_;
DISALLOW_COPY_AND_ASSIGN(GpuProcessHost);
};
diff --git a/chromium/content/browser/gpu/gpu_surface_tracker.cc b/chromium/content/browser/gpu/gpu_surface_tracker.cc
index 03cae9507ae..d04a0e2f424 100644
--- a/chromium/content/browser/gpu/gpu_surface_tracker.cc
+++ b/chromium/content/browser/gpu/gpu_surface_tracker.cc
@@ -58,7 +58,7 @@ gfx::AcceleratedWidget GpuSurfaceTracker::AcquireNativeWidget(
}
#if defined(OS_ANDROID)
-gfx::ScopedJavaSurface GpuSurfaceTracker::AcquireJavaSurface(int surface_id) {
+gl::ScopedJavaSurface GpuSurfaceTracker::AcquireJavaSurface(int surface_id) {
return GetViewSurface(surface_id);
}
#endif
diff --git a/chromium/content/browser/gpu/gpu_surface_tracker.h b/chromium/content/browser/gpu/gpu_surface_tracker.h
index 51cad765368..5e519b8f9c7 100644
--- a/chromium/content/browser/gpu/gpu_surface_tracker.h
+++ b/chromium/content/browser/gpu/gpu_surface_tracker.h
@@ -39,7 +39,7 @@ class CONTENT_EXPORT GpuSurfaceTracker : public gpu::GpuSurfaceLookup {
gpu::SurfaceHandle surface_handle) override;
#if defined(OS_ANDROID)
- gfx::ScopedJavaSurface AcquireJavaSurface(int surface_id) override;
+ gl::ScopedJavaSurface AcquireJavaSurface(int surface_id) override;
#endif
// Gets the global instance of the surface tracker.
diff --git a/chromium/content/browser/iframe_zoom_browsertest.cc b/chromium/content/browser/iframe_zoom_browsertest.cc
index b7ae8c8343b..b74135ca51b 100644
--- a/chromium/content/browser/iframe_zoom_browsertest.cc
+++ b/chromium/content/browser/iframe_zoom_browsertest.cc
@@ -206,9 +206,12 @@ IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SubframesZoomProperly) {
WaitAndCheckFrameZoom(msg_queue, frame_observers);
}
- EXPECT_DOUBLE_EQ(
+ // Make this comparison approximate for Nexus5X test;
+ // https://crbug.com/622858.
+ EXPECT_NEAR(
new_zoom_factor,
- GetMainFrameZoomFactor(web_contents(), main_frame_window_border));
+ GetMainFrameZoomFactor(web_contents(), main_frame_window_border),
+ 0.01);
}
IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SubframesDontZoomIndependently) {
@@ -313,9 +316,13 @@ IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, AllFramesGetDefaultZoom) {
WaitAndCheckFrameZoom(msg_queue, frame_observers);
}
- EXPECT_DOUBLE_EQ(
+ // Make this comparison approximate for Nexus5X test;
+ // https://crbug.com/622858.
+ EXPECT_NEAR(
new_default_zoom_factor,
- GetMainFrameZoomFactor(web_contents(), main_frame_window_border));
+ GetMainFrameZoomFactor(web_contents(), main_frame_window_border),
+ 0.01
+ );
}
IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SiblingFramesZoom) {
@@ -363,9 +370,12 @@ IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SiblingFramesZoom) {
WaitAndCheckFrameZoom(msg_queue, frame_observers);
}
- EXPECT_DOUBLE_EQ(
+ // Make this comparison approximate for Nexus5X test;
+ // https://crbug.com/622858.
+ EXPECT_NEAR(
new_zoom_factor,
- GetMainFrameZoomFactor(web_contents(), main_frame_window_border));
+ GetMainFrameZoomFactor(web_contents(), main_frame_window_border),
+ 0.01);
}
IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SubframeRetainsZoomOnNavigation) {
@@ -409,9 +419,13 @@ IN_PROC_BROWSER_TEST_F(IFrameZoomBrowserTest, SubframeRetainsZoomOnNavigation) {
WaitAndCheckFrameZoom(msg_queue, frame_observers);
}
- EXPECT_DOUBLE_EQ(
+ // Make this comparison approximate for Nexus5X test;
+ // https://crbug.com/622858.
+ EXPECT_NEAR(
new_zoom_factor,
- GetMainFrameZoomFactor(web_contents(), main_frame_window_border));
+ GetMainFrameZoomFactor(web_contents(), main_frame_window_border),
+ 0.01
+ );
// Navigate child frame cross site, and make sure zoom is the same.
TestNavigationObserver observer(web_contents());
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 b33afc020c1..c3fba32e6a9 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -1363,14 +1363,19 @@ bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
static leveldb::Status DeleteRangeBasic(LevelDBTransaction* transaction,
const std::string& begin,
const std::string& end,
- bool upper_open) {
+ bool upper_open,
+ size_t* delete_count) {
+ DCHECK(delete_count);
std::unique_ptr<LevelDBIterator> it = transaction->CreateIterator();
leveldb::Status s;
+ *delete_count = 0;
for (s = it->Seek(begin); s.ok() && it->IsValid() &&
- (upper_open ? CompareKeys(it->Key(), end) < 0
- : CompareKeys(it->Key(), end) <= 0);
- s = it->Next())
- transaction->Remove(it->Key());
+ (upper_open ? CompareKeys(it->Key(), end) < 0
+ : CompareKeys(it->Key(), end) <= 0);
+ s = it->Next()) {
+ if (transaction->Remove(it->Key()))
+ (*delete_count)++;
+ }
return s;
}
@@ -1767,6 +1772,7 @@ leveldb::Status IndexedDBBackingStore::DeleteObjectStore(
LevelDBTransaction* leveldb_transaction = transaction->transaction();
base::string16 object_store_name;
+ size_t delete_count = 0;
bool found = false;
leveldb::Status s =
GetString(leveldb_transaction,
@@ -1792,8 +1798,8 @@ leveldb::Status IndexedDBBackingStore::DeleteObjectStore(
s = DeleteRangeBasic(
leveldb_transaction,
ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0),
- ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id),
- true);
+ ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id), true,
+ &delete_count);
if (s.ok()) {
leveldb_transaction->Remove(
@@ -1802,16 +1808,16 @@ leveldb::Status IndexedDBBackingStore::DeleteObjectStore(
s = DeleteRangeBasic(
leveldb_transaction,
IndexFreeListKey::Encode(database_id, object_store_id, 0),
- IndexFreeListKey::EncodeMaxKey(database_id, object_store_id),
- true);
+ IndexFreeListKey::EncodeMaxKey(database_id, object_store_id), true,
+ &delete_count);
}
if (s.ok()) {
s = DeleteRangeBasic(
leveldb_transaction,
IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0),
- IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id),
- true);
+ IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id), true,
+ &delete_count);
}
if (!s.ok()) {
@@ -1955,9 +1961,9 @@ leveldb::Status IndexedDBBackingStore::ClearObjectStore(
KeyPrefix(database_id, object_store_id).Encode();
const std::string stop_key =
KeyPrefix(database_id, object_store_id + 1).Encode();
-
- leveldb::Status s =
- DeleteRangeBasic(transaction->transaction(), start_key, stop_key, true);
+ size_t delete_count = 0;
+ leveldb::Status s = DeleteRangeBasic(transaction->transaction(), start_key,
+ stop_key, true, &delete_count);
if (!s.ok()) {
INTERNAL_WRITE_ERROR(CLEAR_OBJECT_STORE);
return s;
@@ -1993,8 +1999,11 @@ leveldb::Status IndexedDBBackingStore::DeleteRange(
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKeyRange& key_range) {
+ const IndexedDBKeyRange& key_range,
+ size_t* exists_delete_count) {
+ DCHECK(exists_delete_count);
leveldb::Status s;
+ *exists_delete_count = 0;
std::unique_ptr<IndexedDBBackingStore::Cursor> start_cursor =
OpenObjectStoreCursor(transaction, database_id, object_store_id,
key_range, blink::WebIDBCursorDirectionNext, &s);
@@ -2002,7 +2011,6 @@ leveldb::Status IndexedDBBackingStore::DeleteRange(
return s;
if (!start_cursor)
return leveldb::Status::OK(); // Empty range == delete success.
-
std::unique_ptr<IndexedDBBackingStore::Cursor> end_cursor =
OpenObjectStoreCursor(transaction, database_id, object_store_id,
key_range, blink::WebIDBCursorDirectionPrev, &s);
@@ -2013,7 +2021,6 @@ leveldb::Status IndexedDBBackingStore::DeleteRange(
return leveldb::Status::OK(); // Empty range == delete success.
BlobEntryKey start_blob_key, end_blob_key;
-
std::string start_key = ObjectStoreDataKey::Encode(
database_id, object_store_id, start_cursor->key());
base::StringPiece start_key_piece(start_key);
@@ -2033,15 +2040,20 @@ leveldb::Status IndexedDBBackingStore::DeleteRange(
false);
if (!s.ok())
return s;
- s = DeleteRangeBasic(transaction->transaction(), start_key, stop_key, false);
+ size_t data_delete_count = 0;
+ s = DeleteRangeBasic(transaction->transaction(), start_key, stop_key, false,
+ &data_delete_count);
if (!s.ok())
return s;
start_key =
ExistsEntryKey::Encode(database_id, object_store_id, start_cursor->key());
stop_key =
ExistsEntryKey::Encode(database_id, object_store_id, end_cursor->key());
- return DeleteRangeBasic(
- transaction->transaction(), start_key, stop_key, false);
+
+ s = DeleteRangeBasic(transaction->transaction(), start_key, stop_key, false,
+ exists_delete_count);
+ DCHECK_EQ(data_delete_count, *exists_delete_count);
+ return s;
}
leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
@@ -2835,20 +2847,22 @@ leveldb::Status IndexedDBBackingStore::DeleteIndex(
return InvalidDBKeyStatus();
LevelDBTransaction* leveldb_transaction = transaction->transaction();
+ size_t delete_count = 0;
const std::string index_meta_data_start =
IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0);
const std::string index_meta_data_end =
IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
- leveldb::Status s = DeleteRangeBasic(
- leveldb_transaction, index_meta_data_start, index_meta_data_end, true);
+ leveldb::Status s =
+ DeleteRangeBasic(leveldb_transaction, index_meta_data_start,
+ index_meta_data_end, true, &delete_count);
if (s.ok()) {
const std::string index_data_start =
IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
const std::string index_data_end =
IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
- s = DeleteRangeBasic(
- leveldb_transaction, index_data_start, index_data_end, true);
+ s = DeleteRangeBasic(leveldb_transaction, index_data_start, index_data_end,
+ true, &delete_count);
}
if (!s.ok())
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 a18256646b7..286c19ac33e 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -467,7 +467,8 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id,
- const IndexedDBKeyRange&) WARN_UNUSED_RESULT;
+ const IndexedDBKeyRange&,
+ size_t* delete_count) WARN_UNUSED_RESULT;
virtual leveldb::Status GetKeyGeneratorCurrentNumber(
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
index 7ca56ff5e80..c049019db82 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -459,10 +459,12 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
transaction3.Begin();
IndexedDBValue result_value;
- EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
- 1,
- 1,
- IndexedDBKeyRange(m_key3)).ok());
+ size_t delete_count = 0;
+ EXPECT_TRUE(backing_store_
+ ->DeleteRange(&transaction3, 1, 1,
+ IndexedDBKeyRange(m_key3), &delete_count)
+ .ok());
+ EXPECT_EQ(1UL, delete_count);
scoped_refptr<TestCallback> callback(new TestCallback());
EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
task_runner_->RunUntilIdle();
@@ -547,8 +549,12 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
transaction2.Begin();
IndexedDBValue result_value;
+ size_t delete_count = 0;
EXPECT_TRUE(
- backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
+ backing_store_
+ ->DeleteRange(&transaction2, 1, i + 1, ranges[i], &delete_count)
+ .ok());
+ EXPECT_EQ(2UL, delete_count);
scoped_refptr<TestCallback> callback(new TestCallback());
EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
task_runner_->RunUntilIdle();
@@ -637,8 +643,12 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
transaction2.Begin();
IndexedDBValue result_value;
+ size_t delete_count = 0;
EXPECT_TRUE(
- backing_store_->DeleteRange(&transaction2, 1, i + 1, ranges[i]).ok());
+ backing_store_
+ ->DeleteRange(&transaction2, 1, i + 1, ranges[i], &delete_count)
+ .ok());
+ EXPECT_EQ(0UL, delete_count);
scoped_refptr<TestCallback> callback(new TestCallback());
EXPECT_TRUE(transaction2.CommitPhaseOne(callback).ok());
task_runner_->RunUntilIdle();
@@ -732,10 +742,12 @@ TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
{
IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
transaction3.Begin();
- EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
- 1,
- 1,
- IndexedDBKeyRange(m_key3)).ok());
+ size_t delete_count = 0;
+ EXPECT_TRUE(backing_store_
+ ->DeleteRange(&transaction3, 1, 1,
+ IndexedDBKeyRange(m_key3), &delete_count)
+ .ok());
+ EXPECT_EQ(1UL, delete_count);
scoped_refptr<TestCallback> callback(new TestCallback());
EXPECT_TRUE(transaction3.CommitPhaseOne(callback).ok());
task_runner_->RunUntilIdle();
diff --git a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
index 7418b9da435..8262bbb62df 100644
--- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -16,6 +16,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/thread_test_helper.h"
@@ -93,8 +94,7 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
if (result != "pass") {
std::string js_result;
ASSERT_TRUE(ExecuteScriptAndExtractString(
- the_browser->web_contents(),
- "window.domAutomationController.send(getLog())",
+ the_browser, "window.domAutomationController.send(getLog())",
&js_result));
FAIL() << "Failed: " << js_result;
}
@@ -156,7 +156,7 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
BrowserMainLoop::GetInstance()->indexed_db_thread()->task_runner()));
EXPECT_TRUE(helper->Run());
// Wait for DidGetDiskUsage to be called.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
return disk_usage_;
}
@@ -170,7 +170,7 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
BrowserMainLoop::GetInstance()->indexed_db_thread()->task_runner()));
EXPECT_TRUE(helper->Run());
// Wait for DidGetBlobFileCount to be called.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
return blob_file_count_;
}
@@ -466,7 +466,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, DISABLED_BlobDidAck) {
SimpleTest(GetTestUrl("indexeddb", "blob_did_ack.html"));
// Wait for idle so that the blob ack has time to be received/processed by
// the browser process.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
content::ChromeBlobStorageContext* blob_context =
ChromeBlobStorageContext::GetFor(
shell()->web_contents()->GetBrowserContext());
@@ -479,7 +479,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed,
SimpleTest(GetTestUrl("indexeddb", "blob_did_ack_prefetch.html"));
// Wait for idle so that the blob ack has time to be received/processed by
// the browser process.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
content::ChromeBlobStorageContext* blob_context =
ChromeBlobStorageContext::GetFor(
shell()->web_contents()->GetBrowserContext());
@@ -610,7 +610,9 @@ static std::unique_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
if (request_path == "corruptdb" && !request_query.empty()) {
VLOG(0) << "Requested to corrupt IndexedDB: " << request_query;
- base::WaitableEvent signal_when_finished(false, false);
+ base::WaitableEvent signal_when_finished(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
context->TaskRunner()->PostTask(
FROM_HERE,
base::Bind(&CorruptIndexedDBDatabase, base::ConstRef(context), origin,
@@ -730,8 +732,7 @@ INSTANTIATE_TEST_CASE_P(IndexedDBBrowserTestInstantiation,
"failTransactionCommit",
"clearObjectStore"));
-IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest,
- DeleteCompactsBackingStore) {
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteCompactsBackingStore) {
const GURL test_url = GetTestUrl("indexeddb", "delete_compact.html");
SimpleTest(GURL(test_url.spec() + "#fill"));
int64_t after_filling = RequestDiskUsage();
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.h b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
index c07cc3297db..4895c3be03f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
@@ -101,9 +101,9 @@ class CONTENT_EXPORT IndexedDBCallbacks
// IndexedDBDatabase::Count
// IndexedDBFactory::DeleteDatabase
+ // IndexedDBDatabase::DeleteRange
virtual void OnSuccess(int64_t value);
- // IndexedDBDatabase::Delete
// IndexedDBCursor::Continue / Advance (when complete)
virtual void OnSuccess();
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 ec67dd2474e..8ec55b0c040 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -266,16 +266,16 @@ base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
}
transaction_info->Set("scope", scope.release());
- transaction_list->Append(transaction_info.release());
+ transaction_list->Append(std::move(transaction_info));
}
db_info->Set("transactions", transaction_list.release());
- database_list->Append(db_info.release());
+ database_list->Append(std::move(db_info));
}
info->Set("databases", database_list.release());
}
- list->Append(info.release());
+ list->Append(std::move(info));
}
return list.release();
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.cc b/chromium/content/browser/indexed_db/indexed_db_database.cc
index c686ae87ad3..6d104a56d42 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database.cc
@@ -12,11 +12,13 @@
#include <utility>
#include "base/auto_reset.h"
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_vector.h"
#include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
@@ -35,6 +37,7 @@
#include "content/common/indexed_db/indexed_db_constants.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
+#include "content/public/common/content_switches.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
#include "third_party/leveldatabase/env_chromium.h"
@@ -157,7 +160,10 @@ IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
IndexedDBDatabaseMetadata::NO_VERSION,
kInvalidId),
identifier_(unique_identifier),
- factory_(factory) {
+ factory_(factory),
+ experimental_web_platform_features_enabled_(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
DCHECK(factory != NULL);
}
@@ -1410,13 +1416,12 @@ void IndexedDBDatabase::DeleteRangeOperation(
std::unique_ptr<IndexedDBKeyRange> key_range,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction) {
- IDB_TRACE1(
- "IndexedDBDatabase::DeleteRangeOperation", "txn.id", transaction->id());
+ IDB_TRACE1("IndexedDBDatabase::DeleteRangeOperation", "txn.id",
+ transaction->id());
+ size_t delete_count = 0;
leveldb::Status s =
- backing_store_->DeleteRange(transaction->BackingStoreTransaction(),
- id(),
- object_store_id,
- *key_range);
+ backing_store_->DeleteRange(transaction->BackingStoreTransaction(), id(),
+ object_store_id, *key_range, &delete_count);
if (!s.ok()) {
base::string16 error_string =
ASCIIToUTF16("Internal error deleting data in range");
@@ -1428,7 +1433,11 @@ void IndexedDBDatabase::DeleteRangeOperation(
}
return;
}
- callbacks->OnSuccess();
+ if (experimental_web_platform_features_enabled_) {
+ callbacks->OnSuccess(base::checked_cast<int64_t>(delete_count));
+ } else {
+ callbacks->OnSuccess();
+ }
}
void IndexedDBDatabase::Clear(int64_t transaction_id,
@@ -1613,7 +1622,7 @@ void IndexedDBDatabase::ProcessPendingCalls() {
}
if (!IsDeleteDatabaseBlocked()) {
- PendingDeleteCallList pending_delete_calls;
+ std::list<PendingDeleteCall*> pending_delete_calls;
pending_delete_calls_.swap(pending_delete_calls);
while (!pending_delete_calls.empty()) {
// Only the first delete call will delete the database, but each must fire
@@ -1629,11 +1638,11 @@ void IndexedDBDatabase::ProcessPendingCalls() {
}
if (!IsOpenConnectionBlocked()) {
- PendingOpenCallList pending_open_calls;
+ std::queue<IndexedDBPendingConnection> pending_open_calls;
pending_open_calls_.swap(pending_open_calls);
while (!pending_open_calls.empty()) {
OpenConnection(pending_open_calls.front());
- pending_open_calls.pop_front();
+ pending_open_calls.pop();
}
}
}
@@ -1682,7 +1691,7 @@ void IndexedDBDatabase::OpenConnection(
// presence of existing connections means we didn't even check for data loss
// so there'd better not be any.
DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss());
- pending_open_calls_.push_back(connection);
+ pending_open_calls_.push(connection);
return;
}
@@ -1914,7 +1923,7 @@ void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
ProcessPendingCalls();
// TODO(jsbell): Add a test for the pending_open_calls_ cases below.
- if (!ConnectionCount() && !pending_open_calls_.size() &&
+ if (!ConnectionCount() && pending_open_calls_.empty() &&
!pending_delete_calls_.size()) {
DCHECK(transactions_.empty());
backing_store_ = NULL;
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.h b/chromium/content/browser/indexed_db/indexed_db_database.h
index 2a6615f744b..bcbdb538770 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database.h
@@ -10,6 +10,7 @@
#include <list>
#include <map>
+#include <queue>
#include <string>
#include <utility>
#include <vector>
@@ -260,8 +261,6 @@ class CONTENT_EXPORT IndexedDBDatabase
class PendingUpgradeCall;
typedef std::map<int64_t, IndexedDBTransaction*> TransactionMap;
- typedef std::list<IndexedDBPendingConnection> PendingOpenCallList;
- typedef std::list<PendingDeleteCall*> PendingDeleteCallList;
typedef list_set<IndexedDBConnection*> ConnectionSet;
bool IsOpenConnectionBlocked() const;
@@ -304,13 +303,14 @@ class CONTENT_EXPORT IndexedDBDatabase
IndexedDBTransactionCoordinator transaction_coordinator_;
TransactionMap transactions_;
- PendingOpenCallList pending_open_calls_;
+ std::queue<IndexedDBPendingConnection> pending_open_calls_;
std::unique_ptr<PendingUpgradeCall>
pending_run_version_change_transaction_call_;
std::unique_ptr<PendingSuccessCall> pending_second_half_open_;
- PendingDeleteCallList pending_delete_calls_;
+ std::list<PendingDeleteCall*> pending_delete_calls_;
ConnectionSet connections_;
+ bool experimental_web_platform_features_enabled_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabase);
};
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 0a6ddab4e26..cc4cb3ceeaf 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -10,6 +10,7 @@
#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"
#include "content/browser/indexed_db/indexed_db_connection.h"
@@ -483,7 +484,7 @@ TEST_F(IndexedDBFactoryTest, DatabaseFailedOpen) {
EXPECT_TRUE(factory()->IsDatabaseOpen(origin, db_name));
// Pump the message loop so the upgrade transaction can run.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callbacks->connection());
callbacks->connection()->database()->Commit(transaction_id);
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 6f388b8b0e4..357ed1e148b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -124,8 +124,8 @@ void IndexedDBInternalsUI::OnOriginsReady(
std::unique_ptr<base::ListValue> origins,
const base::FilePath& path) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- web_ui()->CallJavascriptFunction(
- "indexeddb.onOriginsReady", *origins, base::StringValue(path.value()));
+ web_ui()->CallJavascriptFunctionUnsafe("indexeddb.onOriginsReady", *origins,
+ base::StringValue(path.value()));
}
static void FindContext(const base::FilePath& partition_path,
@@ -269,7 +269,7 @@ void IndexedDBInternalsUI::ForceCloseOriginOnIndexedDBThread(
void IndexedDBInternalsUI::OnForcedClose(const base::FilePath& partition_path,
const Origin& origin,
size_t connection_count) {
- web_ui()->CallJavascriptFunction(
+ web_ui()->CallJavascriptFunctionUnsafe(
"indexeddb.onForcedClose", base::StringValue(partition_path.value()),
base::StringValue(origin.Serialize()),
base::FundamentalValue(static_cast<double>(connection_count)));
@@ -286,7 +286,8 @@ void IndexedDBInternalsUI::OnDownloadDataReady(
BrowserContext* browser_context =
web_ui()->GetWebContents()->GetBrowserContext();
std::unique_ptr<DownloadUrlParameters> dl_params(
- DownloadUrlParameters::FromWebContents(web_ui()->GetWebContents(), url));
+ DownloadUrlParameters::CreateForWebContentsMainFrame(
+ web_ui()->GetWebContents(), url));
DownloadManager* dlm = BrowserContext::GetDownloadManager(browser_context);
const GURL referrer(web_ui()->GetWebContents()->GetLastCommittedURL());
@@ -356,7 +357,7 @@ void IndexedDBInternalsUI::OnDownloadStarted(
}
item->AddObserver(new FileDeleter(temp_path));
- web_ui()->CallJavascriptFunction(
+ web_ui()->CallJavascriptFunctionUnsafe(
"indexeddb.onOriginDownloadReady",
base::StringValue(partition_path.value()),
base::StringValue(origin.Serialize()),
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
index f56346b442e..19c50610c35 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
@@ -11,8 +11,10 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_quota_client.h"
@@ -46,8 +48,8 @@ class IndexedDBQuotaClientTest : public testing::Test {
scoped_refptr<storage::QuotaManager> quota_manager =
new MockQuotaManager(false /*in_memory*/, browser_context_->GetPath(),
- base::MessageLoop::current()->task_runner(),
- base::MessageLoop::current()->task_runner(),
+ base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
browser_context_->GetSpecialStoragePolicy());
idb_context_ =
@@ -55,7 +57,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
browser_context_->GetSpecialStoragePolicy(),
quota_manager->proxy(),
task_runner_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
setup_temp_dir();
}
@@ -73,7 +75,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
FlushIndexedDBTaskRunner();
idb_context_ = NULL;
browser_context_.reset();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
int64_t GetOriginUsage(storage::QuotaClient* client,
@@ -86,7 +88,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
base::Bind(&IndexedDBQuotaClientTest::OnGetOriginUsageComplete,
weak_factory_.GetWeakPtr()));
FlushIndexedDBTaskRunner();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_GT(usage_, -1);
return usage_;
}
@@ -99,7 +101,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
base::Bind(&IndexedDBQuotaClientTest::OnGetOriginsComplete,
weak_factory_.GetWeakPtr()));
FlushIndexedDBTaskRunner();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
return origins_;
}
@@ -113,7 +115,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
base::Bind(&IndexedDBQuotaClientTest::OnGetOriginsComplete,
weak_factory_.GetWeakPtr()));
FlushIndexedDBTaskRunner();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
return origins_;
}
@@ -126,7 +128,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
base::Bind(&IndexedDBQuotaClientTest::OnDeleteOriginComplete,
weak_factory_.GetWeakPtr()));
FlushIndexedDBTaskRunner();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
return delete_status_;
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.cc b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
index a7f17b6178c..768cf1dc2f8 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
@@ -21,8 +21,19 @@
namespace content {
+namespace {
+
const int64_t kInactivityTimeoutPeriodSeconds = 60;
+// Helper for posting a task to call IndexedDBTransaction::Commit when we know
+// the transaction had no requests and therefore the commit must succeed.
+void CommitUnused(scoped_refptr<IndexedDBTransaction> transaction) {
+ leveldb::Status status = transaction->Commit();
+ DCHECK(status.ok());
+}
+
+} // namespace
+
IndexedDBTransaction::TaskQueue::TaskQueue() {}
IndexedDBTransaction::TaskQueue::~TaskQueue() { clear(); }
@@ -204,8 +215,16 @@ void IndexedDBTransaction::Start() {
state_ = STARTED;
diagnostics_.start_time = base::Time::Now();
- if (!used_)
+ if (!used_) {
+ if (commit_pending_) {
+ // The transaction has never had requests issued against it, but the
+ // front-end previously requested a commit; do the commit now, but not
+ // re-entrantly as that may renter the coordinator.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&CommitUnused, make_scoped_refptr(this)));
+ }
return;
+ }
RunTasksIfStarted();
}
@@ -253,6 +272,12 @@ leveldb::Status IndexedDBTransaction::Commit() {
DCHECK(!used_ || state_ == STARTED);
commit_pending_ = true;
+ // Front-end has requested a commit, but this transaction is blocked by
+ // other transactions. The commit will be initiated when the transaction
+ // coordinator unblocks this transaction.
+ if (state_ != STARTED)
+ return leveldb::Status::OK();
+
// Front-end has requested a commit, but there may be tasks like
// create_index which are considered synchronous by the front-end
// but are processed asynchronously.
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 dbe63ac0f71..170ccd23a3b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -10,6 +10,7 @@
#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_fake_backing_store.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
@@ -198,7 +199,7 @@ TEST_P(IndexedDBTransactionTestMode, ScheduleNormalTask) {
// Pump the message loop so that the transaction completes all pending tasks,
// otherwise it will defer the commit.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(transaction->HasPendingTasks());
EXPECT_TRUE(transaction->IsTaskQueueEmpty());
EXPECT_TRUE(transaction->task_queue_.empty());
@@ -258,7 +259,7 @@ TEST_F(IndexedDBTransactionTest, SchedulePreemptiveTask) {
// Pump the message loop so that the transaction completes all pending tasks,
// otherwise it will defer the commit.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(transaction->HasPendingTasks());
EXPECT_TRUE(transaction->IsTaskQueueEmpty());
EXPECT_TRUE(transaction->task_queue_.empty());
@@ -301,7 +302,7 @@ TEST_P(IndexedDBTransactionTestMode, AbortTasks) {
// Pump the message loop so that the transaction completes all pending tasks,
// otherwise it will defer the commit.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(observer.abort_task_called());
transaction->Commit();
diff --git a/chromium/content/browser/indexed_db/indexed_db_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
index ea958de168b..b3736a50ce0 100644
--- a/chromium/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
@@ -247,11 +247,11 @@ TEST_F(IndexedDBTest, DeleteFailsIfDirectoryLocked) {
ASSERT_TRUE(lock);
// TODO(jsbell): Remove static_cast<> when overloads are eliminated.
+ void (IndexedDBContextImpl::* delete_for_origin)(const Origin&) =
+ &IndexedDBContextImpl::DeleteForOrigin;
idb_context->TaskRunner()->PostTask(
FROM_HERE,
- base::Bind(static_cast<void (IndexedDBContextImpl::*)(const Origin&)>(
- &IndexedDBContextImpl::DeleteForOrigin),
- idb_context, kTestOrigin));
+ base::Bind(delete_for_origin, idb_context, kTestOrigin));
FlushIndexedDBTaskRunner();
EXPECT_TRUE(base::DirectoryExists(test_path));
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
index 87186ee6dce..9126d4a0db8 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -4,6 +4,7 @@
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
+#include <inttypes.h>
#include <stdint.h>
#include <cerrno>
@@ -460,8 +461,8 @@ bool LevelDBDatabase::OnMemoryDump(
DCHECK(res);
base::StringToUint64(value, &size);
- auto dump = pmd->CreateAllocatorDump(
- base::StringPrintf("leveldb/index_db/%p", db_.get()));
+ auto dump = pmd->CreateAllocatorDump(base::StringPrintf(
+ "leveldb/index_db/0x%" PRIXPTR, reinterpret_cast<uintptr_t>(db_.get())));
dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes, size);
dump->AddString("file_name", "", file_name_for_tracing);
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
index 2abd7e6033d..a42f3c3da4f 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
@@ -36,7 +36,7 @@ void LevelDBTransaction::Clear() {
LevelDBTransaction::~LevelDBTransaction() { Clear(); }
-void LevelDBTransaction::Set(const StringPiece& key,
+bool LevelDBTransaction::Set(const StringPiece& key,
std::string* value,
bool deleted) {
DCHECK(!finished_);
@@ -49,20 +49,21 @@ void LevelDBTransaction::Set(const StringPiece& key,
record->deleted = deleted;
data_[record->key] = record;
NotifyIterators();
- return;
+ return false;
}
-
+ bool replaced_deleted_value = it->second->deleted;
it->second->value.swap(*value);
it->second->deleted = deleted;
+ return replaced_deleted_value;
}
void LevelDBTransaction::Put(const StringPiece& key, std::string* value) {
Set(key, value, false);
}
-void LevelDBTransaction::Remove(const StringPiece& key) {
+bool LevelDBTransaction::Remove(const StringPiece& key) {
std::string empty;
- Set(key, &empty, true);
+ return !Set(key, &empty, true);
}
leveldb::Status LevelDBTransaction::Get(const StringPiece& key,
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h
index 988506fac5e..91ae38bf98d 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h
@@ -26,7 +26,10 @@ class CONTENT_EXPORT LevelDBTransaction
: public base::RefCounted<LevelDBTransaction> {
public:
void Put(const base::StringPiece& key, std::string* value);
- void Remove(const base::StringPiece& key);
+
+ // Returns true if this operation performs a change, where the value wasn't
+ // already deleted.
+ bool Remove(const base::StringPiece& key);
virtual leveldb::Status Get(const base::StringPiece& key,
std::string* value,
bool* found);
@@ -129,8 +132,8 @@ class CONTENT_EXPORT LevelDBTransaction
DISALLOW_COPY_AND_ASSIGN(TransactionIterator);
};
-
- void Set(const base::StringPiece& key, std::string* value, bool deleted);
+ // Returns true if the key was originally marked deleted, false otherwise.
+ bool Set(const base::StringPiece& key, std::string* value, bool deleted);
void Clear();
void RegisterIterator(TransactionIterator* iterator);
void UnregisterIterator(TransactionIterator* iterator);
diff --git a/chromium/content/browser/leveldb_wrapper_impl.cc b/chromium/content/browser/leveldb_wrapper_impl.cc
index c9d7157c32b..546676cd2e5 100644
--- a/chromium/content/browser/leveldb_wrapper_impl.cc
+++ b/chromium/content/browser/leveldb_wrapper_impl.cc
@@ -222,7 +222,7 @@ void LevelDBWrapperImpl::GetAll(const mojo::String& source,
return;
}
- mojo::Array<mojom::KeyValuePtr> all(map_->size());
+ mojo::Array<mojom::KeyValuePtr> all;
for (const auto& it : (*map_)) {
mojom::KeyValuePtr kv = mojom::KeyValue::New();
kv->key = it.first.Clone();
diff --git a/chromium/content/browser/loader/DEPS b/chromium/content/browser/loader/DEPS
index 188bb2b8214..1f7b4e9ce67 100644
--- a/chromium/content/browser/loader/DEPS
+++ b/chromium/content/browser/loader/DEPS
@@ -24,7 +24,6 @@ specific_include_rules = {
# TODO: these all have to be removed.
"+content/browser/host_zoom_map_impl.h",
- "+content/browser/resource_context_impl.h",
"+content/public/common/content_features.h",
# TODO: To be replaced by mojo.
@@ -93,15 +92,14 @@ specific_include_rules = {
"-content",
"+content/browser/loader/power_save_block_resource_throttle.h",
"+content/public/browser/resource_throttle.h",
-
- # TODO: these all have to be removed.
- "+content/public/browser/power_save_blocker.h",
],
"resource_dispatcher_host_impl\.(cc|h)": [
"-content",
+ "+content/browser/cert_store_impl.h",
"+content/browser/loader/async_resource_handler.h",
"+content/browser/loader/async_revalidation_manager.h",
"+content/browser/loader/global_routing_id.h",
+ "+content/browser/loader/loader_delegate.h",
"+content/browser/loader/power_save_block_resource_throttle.h",
"+content/browser/loader/resource_dispatcher_host_impl.h",
"+content/browser/loader/resource_loader.h",
@@ -112,6 +110,8 @@ specific_include_rules = {
"+content/browser/loader/stream_resource_handler.h",
"+content/browser/loader/sync_resource_handler.h",
"+content/browser/loader/throttling_resource_handler.h",
+ "+content/common/resource_request_body_impl.h",
+ "+content/common/ssl_status_serialization.h",
"+content/public/browser/global_request_id.h",
"+content/public/browser/resource_dispatcher_host.h",
"+content/public/browser/resource_dispatcher_host_delegate.h",
@@ -122,7 +122,6 @@ specific_include_rules = {
"+content/browser/appcache/chrome_appcache_service.h",
"+content/browser/bad_message.h",
"+content/browser/blob_storage/chrome_blob_storage_context.h",
- "+content/browser/cert_store_impl.h",
"+content/browser/child_process_security_policy_impl.h",
"+content/browser/download/download_resource_handler.h",
"+content/browser/download/save_file_manager.h",
@@ -139,8 +138,6 @@ specific_include_rules = {
"+content/browser/loader/navigation_url_loader_impl_core.h",
"+content/browser/loader/redirect_to_file_resource_handler.h",
"+content/browser/loader/upload_data_stream_builder.h",
- "+content/browser/renderer_host/render_view_host_delegate.h",
- "+content/browser/renderer_host/render_view_host_impl.h",
"+content/browser/resource_context_impl.h",
"+content/browser/service_worker/foreign_fetch_request_handler.h",
"+content/browser/service_worker/link_header_support.h",
@@ -148,26 +145,16 @@ specific_include_rules = {
"+content/browser/streams/stream.h",
"+content/browser/streams/stream_context.h",
"+content/browser/streams/stream_registry.h",
- "+content/browser/web_contents/web_contents_impl.h",
- "+content/common/appcache_interfaces.h",
"+content/common/content_export.h",
"+content/common/navigation_params.h",
"+content/common/net/url_request_service_worker_data.h",
- "+content/common/resource_request_body.h",
"+content/common/site_isolation_policy.h",
- "+content/common/ssl_status_serialization.h",
"+content/public/browser/browser_thread.h",
- "+content/public/browser/child_process_data.h",
"+content/public/browser/content_browser_client.h",
- "+content/public/browser/download_item.h",
- "+content/public/browser/download_manager.h",
- "+content/public/browser/download_url_parameters.h",
- "+content/public/browser/notification_types.h",
"+content/public/browser/plugin_service.h",
"+content/public/browser/resource_request_details.h",
"+content/public/browser/stream_handle.h",
"+content/public/browser/stream_info.h",
- "+content/public/browser/user_metrics.h",
"+content/public/browser/web_contents_observer.h",
"+content/public/common/browser_side_navigation_policy.h",
"+content/public/common/content_features.h",
@@ -193,7 +180,11 @@ specific_include_rules = {
"+content/browser/loader/resource_loader.h",
"+content/browser/loader/resource_loader_delegate.h",
"+content/browser/loader/resource_request_info_impl.h",
+ "+content/browser/ssl/ssl_client_auth_handler.h",
+ "+content/browser/ssl/ssl_error_handler.h",
"+content/common/content_export.h",
+ "+content/common/ssl_status_serialization.h",
+ "+content/public/browser/cert_store.h",
"+content/public/browser/resource_controller.h",
"+content/public/browser/resource_dispatcher_host_login_delegate.h",
"+content/public/common/resource_response.h",
@@ -205,19 +196,12 @@ specific_include_rules = {
"+content/browser/loader/detachable_resource_handler.h",
"+content/browser/service_worker/service_worker_request_handler.h",
"+content/browser/service_worker/service_worker_response_info.h",
- "+content/browser/ssl/ssl_client_auth_handler.h",
- "+content/browser/ssl/ssl_error_handler.h",
"+content/browser/ssl/ssl_manager.h",
"+content/browser/ssl/ssl_policy.h",
- "+content/common/ssl_status_serialization.h",
- "+content/public/browser/cert_store.h",
- "+content/public/browser/resource_context.h",
- "+content/public/browser/signed_certificate_timestamp_store.h",
"+content/public/common/content_client.h",
"+content/public/common/content_switches.h",
"+content/public/common/process_type.h",
"+content/public/common/security_style.h",
- "+content/public/common/signed_certificate_timestamp_id_and_status.h",
],
"resource_handler_delegate\.h": [
"-content",
@@ -229,6 +213,7 @@ specific_include_rules = {
"+content/browser/loader/resource_message_filter.h",
"+content/browser/loader/resource_request_info_impl.h",
"+content/common/content_export.h",
+ "+content/common/resource_request_body_impl.h",
"+content/public/browser/global_request_id.h",
"+content/public/browser/resource_request_info.h",
"+content/public/common/referrer.h",
diff --git a/chromium/content/browser/loader/async_resource_handler.cc b/chromium/content/browser/loader/async_resource_handler.cc
index f570cea606b..321b0de619b 100644
--- a/chromium/content/browser/loader/async_resource_handler.cc
+++ b/chromium/content/browser/loader/async_resource_handler.cc
@@ -23,7 +23,6 @@
#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/resource_context_impl.h"
#include "content/common/resource_messages.h"
#include "content/common/resource_request_completion_status.h"
#include "content/common/view_messages.h"
diff --git a/chromium/content/browser/loader/async_resource_handler_browsertest.cc b/chromium/content/browser/loader/async_resource_handler_browsertest.cc
index 4a9c4409534..d0e15f0bdb5 100644
--- a/chromium/content/browser/loader/async_resource_handler_browsertest.cc
+++ b/chromium/content/browser/loader/async_resource_handler_browsertest.cc
@@ -78,10 +78,8 @@ IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest, UploadProgress) {
std::string js_result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
- base::StringPrintf("WaitForAsyncXHR('%s', %" PRIuS ")",
- kPostPath,
- kPayloadSize),
+ shell(), base::StringPrintf("WaitForAsyncXHR('%s', %" PRIuS ")",
+ kPostPath, kPayloadSize),
&js_result));
EXPECT_EQ(js_result, "success");
}
@@ -98,10 +96,8 @@ IN_PROC_BROWSER_TEST_F(AsyncResourceHandlerBrowserTest,
std::string js_result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
- base::StringPrintf("WaitForAsyncXHR('%s', %" PRIuS ")",
- kRedirectPostPath,
- kPayloadSize),
+ shell(), base::StringPrintf("WaitForAsyncXHR('%s', %" PRIuS ")",
+ kRedirectPostPath, kPayloadSize),
&js_result));
EXPECT_EQ(js_result, "success");
}
diff --git a/chromium/content/browser/loader/async_revalidation_manager_unittest.cc b/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
index f299ad54d0f..68053ff34a0 100644
--- a/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
+++ b/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
@@ -19,6 +19,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/loader_delegate_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/resource_messages.h"
#include "content/common/resource_request.h"
@@ -270,6 +271,7 @@ class AsyncRevalidationManagerTest : public ::testing::Test {
std::unique_ptr<net::TestNetworkDelegate> network_delegate)
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
network_delegate_(std::move(network_delegate)) {
+ host_.SetLoaderDelegate(&loader_delegate_);
browser_context_.reset(new TestBrowserContext());
BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
base::RunLoop().RunUntilIdle();
@@ -321,6 +323,7 @@ class AsyncRevalidationManagerTest : public ::testing::Test {
std::unique_ptr<TestURLRequestJobFactory> job_factory_;
scoped_refptr<BlackholeFilter> filter_;
std::unique_ptr<net::TestNetworkDelegate> network_delegate_;
+ LoaderDelegateImpl loader_delegate_;
ResourceDispatcherHostImpl host_;
};
diff --git a/chromium/content/browser/loader/loader_delegate.h b/chromium/content/browser/loader/loader_delegate.h
new file mode 100644
index 00000000000..b2f29de1794
--- /dev/null
+++ b/chromium/content/browser/loader/loader_delegate.h
@@ -0,0 +1,56 @@
+// 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_LOADER_DELEGATE_H_
+#define CONTENT_BROWSER_LOADER_LOADER_DELEGATE_H_
+
+#include <inttypes.h>
+
+#include <memory>
+
+#include "content/common/content_export.h"
+#include "content/public/browser/resource_request_details.h"
+#include "net/base/load_states.h"
+
+class GURL;
+
+namespace content {
+
+// Delegate from loader to the rest of content. Should be interacted with on the
+// IO thread.
+//
+// This is used for breaking dependencies between content at-large and
+// content/browser/loader which will eventually be moved to a separate
+// networking service. All methods in this interface should be asynchronous,
+// since eventually this will be a Mojo interface. See https://crbug.com/622050
+// and https://crbug.com/598073.
+class CONTENT_EXPORT LoaderDelegate {
+ public:
+ virtual ~LoaderDelegate() {}
+
+ // Notification that the load state for the route identified by child_id and
+ // route_id has changed.
+ virtual void LoadStateChanged(int child_id,
+ int route_id,
+ const GURL& url,
+ const net::LoadStateWithParam& load_state,
+ uint64_t upload_position,
+ uint64_t upload_size) = 0;
+
+ // Notification that a response has been received for a resource request.
+ virtual void DidGetResourceResponseStart(
+ int render_process_id,
+ int render_frame_host,
+ std::unique_ptr<ResourceRequestDetails> details) = 0;
+
+ // Notification that a redirect was received while requesting a resource.
+ virtual void DidGetRedirectForResourceRequest(
+ int render_process_id,
+ int render_frame_host,
+ std::unique_ptr<ResourceRedirectDetails> details) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_LOADER_DELEGATE_H_
diff --git a/chromium/content/browser/loader/mime_type_resource_handler.cc b/chromium/content/browser/loader/mime_type_resource_handler.cc
index 6cf84d58612..ab4fca3a8db 100644
--- a/chromium/content/browser/loader/mime_type_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_type_resource_handler.cc
@@ -73,12 +73,15 @@ MimeTypeResourceHandler::MimeTypeResourceHandler(
: LayeredResourceHandler(request, std::move(next_handler)),
state_(STATE_STARTING),
host_(host),
+#if defined(ENABLE_PLUGINS)
plugin_service_(plugin_service),
+#endif
read_buffer_size_(0),
bytes_read_(0),
must_download_(false),
must_download_is_set_(false),
- weak_ptr_factory_(this) {}
+ weak_ptr_factory_(this) {
+}
MimeTypeResourceHandler::~MimeTypeResourceHandler() {
}
diff --git a/chromium/content/browser/loader/mime_type_resource_handler.h b/chromium/content/browser/loader/mime_type_resource_handler.h
index cef22b77b65..f5581a6a807 100644
--- a/chromium/content/browser/loader/mime_type_resource_handler.h
+++ b/chromium/content/browser/loader/mime_type_resource_handler.h
@@ -120,7 +120,9 @@ class CONTENT_EXPORT MimeTypeResourceHandler
scoped_refptr<ResourceResponse> response_;
ResourceDispatcherHostImpl* host_;
+#if defined(ENABLE_PLUGINS)
PluginService* plugin_service_;
+#endif
scoped_refptr<net::IOBuffer> read_buffer_;
int read_buffer_size_;
int bytes_read_;
diff --git a/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc b/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc
index ca9de0b4a77..6bed3a84943 100644
--- a/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc
@@ -9,8 +9,11 @@
#include <memory>
#include "base/files/file_path.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
@@ -188,8 +191,8 @@ class TestFakePluginService : public FakePluginService {
void GetPlugins(const GetPluginsCallback& callback) override {
is_plugin_stale_ = false;
std::vector<WebPluginInfo> plugins;
- base::MessageLoop::current()->PostTask(FROM_HERE,
- base::Bind(callback, plugins));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, plugins));
}
private:
diff --git a/chromium/content/browser/loader/navigation_resource_throttle.cc b/chromium/content/browser/loader/navigation_resource_throttle.cc
index 3c0f5121c4c..2ad781f10af 100644
--- a/chromium/content/browser/loader/navigation_resource_throttle.cc
+++ b/chromium/content/browser/loader/navigation_resource_throttle.cc
@@ -10,8 +10,10 @@
#include "base/callback.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/memory/ref_counted.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/loader/resource_request_info_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/resource_context.h"
@@ -39,14 +41,17 @@ void SendCheckResultToIOThread(UIChecksPerformedCallback callback,
base::Bind(callback, result));
}
-void CheckWillStartRequestOnUIThread(UIChecksPerformedCallback callback,
- int render_process_id,
- int render_frame_host_id,
- const std::string& method,
- const Referrer& sanitized_referrer,
- bool has_user_gesture,
- ui::PageTransition transition,
- bool is_external_protocol) {
+void CheckWillStartRequestOnUIThread(
+ UIChecksPerformedCallback callback,
+ int render_process_id,
+ int render_frame_host_id,
+ const std::string& method,
+ const scoped_refptr<content::ResourceRequestBodyImpl>&
+ resource_request_body,
+ const Referrer& sanitized_referrer,
+ bool has_user_gesture,
+ ui::PageTransition transition,
+ bool is_external_protocol) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHostImpl* render_frame_host =
RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
@@ -63,8 +68,9 @@ void CheckWillStartRequestOnUIThread(UIChecksPerformedCallback callback,
}
navigation_handle->WillStartRequest(
- method, sanitized_referrer, has_user_gesture, transition,
- is_external_protocol, base::Bind(&SendCheckResultToIOThread, callback));
+ method, resource_request_body, sanitized_referrer, has_user_gesture,
+ transition, is_external_protocol,
+ base::Bind(&SendCheckResultToIOThread, callback));
}
void CheckWillRedirectRequestOnUIThread(
@@ -141,7 +147,8 @@ NavigationResourceThrottle::~NavigationResourceThrottle() {}
void NavigationResourceThrottle::WillStartRequest(bool* defer) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+ const ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
if (!info)
return;
@@ -159,7 +166,7 @@ void NavigationResourceThrottle::WillStartRequest(bool* defer) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&CheckWillStartRequestOnUIThread, callback, render_process_id,
- render_frame_id, request_->method(),
+ render_frame_id, request_->method(), info->body(),
Referrer::SanitizeForRequest(
request_->url(), Referrer(GURL(request_->referrer()),
info->GetReferrerPolicy())),
@@ -172,10 +179,13 @@ void NavigationResourceThrottle::WillRedirectRequest(
const net::RedirectInfo& redirect_info,
bool* defer) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+ ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_);
if (!info)
return;
+ if (redirect_info.new_method != "POST")
+ info->ResetBody();
+
int render_process_id, render_frame_id;
if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
return;
@@ -259,6 +269,8 @@ void NavigationResourceThrottle::OnUIChecksPerformed(
controller()->CancelAndIgnore();
} else if (result == NavigationThrottle::CANCEL) {
controller()->Cancel();
+ } else if (result == NavigationThrottle::BLOCK_REQUEST) {
+ controller()->CancelWithError(net::ERR_BLOCKED_BY_CLIENT);
} else {
controller()->Resume();
}
diff --git a/chromium/content/browser/loader/navigation_url_loader.cc b/chromium/content/browser/loader/navigation_url_loader.cc
index d9b0c927543..0dd7fe22c82 100644
--- a/chromium/content/browser/loader/navigation_url_loader.cc
+++ b/chromium/content/browser/loader/navigation_url_loader.cc
@@ -17,15 +17,15 @@ static NavigationURLLoaderFactory* g_factory = nullptr;
std::unique_ptr<NavigationURLLoader> NavigationURLLoader::Create(
BrowserContext* browser_context,
std::unique_ptr<NavigationRequestInfo> request_info,
- ServiceWorkerNavigationHandle* service_worker_handle,
+ ServiceWorkerContextWrapper* service_worker_context_wrapper,
NavigationURLLoaderDelegate* delegate) {
if (g_factory) {
return g_factory->CreateLoader(browser_context, std::move(request_info),
- service_worker_handle, delegate);
+ service_worker_context_wrapper, delegate);
}
return std::unique_ptr<NavigationURLLoader>(
new NavigationURLLoaderImpl(browser_context, std::move(request_info),
- service_worker_handle, delegate));
+ service_worker_context_wrapper, delegate));
}
void NavigationURLLoader::SetFactoryForTesting(
diff --git a/chromium/content/browser/loader/navigation_url_loader.h b/chromium/content/browser/loader/navigation_url_loader.h
index f7d3280f9b4..632c84de517 100644
--- a/chromium/content/browser/loader/navigation_url_loader.h
+++ b/chromium/content/browser/loader/navigation_url_loader.h
@@ -15,7 +15,7 @@ namespace content {
class BrowserContext;
class NavigationURLLoaderDelegate;
class NavigationURLLoaderFactory;
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerContextWrapper;
struct CommonNavigationParams;
struct NavigationRequestInfo;
@@ -36,7 +36,7 @@ class CONTENT_EXPORT NavigationURLLoader {
static std::unique_ptr<NavigationURLLoader> Create(
BrowserContext* browser_context,
std::unique_ptr<NavigationRequestInfo> request_info,
- ServiceWorkerNavigationHandle* service_worker_handle,
+ ServiceWorkerContextWrapper* service_worker_context_wrapper,
NavigationURLLoaderDelegate* delegate);
// For testing purposes; sets the factory for use in testing.
diff --git a/chromium/content/browser/loader/navigation_url_loader_delegate.h b/chromium/content/browser/loader/navigation_url_loader_delegate.h
index 6f6cf1db2fb..abfe074f667 100644
--- a/chromium/content/browser/loader/navigation_url_loader_delegate.h
+++ b/chromium/content/browser/loader/navigation_url_loader_delegate.h
@@ -49,6 +49,9 @@ class CONTENT_EXPORT NavigationURLLoaderDelegate {
// until after the renderer was initialized.
virtual void OnRequestStarted(base::TimeTicks timestamp) = 0;
+ // Called when a ServiceWorker was found for the navigation.
+ virtual void OnServiceWorkerEncountered() = 0;
+
protected:
NavigationURLLoaderDelegate() {}
virtual ~NavigationURLLoaderDelegate() {}
diff --git a/chromium/content/browser/loader/navigation_url_loader_factory.h b/chromium/content/browser/loader/navigation_url_loader_factory.h
index df7ae0c0cb2..f68815179b2 100644
--- a/chromium/content/browser/loader/navigation_url_loader_factory.h
+++ b/chromium/content/browser/loader/navigation_url_loader_factory.h
@@ -19,7 +19,7 @@ class NavigationURLLoaderFactory {
virtual std::unique_ptr<NavigationURLLoader> CreateLoader(
BrowserContext* browser_context,
std::unique_ptr<NavigationRequestInfo> request_info,
- ServiceWorkerNavigationHandle* service_worker_handle,
+ ServiceWorkerContextWrapper* service_worker_context_wrapper,
NavigationURLLoaderDelegate* delegate) = 0;
protected:
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index bd0199c99e2..656fa90eb79 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -12,7 +12,6 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/navigation_url_loader_impl_core.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_data.h"
@@ -23,7 +22,7 @@ namespace content {
NavigationURLLoaderImpl::NavigationURLLoaderImpl(
BrowserContext* browser_context,
std::unique_ptr<NavigationRequestInfo> request_info,
- ServiceWorkerNavigationHandle* service_worker_handle,
+ ServiceWorkerContextWrapper* service_worker_context_wrapper,
NavigationURLLoaderDelegate* delegate)
: delegate_(delegate), weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -38,13 +37,11 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
"navigation", "Navigation timeToResponseStarted", core_,
request_info->common_params.navigation_start.ToInternalValue(),
"FrameTreeNode id", request_info->frame_tree_node_id);
- ServiceWorkerNavigationHandleCore* service_worker_handle_core =
- service_worker_handle ? service_worker_handle->core() : nullptr;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&NavigationURLLoaderImplCore::Start, base::Unretained(core_),
browser_context->GetResourceContext(),
- service_worker_handle_core, base::Passed(&request_info)));
+ service_worker_context_wrapper, base::Passed(&request_info)));
}
NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
@@ -103,4 +100,10 @@ void NavigationURLLoaderImpl::NotifyRequestStarted(base::TimeTicks timestamp) {
delegate_->OnRequestStarted(timestamp);
}
+void NavigationURLLoaderImpl::NotifyServiceWorkerEncountered() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ delegate_->OnServiceWorkerEncountered();
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index d3d2d38e713..000e7f96b0b 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -21,17 +21,18 @@ namespace content {
class NavigationURLLoaderImplCore;
class NavigationData;
-class ServiceWorkerNavigationHandle;
+class ServiceWorkerContextWrapper;
class StreamHandle;
struct ResourceResponse;
class NavigationURLLoaderImpl : public NavigationURLLoader {
public:
// The caller is responsible for ensuring that |delegate| outlives the loader.
- NavigationURLLoaderImpl(BrowserContext* browser_context,
- std::unique_ptr<NavigationRequestInfo> request_info,
- ServiceWorkerNavigationHandle* service_worker_handle,
- NavigationURLLoaderDelegate* delegate);
+ NavigationURLLoaderImpl(
+ BrowserContext* browser_context,
+ std::unique_ptr<NavigationRequestInfo> request_info,
+ ServiceWorkerContextWrapper* service_worker_context_wrapper,
+ NavigationURLLoaderDelegate* delegate);
~NavigationURLLoaderImpl() override;
// NavigationURLLoader implementation.
@@ -57,6 +58,9 @@ class NavigationURLLoaderImpl : public NavigationURLLoader {
// potential first network request is about to be made.
void NotifyRequestStarted(base::TimeTicks timestamp);
+ // Notifies the delegate that a ServiceWorker was found for this navigation.
+ void NotifyServiceWorkerEncountered();
+
NavigationURLLoaderDelegate* delegate_;
// |core_| is deleted on the IO thread in a subsequent task when the
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
index c7a215d0dd8..9ff2adaa787 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
@@ -10,7 +10,8 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_resource_handler.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_registration.h"
#include "content/common/navigation_params.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_data.h"
@@ -24,7 +25,9 @@ namespace content {
NavigationURLLoaderImplCore::NavigationURLLoaderImplCore(
const base::WeakPtr<NavigationURLLoaderImpl>& loader)
: loader_(loader),
- resource_handler_(nullptr) {
+ resource_handler_(nullptr),
+ resource_context_(nullptr),
+ factory_(this) {
// This object is created on the UI thread but otherwise is accessed and
// deleted on the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -39,7 +42,7 @@ NavigationURLLoaderImplCore::~NavigationURLLoaderImplCore() {
void NavigationURLLoaderImplCore::Start(
ResourceContext* resource_context,
- ServiceWorkerNavigationHandleCore* service_worker_handle_core,
+ ServiceWorkerContextWrapper* service_worker_context_wrapper,
std::unique_ptr<NavigationRequestInfo> request_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -47,11 +50,22 @@ void NavigationURLLoaderImplCore::Start(
BrowserThread::UI, FROM_HERE,
base::Bind(&NavigationURLLoaderImpl::NotifyRequestStarted, loader_,
base::TimeTicks::Now()));
-
- // The ResourceDispatcherHostImpl can be null in unit tests.
- if (ResourceDispatcherHostImpl::Get()) {
+ request_info_ = std::move(request_info);
+ resource_context_ = resource_context;
+
+ // Check if there is a ServiceWorker registered for this navigation if
+ // ServiceWorkers are allowed for this navigation. Otherwise start the
+ // request right away.
+ // ServiceWorkerContextWrapper can be null in tests.
+ if (!request_info_->begin_params.skip_service_worker &&
+ service_worker_context_wrapper) {
+ service_worker_context_wrapper->FindReadyRegistrationForDocument(
+ request_info_->common_params.url,
+ base::Bind(&NavigationURLLoaderImplCore::OnServiceWorkerChecksPerformed,
+ factory_.GetWeakPtr()));
+ } else {
ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
- resource_context, *request_info, this, service_worker_handle_core);
+ resource_context_, *request_info_, this);
}
}
@@ -132,4 +146,29 @@ void NavigationURLLoaderImplCore::NotifyRequestFailed(bool in_cache,
in_cache, net_error));
}
+void NavigationURLLoaderImplCore::OnServiceWorkerChecksPerformed(
+ ServiceWorkerStatusCode status,
+ const scoped_refptr<ServiceWorkerRegistration>& registration) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // If the navigation has a ServiceWorker, bail out immediately.
+ // TODO(clamy): only bail out when the ServiceWorker has a Fetch event
+ // handler.
+ if (status == SERVICE_WORKER_OK) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&NavigationURLLoaderImpl::NotifyServiceWorkerEncountered,
+ loader_));
+ return;
+ }
+
+ // Otherwise, start the navigation in the network stack.
+
+ // The ResourceDispatcherHostImpl can be null in unit tests.
+ if (!ResourceDispatcherHostImpl::Get())
+ return;
+
+ ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
+ resource_context_, *request_info_, this);
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.h b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
index 46c46c20755..1a7a152c1dd 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/loader/navigation_url_loader_impl.h"
+#include "content/common/service_worker/service_worker_status_code.h"
namespace net {
class URLRequest;
@@ -24,7 +25,8 @@ class NavigationData;
class ResourceContext;
class ResourceHandler;
class ResourceRequestBody;
-class ServiceWorkerNavigationHandleCore;
+class ServiceWorkerContextWrapper;
+class ServiceWorkerRegistration;
class StreamHandle;
struct ResourceResponse;
@@ -42,7 +44,7 @@ class NavigationURLLoaderImplCore {
// Starts the request.
void Start(ResourceContext* resource_context,
- ServiceWorkerNavigationHandleCore* service_worker_handle_core,
+ ServiceWorkerContextWrapper* service_worker_context_wrapper,
std::unique_ptr<NavigationRequestInfo> request_info);
// Follows the current pending redirect.
@@ -68,8 +70,18 @@ class NavigationURLLoaderImplCore {
void NotifyRequestFailed(bool in_cache, int net_error);
private:
+ // Called when done checking whether the navigation has a ServiceWorker
+ // registered for it.
+ void OnServiceWorkerChecksPerformed(
+ ServiceWorkerStatusCode status,
+ const scoped_refptr<ServiceWorkerRegistration>& registration);
+
base::WeakPtr<NavigationURLLoaderImpl> loader_;
NavigationResourceHandler* resource_handler_;
+ std::unique_ptr<NavigationRequestInfo> request_info_;
+ ResourceContext* resource_context_;
+
+ base::WeakPtrFactory<NavigationURLLoaderImplCore> factory_;
DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderImplCore);
};
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index 8f4a9b9c10f..66725370591 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -13,6 +13,7 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_url_loader_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader_delegate_impl.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_context.h"
#include "content/browser/streams/stream_registry.h"
@@ -83,6 +84,7 @@ class NavigationURLLoaderTest : public testing::Test {
NavigationURLLoaderTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
browser_context_(new TestBrowserContext) {
+ host_.SetLoaderDelegate(&loader_delegate_);
BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
base::RunLoop().RunUntilIdle();
net::URLRequestContext* request_context =
@@ -110,8 +112,7 @@ 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, -1,
- scoped_refptr<ResourceRequestBody>()));
+ url::Origin(url), true, false, -1));
return NavigationURLLoader::Create(
browser_context_.get(), std::move(request_info), nullptr, delegate);
@@ -136,6 +137,7 @@ class NavigationURLLoaderTest : public testing::Test {
TestBrowserThreadBundle thread_bundle_;
net::URLRequestJobFactoryImpl job_factory_;
std::unique_ptr<TestBrowserContext> browser_context_;
+ LoaderDelegateImpl loader_delegate_;
ResourceDispatcherHostImpl host_;
};
diff --git a/chromium/content/browser/loader/power_save_block_resource_throttle.cc b/chromium/content/browser/loader/power_save_block_resource_throttle.cc
index 76afe12de13..1af02c5c51a 100644
--- a/chromium/content/browser/loader/power_save_block_resource_throttle.cc
+++ b/chromium/content/browser/loader/power_save_block_resource_throttle.cc
@@ -4,7 +4,7 @@
#include "content/browser/loader/power_save_block_resource_throttle.h"
-#include "content/public/browser/power_save_blocker.h"
+#include "device/power_save_blocker/power_save_blocker.h"
namespace content {
@@ -15,8 +15,12 @@ const int kPowerSaveBlockDelaySeconds = 30;
} // namespace
PowerSaveBlockResourceThrottle::PowerSaveBlockResourceThrottle(
- const std::string& host)
- : host_(host) {}
+ const std::string& host,
+ scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner)
+ : host_(host),
+ ui_task_runner_(ui_task_runner),
+ blocking_task_runner_(blocking_task_runner) {}
PowerSaveBlockResourceThrottle::~PowerSaveBlockResourceThrottle() {
}
@@ -40,9 +44,10 @@ const char* PowerSaveBlockResourceThrottle::GetNameForLogging() const {
}
void PowerSaveBlockResourceThrottle::ActivatePowerSaveBlocker() {
- power_save_blocker_ = PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
- PowerSaveBlocker::kReasonOther, "Uploading data to " + host_);
+ power_save_blocker_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ device::PowerSaveBlocker::kReasonOther, "Uploading data to " + host_,
+ ui_task_runner_, blocking_task_runner_));
}
} // namespace content
diff --git a/chromium/content/browser/loader/power_save_block_resource_throttle.h b/chromium/content/browser/loader/power_save_block_resource_throttle.h
index 3f6f1d363d7..67b8a9f6953 100644
--- a/chromium/content/browser/loader/power_save_block_resource_throttle.h
+++ b/chromium/content/browser/loader/power_save_block_resource_throttle.h
@@ -10,17 +10,25 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
#include "base/timer/timer.h"
#include "content/public/browser/resource_throttle.h"
-namespace content {
-
+namespace device {
class PowerSaveBlocker;
+} // namespace device
+
+namespace content {
// This ResourceThrottle blocks power save until large upload request finishes.
class PowerSaveBlockResourceThrottle : public ResourceThrottle {
public:
- explicit PowerSaveBlockResourceThrottle(const std::string& host);
+ PowerSaveBlockResourceThrottle(
+ const std::string& host,
+ scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner);
~PowerSaveBlockResourceThrottle() override;
// ResourceThrottle overrides:
@@ -33,7 +41,9 @@ class PowerSaveBlockResourceThrottle : public ResourceThrottle {
const std::string host_;
base::OneShotTimer timer_;
- std::unique_ptr<PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
+ scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner_;
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockResourceThrottle);
};
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
index 3a3a13d5550..0816b5be825 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -32,6 +32,7 @@
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_network_delegate.h"
#include "net/base/net_errors.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
@@ -82,7 +83,7 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest,
ShellAddedObserver new_shell_observer;
// Create dynamic popup.
- if (!ExecuteScript(shell()->web_contents(), "OpenPopup();"))
+ if (!ExecuteScript(shell(), "OpenPopup();"))
return false;
Shell* new_shell = new_shell_observer.GetShell();
@@ -189,8 +190,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, SyncXMLHttpRequest) {
// Let's check the XMLHttpRequest ran successfully.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(DidSyncRequestSucceed());",
+ shell(), "window.domAutomationController.send(DidSyncRequestSucceed());",
&success));
EXPECT_TRUE(success);
}
@@ -206,9 +206,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// Let's check the XMLHttpRequest ran successfully.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(DidSucceed());",
- &success));
+ shell(), "window.domAutomationController.send(DidSucceed());", &success));
EXPECT_TRUE(success);
}
@@ -405,10 +403,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
std::string redirect_script = "window.location='" +
test_url.possibly_invalid_spec() + "';" +
"window.domAutomationController.send(true);";
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- redirect_script,
- &success));
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(shell(), redirect_script, &success));
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
}
@@ -755,4 +750,249 @@ IN_PROC_BROWSER_TEST_F(LoFiResourceDispatcherHostBrowserTest,
CheckResourcesRequested(false);
}
+namespace {
+
+struct RequestDataForDelegate {
+ const GURL url;
+ const GURL first_party;
+ const url::Origin initiator;
+
+ RequestDataForDelegate(const GURL& url,
+ const GURL& first_party,
+ const url::Origin initiator)
+ : url(url), first_party(first_party), initiator(initiator) {}
+};
+
+// Captures calls to 'RequestBeginning' and records the URL, first-party for
+// cookies, and initiator.
+class RequestDataResourceDispatcherHostDelegate
+ : public ResourceDispatcherHostDelegate {
+ public:
+ RequestDataResourceDispatcherHostDelegate() {}
+
+ const ScopedVector<RequestDataForDelegate>& data() { return requests_; }
+
+ // ResourceDispatcherHostDelegate implementation:
+ void RequestBeginning(net::URLRequest* request,
+ ResourceContext* resource_context,
+ AppCacheService* appcache_service,
+ ResourceType resource_type,
+ ScopedVector<ResourceThrottle>* throttles) override {
+ requests_.push_back(new RequestDataForDelegate(
+ request->url(), request->first_party_for_cookies(),
+ request->initiator()));
+ }
+
+ void SetDelegate() { ResourceDispatcherHost::Get()->SetDelegate(this); }
+
+ private:
+ ScopedVector<RequestDataForDelegate> requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(RequestDataResourceDispatcherHostDelegate);
+};
+
+const GURL kURLWithUniqueOrigin("data:,");
+
+} // namespace
+
+class RequestDataResourceDispatcherHostBrowserTest : public ContentBrowserTest {
+ public:
+ ~RequestDataResourceDispatcherHostBrowserTest() override {}
+
+ protected:
+ void SetUpOnMainThread() override {
+ ContentBrowserTest::SetUpOnMainThread();
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ delegate_.reset(new RequestDataResourceDispatcherHostDelegate());
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&RequestDataResourceDispatcherHostDelegate::SetDelegate,
+ base::Unretained(delegate_.get())));
+ }
+
+ protected:
+ std::unique_ptr<RequestDataResourceDispatcherHostDelegate> delegate_;
+};
+
+IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest, Basic) {
+ GURL top_url(embedded_test_server()->GetURL("/simple_page.html"));
+ url::Origin top_origin(top_url);
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+
+ EXPECT_EQ(1u, delegate_->data().size());
+
+ // User-initiated top-level navigations have a first-party and initiator that
+ // matches the URL to which they navigate.
+ EXPECT_EQ(top_url, delegate_->data()[0]->url);
+ EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[0]->initiator);
+}
+
+IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
+ SameOriginNested) {
+ GURL top_url(embedded_test_server()->GetURL("/page_with_iframe.html"));
+ GURL image_url(embedded_test_server()->GetURL("/image.jpg"));
+ GURL nested_url(embedded_test_server()->GetURL("/title1.html"));
+ url::Origin top_origin(top_url);
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+
+ EXPECT_EQ(3u, delegate_->data().size());
+
+ // User-initiated top-level navigations have a first-party and initiator that
+ // matches the URL to which they navigate.
+ EXPECT_EQ(top_url, delegate_->data()[0]->url);
+ EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[0]->initiator);
+
+ // Subresource requests have a first-party and initiator that matches the
+ // document in which they're embedded.
+ EXPECT_EQ(image_url, delegate_->data()[1]->url);
+ EXPECT_EQ(top_url, delegate_->data()[1]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[1]->initiator);
+
+ // Same-origin nested frames have a first-party and initiator that matches
+ // the document in which they're embedded.
+ EXPECT_EQ(nested_url, delegate_->data()[2]->url);
+ EXPECT_EQ(top_url, delegate_->data()[2]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[2]->initiator);
+}
+
+IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
+ SameOriginAuxiliary) {
+ GURL top_url(embedded_test_server()->GetURL("/simple_links.html"));
+ GURL auxiliary_url(embedded_test_server()->GetURL("/title2.html"));
+ url::Origin top_origin(top_url);
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+
+ ShellAddedObserver new_shell_observer;
+ bool success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ shell(),
+ "window.domAutomationController.send(clickSameSiteNewWindowLink());",
+ &success));
+ EXPECT_TRUE(success);
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+
+ EXPECT_EQ(2u, delegate_->data().size());
+
+ // User-initiated top-level navigations have a first-party and initiator that
+ // matches the URL to which they navigate, even if they fail to load.
+ EXPECT_EQ(top_url, delegate_->data()[0]->url);
+ EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[0]->initiator);
+
+ // Auxiliary navigations have a first-party that matches the URL to which they
+ // navigate, and an initiator that matches the document that triggered them.
+ EXPECT_EQ(auxiliary_url, delegate_->data()[1]->url);
+ EXPECT_EQ(auxiliary_url, delegate_->data()[1]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[1]->initiator);
+}
+
+IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
+ CrossOriginAuxiliary) {
+ GURL top_url(embedded_test_server()->GetURL("/simple_links.html"));
+ GURL auxiliary_url(embedded_test_server()->GetURL("foo.com", "/title2.html"));
+ url::Origin top_origin(top_url);
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+
+ const char kReplacePortNumber[] =
+ "window.domAutomationController.send(setPortNumber(%d));";
+ uint16_t port_number = embedded_test_server()->port();
+ bool success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ shell(), base::StringPrintf(kReplacePortNumber, port_number), &success));
+ success = false;
+
+ ShellAddedObserver new_shell_observer;
+ success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ shell(),
+ "window.domAutomationController.send(clickCrossSiteNewWindowLink());",
+ &success));
+ EXPECT_TRUE(success);
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+
+ EXPECT_EQ(2u, delegate_->data().size());
+
+ // User-initiated top-level navigations have a first-party and initiator that
+ // matches the URL to which they navigate, even if they fail to load.
+ EXPECT_EQ(top_url, delegate_->data()[0]->url);
+ EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[0]->initiator);
+
+ // Auxiliary navigations have a first-party that matches the URL to which they
+ // navigate, and an initiator that matches the document that triggered them.
+ EXPECT_EQ(auxiliary_url, delegate_->data()[1]->url);
+ EXPECT_EQ(auxiliary_url, delegate_->data()[1]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[1]->initiator);
+}
+
+IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
+ FailedNavigation) {
+ // Navigating to this URL will fail, as we haven't taught the host resolver
+ // about 'a.com'.
+ GURL top_url(embedded_test_server()->GetURL("a.com", "/simple_page.html"));
+ url::Origin top_origin(top_url);
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+
+ EXPECT_EQ(1u, delegate_->data().size());
+
+ // User-initiated top-level navigations have a first-party and initiator that
+ // matches the URL to which they navigate, even if they fail to load.
+ EXPECT_EQ(top_url, delegate_->data()[0]->url);
+ EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[0]->initiator);
+}
+
+IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
+ CrossOriginNested) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ GURL top_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ GURL top_js_url(
+ embedded_test_server()->GetURL("a.com", "/tree_parser_util.js"));
+ GURL nested_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b()"));
+ GURL nested_js_url(
+ embedded_test_server()->GetURL("b.com", "/tree_parser_util.js"));
+ url::Origin top_origin(top_url);
+ url::Origin nested_origin(nested_url);
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+
+ EXPECT_EQ(4u, delegate_->data().size());
+
+ // User-initiated top-level navigations have a first-party and initiator that
+ // matches the URL to which they navigate.
+ EXPECT_EQ(top_url, delegate_->data()[0]->url);
+ EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[0]->initiator);
+
+ EXPECT_EQ(top_js_url, delegate_->data()[1]->url);
+ EXPECT_EQ(top_url, delegate_->data()[1]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[1]->initiator);
+
+ // Cross-origin frames have a first-party and initiator that matches the URL
+ // in which they're embedded.
+ EXPECT_EQ(nested_url, delegate_->data()[2]->url);
+ EXPECT_EQ(top_url, delegate_->data()[2]->first_party);
+ EXPECT_EQ(top_origin, delegate_->data()[2]->initiator);
+
+ // Cross-origin subresource requests have a unique first-party, and an
+ // initiator that matches the document in which they're embedded.
+ EXPECT_EQ(nested_js_url, delegate_->data()[3]->url);
+ EXPECT_EQ(kURLWithUniqueOrigin, delegate_->data()[3]->first_party);
+ EXPECT_EQ(nested_origin, delegate_->data()[3]->initiator);
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index cb64dc8880b..377350d1abc 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -49,6 +49,7 @@
#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/loader_delegate.h"
#include "content/browser/loader/mime_type_resource_handler.h"
#include "content/browser/loader/navigation_resource_handler.h"
#include "content/browser/loader/navigation_resource_throttle.h"
@@ -61,8 +62,6 @@
#include "content/browser/loader/sync_resource_handler.h"
#include "content/browser/loader/throttling_resource_handler.h"
#include "content/browser/loader/upload_data_stream_builder.h"
-#include "content/browser/renderer_host/render_view_host_delegate.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
#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"
@@ -70,20 +69,17 @@
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_context.h"
#include "content/browser/streams/stream_registry.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/appcache_interfaces.h"
#include "content/common/navigation_params.h"
#include "content/common/net/url_request_service_worker_data.h"
#include "content/common/resource_messages.h"
#include "content/common/resource_request.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/common/resource_request_completion_status.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/download_manager.h"
-#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
@@ -91,7 +87,6 @@
#include "content/public/browser/resource_throttle.h"
#include "content/public/browser/stream_handle.h"
#include "content/public/browser/stream_info.h"
-#include "content/public/browser/user_metrics.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -109,6 +104,7 @@
#include "net/cookies/cookie_monster.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
+#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
@@ -327,17 +323,18 @@ bool ShouldServiceRequest(int process_type,
// Check if the renderer is permitted to upload the requested files.
if (request_data.request_body.get()) {
- const std::vector<ResourceRequestBody::Element>* uploads =
+ const std::vector<ResourceRequestBodyImpl::Element>* uploads =
request_data.request_body->elements();
- std::vector<ResourceRequestBody::Element>::const_iterator iter;
+ std::vector<ResourceRequestBodyImpl::Element>::const_iterator iter;
for (iter = uploads->begin(); iter != uploads->end(); ++iter) {
- if (iter->type() == ResourceRequestBody::Element::TYPE_FILE &&
+ if (iter->type() == ResourceRequestBodyImpl::Element::TYPE_FILE &&
!policy->CanReadFile(child_id, iter->path())) {
NOTREACHED() << "Denied unauthorized upload of "
<< iter->path().value();
return false;
}
- if (iter->type() == ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM) {
+ if (iter->type() ==
+ ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM) {
storage::FileSystemURL url =
filter->file_system_context()->CrackURL(iter->filesystem_url());
if (!policy->CanReadFileSystemFile(child_id, url)) {
@@ -364,30 +361,6 @@ int GetCertID(CertStore* cert_store, net::URLRequest* request, int child_id) {
return 0;
}
-void NotifyRedirectOnUI(int render_process_id,
- int render_frame_host,
- std::unique_ptr<ResourceRedirectDetails> details) {
- RenderFrameHostImpl* host =
- RenderFrameHostImpl::FromID(render_process_id, render_frame_host);
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host));
- if (!web_contents)
- return;
- web_contents->DidGetRedirectForResourceRequest(host, *details.get());
-}
-
-void NotifyResponseOnUI(int render_process_id,
- int render_frame_host,
- std::unique_ptr<ResourceRequestDetails> details) {
- RenderFrameHostImpl* host =
- RenderFrameHostImpl::FromID(render_process_id, render_frame_host);
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host));
- if (!web_contents)
- return;
- web_contents->DidGetResourceResponseStart(*details.get());
-}
-
bool IsValidatedSCT(
const net::SignedCertificateTimestampAndStatus& sct_status) {
return sct_status.status == net::ct::SCT_STATUS_OK;
@@ -401,12 +374,12 @@ storage::BlobStorageContext* GetBlobStorageContext(
}
void AttachRequestBodyBlobDataHandles(
- ResourceRequestBody* body,
+ ResourceRequestBodyImpl* body,
storage::BlobStorageContext* blob_context) {
DCHECK(blob_context);
for (size_t i = 0; i < body->elements()->size(); ++i) {
- const ResourceRequestBody::Element& element = (*body->elements())[i];
- if (element.type() != ResourceRequestBody::Element::TYPE_BLOB)
+ const ResourceRequestBodyImpl::Element& element = (*body->elements())[i];
+ if (element.type() != ResourceRequestBodyImpl::Element::TYPE_BLOB)
continue;
std::unique_ptr<storage::BlobDataHandle> handle =
blob_context->GetBlobDataFromUUID(element.blob_uuid());
@@ -548,8 +521,9 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl()
max_num_in_flight_requests_ * kMaxRequestsPerProcessRatio)),
max_outstanding_requests_cost_per_process_(
kMaxOutstandingRequestsCostPerProcess),
- filter_(NULL),
- delegate_(NULL),
+ filter_(nullptr),
+ delegate_(nullptr),
+ loader_delegate_(nullptr),
allow_cross_origin_auth_prompt_(false),
cert_store_for_testing_(nullptr) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -637,24 +611,11 @@ void ResourceDispatcherHostImpl::SetAllowCrossOriginAuthPrompt(bool value) {
allow_cross_origin_auth_prompt_ = value;
}
-void ResourceDispatcherHostImpl::AddResourceContext(ResourceContext* context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- active_resource_contexts_.insert(context);
-}
-
-void ResourceDispatcherHostImpl::RemoveResourceContext(
- ResourceContext* context) {
- CHECK(ContainsKey(active_resource_contexts_, context));
- active_resource_contexts_.erase(context);
-}
-
void ResourceDispatcherHostImpl::CancelRequestsForContext(
ResourceContext* context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(context);
- CHECK(ContainsKey(active_resource_contexts_, context));
-
// Note that request cancellation has side effects. Therefore, we gather all
// the requests to cancel first, and then we start cancelling. We assert at
// the end that there are no more to cancel since the context is about to go
@@ -725,21 +686,6 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
async_revalidation_manager_->CancelAsyncRevalidationsForResourceContext(
context);
}
-
- // Validate that no more requests for this context were added.
- for (const auto& loader : pending_loaders_) {
- // http://crbug.com/90971
- CHECK_NE(loader.second->GetRequestInfo()->GetContext(), context);
- }
-
- for (const auto& blocked_loaders : blocked_loaders_map_) {
- BlockedLoadersList* loaders = blocked_loaders.second.get();
- if (!loaders->empty()) {
- ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo();
- // http://crbug.com/90971
- CHECK_NE(info->GetContext(), context);
- }
- }
}
DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
@@ -747,7 +693,7 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
const Referrer& referrer,
bool is_content_initiated,
ResourceContext* context,
- int child_id,
+ int render_process_id,
int render_view_route_id,
int render_frame_route_id,
bool do_not_prompt_for_login) {
@@ -755,13 +701,6 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
return DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
const GURL& url = request->original_url();
-
- // http://crbug.com/90971
- char url_buf[128];
- base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf));
- base::debug::Alias(url_buf);
- CHECK(ContainsKey(active_resource_contexts_, context));
-
SetReferrerForRequest(request.get(), referrer);
// We treat a download as a main frame load, and thus update the policy URL on
@@ -775,7 +714,7 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
// Check if the renderer is permitted to request the requested URL.
if (!ChildProcessSecurityPolicyImpl::GetInstance()->
- CanRequestURL(child_id, url)) {
+ CanRequestURL(render_process_id, url)) {
DVLOG(1) << "Denied unauthorized download request for "
<< url.possibly_invalid_spec();
return DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST;
@@ -791,7 +730,7 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
}
ResourceRequestInfoImpl* extra_info =
- CreateRequestInfo(child_id, render_view_route_id,
+ CreateRequestInfo(render_process_id, render_view_route_id,
render_frame_route_id, true, context);
extra_info->set_do_not_prompt_for_login(do_not_prompt_for_login);
extra_info->AssociateWithRequest(request.get()); // Request takes ownership.
@@ -847,8 +786,8 @@ ResourceDispatcherHostImpl::CreateResourceHandlerForDownload(
ScopedVector<ResourceThrottle> throttles;
delegate_->DownloadStarting(
request, request_info->GetContext(), request_info->GetChildID(),
- request_info->GetRouteID(), request_info->GetRequestID(),
- is_content_initiated, must_download, &throttles);
+ request_info->GetRouteID(), is_content_initiated, must_download,
+ &throttles);
if (!throttles.empty()) {
handler.reset(new ThrottlingResourceHandler(std::move(handler), request,
std::move(throttles)));
@@ -923,7 +862,8 @@ bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader,
return delegate_->HandleExternalProtocol(
url, info->GetChildID(), info->GetWebContentsGetterForRequest(),
- info->IsMainFrame(), info->GetPageTransition(), info->HasUserGesture());
+ info->IsMainFrame(), info->GetPageTransition(), info->HasUserGesture(),
+ info->GetContext());
}
void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) {
@@ -977,11 +917,8 @@ void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader,
loader->request(),
GetCertID(GetCertStore(), loader->request(), info->GetChildID()),
new_url));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &NotifyRedirectOnUI,
- render_process_id, render_frame_host, base::Passed(&detail)));
+ loader_delegate_->DidGetRedirectForResourceRequest(
+ render_process_id, render_frame_host, std::move(detail));
}
void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
@@ -1015,11 +952,8 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
// Notify the observers on the UI thread.
std::unique_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails(
request, GetCertID(GetCertStore(), request, info->GetChildID())));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &NotifyResponseOnUI,
- render_process_id, render_frame_host, base::Passed(&detail)));
+ loader_delegate_->DidGetResourceResponseStart(
+ render_process_id, render_frame_host, std::move(detail));
}
void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
@@ -1141,6 +1075,12 @@ void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
RemovePendingRequest(info->GetChildID(), info->GetRequestID());
}
+std::unique_ptr<net::ClientCertStore>
+ ResourceDispatcherHostImpl::CreateClientCertStore(ResourceLoader* loader) {
+ return delegate_->CreateClientCertStore(
+ loader->GetRequestInfo()->GetContext());
+}
+
void ResourceDispatcherHostImpl::OnInit() {
scheduler_.reset(new ResourceScheduler);
}
@@ -1426,8 +1366,6 @@ void ResourceDispatcherHostImpl::BeginRequest(
net::URLRequestContext* request_context = NULL;
filter_->GetContexts(request_data.resource_type, request_data.origin_pid,
&resource_context, &request_context);
- // http://crbug.com/90971
- CHECK(ContainsKey(active_resource_contexts_, resource_context));
// Parse the headers before calling ShouldServiceRequest, so that they are
// available to be validated.
@@ -1581,7 +1519,8 @@ void ResourceDispatcherHostImpl::BeginRequest(
IsUsingLoFi(request_data.lofi_state, delegate_, *new_request,
resource_context,
request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME),
- support_async_revalidation ? request_data.headers : std::string());
+ support_async_revalidation ? request_data.headers : std::string(),
+ request_data.request_body, request_data.initiated_in_secure_context);
// Request takes ownership.
extra_info->AssociateWithRequest(new_request.get());
@@ -1596,12 +1535,12 @@ void ResourceDispatcherHostImpl::BeginRequest(
// Initialize the service worker handler for the request. We don't use
// ServiceWorker for synchronous loads to avoid renderer deadlocks.
- const bool should_skip_service_worker =
- request_data.skip_service_worker || is_sync_load;
+ const SkipServiceWorker should_skip_service_worker =
+ is_sync_load ? SkipServiceWorker::ALL : request_data.skip_service_worker;
ServiceWorkerRequestHandler::InitializeHandler(
new_request.get(), filter_->service_worker_context(), blob_context,
child_id, request_data.service_worker_provider_id,
- should_skip_service_worker,
+ should_skip_service_worker != SkipServiceWorker::NONE,
request_data.fetch_request_mode, request_data.fetch_credentials_mode,
request_data.fetch_redirect_mode, request_data.resource_type,
request_data.fetch_request_context_type, request_data.fetch_frame_type,
@@ -1612,11 +1551,11 @@ void ResourceDispatcherHostImpl::BeginRequest(
ForeignFetchRequestHandler::InitializeHandler(
new_request.get(), filter_->service_worker_context(), blob_context,
child_id, request_data.service_worker_provider_id,
- should_skip_service_worker,
- request_data.fetch_request_mode, request_data.fetch_credentials_mode,
- request_data.fetch_redirect_mode, request_data.resource_type,
- request_data.fetch_request_context_type, request_data.fetch_frame_type,
- request_data.request_body);
+ should_skip_service_worker, request_data.fetch_request_mode,
+ request_data.fetch_credentials_mode, request_data.fetch_redirect_mode,
+ request_data.resource_type, request_data.fetch_request_context_type,
+ request_data.fetch_frame_type, request_data.request_body,
+ request_data.initiated_in_secure_context);
}
// Have the appcache associate its extra info with the request.
@@ -1745,8 +1684,10 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
if (request->has_upload()) {
// Block power save while uploading data.
- throttles.push_back(
- new PowerSaveBlockResourceThrottle(request->url().host()));
+ throttles.push_back(new PowerSaveBlockResourceThrottle(
+ request->url().host(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
}
// TODO(ricea): Stop looking this up so much.
@@ -1878,7 +1819,9 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
false, // report_raw_headers
true, // is_async
false, // is_using_lofi
- std::string()); // original_headers
+ std::string(), // original_headers
+ nullptr, // body
+ false); // initiated_in_secure_context
}
void ResourceDispatcherHostImpl::OnRenderFrameDeleted(
@@ -1914,12 +1857,6 @@ void ResourceDispatcherHostImpl::BeginSaveFile(const GURL& url,
if (is_shutdown_)
return;
- // http://crbug.com/90971
- char url_buf[128];
- base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf));
- base::debug::Alias(url_buf);
- CHECK(ContainsKey(active_resource_contexts_, context));
-
request_id_--;
const net::URLRequestContext* request_context = context->GetRequestContext();
@@ -1948,9 +1885,22 @@ void ResourceDispatcherHostImpl::BeginSaveFile(const GURL& url,
render_frame_route_id, false, context);
extra_info->AssociateWithRequest(request.get()); // Request takes ownership.
- std::unique_ptr<ResourceHandler> handler(new SaveFileResourceHandler(
+ // Check if the renderer is permitted to request the requested URL.
+ using AuthorizationState = SaveFileResourceHandler::AuthorizationState;
+ AuthorizationState authorization_state = AuthorizationState::AUTHORIZED;
+ if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(child_id,
+ url)) {
+ DVLOG(1) << "Denying unauthorized save of " << url.possibly_invalid_spec();
+ authorization_state = AuthorizationState::NOT_AUTHORIZED;
+ // No need to return here (i.e. okay to begin processing the request below),
+ // because NOT_AUTHORIZED will cause the request to be cancelled. See also
+ // doc comments for AuthorizationState enum.
+ }
+
+ std::unique_ptr<SaveFileResourceHandler> handler(new SaveFileResourceHandler(
request.get(), save_item_id, save_package_id, child_id,
- render_frame_route_id, url, save_file_manager_.get()));
+ render_frame_route_id, url, save_file_manager_.get(),
+ authorization_state));
BeginRequestInternal(std::move(request), std::move(handler));
}
@@ -2182,8 +2132,7 @@ void ResourceDispatcherHostImpl::FinishedWithResourcesForRequest(
void ResourceDispatcherHostImpl::BeginNavigationRequest(
ResourceContext* resource_context,
const NavigationRequestInfo& info,
- NavigationURLLoaderImplCore* loader,
- ServiceWorkerNavigationHandleCore* service_worker_handle_core) {
+ NavigationURLLoaderImplCore* loader) {
// PlzNavigate: BeginNavigationRequest currently should only be used for the
// browser-side navigations project.
CHECK(IsBrowserSideNavigationEnabled());
@@ -2204,14 +2153,6 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
return;
}
- // Save the URL on the stack to help catch URLRequests which outlive their
- // URLRequestContexts. See https://crbug.com/90971
- char url_buf[128];
- base::strlcpy(
- url_buf, info.common_params.url.spec().c_str(), arraysize(url_buf));
- base::debug::Alias(url_buf);
- CHECK(ContainsKey(active_resource_contexts_, resource_context));
-
const net::URLRequestContext* request_context =
resource_context->GetRequestContext();
@@ -2252,15 +2193,14 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
GetChromeBlobStorageContextForResourceContext(resource_context));
// Resolve elements from request_body and prepare upload data.
- if (info.request_body.get()) {
- AttachRequestBodyBlobDataHandles(
- info.request_body.get(),
- blob_context);
+ ResourceRequestBodyImpl* body = info.common_params.post_data.get();
+ if (body) {
+ AttachRequestBodyBlobDataHandles(body, blob_context);
// TODO(davidben): The FileSystemContext is null here. In the case where
// another renderer requested this navigation, this should be the same
// FileSystemContext passed into ShouldServiceRequest.
new_request->set_upload(UploadDataStreamBuilder::Build(
- info.request_body.get(),
+ body,
blob_context,
nullptr, // file_system_context
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
@@ -2307,7 +2247,13 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// here.
// TODO(ricea): Make the feature work with stale-while-revalidate
// and clean this up.
- std::string()); // original_headers
+ std::string(), // original_headers
+ info.common_params.post_data,
+ // TODO(mek): Currently initiated_in_secure_context is only used for
+ // subresource requests, so it doesn't matter what value it gets here.
+ // If in the future this changes this should be updated to somehow get a
+ // meaningful value.
+ false); // initiated_in_secure_context
// Request takes ownership.
extra_info->AssociateWithRequest(new_request.get());
@@ -2319,14 +2265,6 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
blob_context->GetBlobDataFromPublicURL(new_request->url()));
}
- RequestContextFrameType frame_type =
- info.is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL
- : REQUEST_CONTEXT_FRAME_TYPE_NESTED;
- ServiceWorkerRequestHandler::InitializeForNavigation(
- new_request.get(), service_worker_handle_core, blob_context,
- info.begin_params.skip_service_worker, resource_type,
- info.begin_params.request_context_type, frame_type, info.request_body);
-
// TODO(davidben): Attach AppCacheInterceptor.
std::unique_ptr<ResourceHandler> handler(
@@ -2350,6 +2288,11 @@ void ResourceDispatcherHostImpl::EnableStaleWhileRevalidateForTesting() {
async_revalidation_manager_.reset(new AsyncRevalidationManager);
}
+void ResourceDispatcherHostImpl::SetLoaderDelegate(
+ LoaderDelegate* loader_delegate) {
+ loader_delegate_ = loader_delegate;
+}
+
// static
int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
net::URLRequest* request) {
@@ -2432,7 +2375,7 @@ void ResourceDispatcherHostImpl::StartLoading(
loader_ptr->StartRequest();
}
-void ResourceDispatcherHostImpl::OnUserGesture(WebContentsImpl* contents) {
+void ResourceDispatcherHostImpl::OnUserGesture() {
last_user_gesture_time_ = TimeTicks::Now();
}
@@ -2465,27 +2408,6 @@ bool ResourceDispatcherHostImpl::LoadInfoIsMoreInteresting(const LoadInfo& a,
return a.load_state.state > b.load_state.state;
}
-// static
-void ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread(
- std::unique_ptr<LoadInfoMap> info_map) {
- // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466285
- // is fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "466285 ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread"));
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- for (const auto& load_info : *info_map) {
- RenderViewHostImpl* view = RenderViewHostImpl::FromID(
- load_info.first.child_id, load_info.first.route_id);
- // The view could be gone at this point.
- if (view) {
- view->LoadStateChanged(load_info.second.url, load_info.second.load_state,
- load_info.second.upload_position,
- load_info.second.upload_size);
- }
- }
-}
-
std::unique_ptr<ResourceDispatcherHostImpl::LoadInfoMap>
ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() {
// Populate this map with load state changes, and then send them on to the UI
@@ -2525,10 +2447,12 @@ void ResourceDispatcherHostImpl::UpdateLoadInfo() {
return;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread,
- base::Passed(&info_map)));
+ for (const auto& load_info : *info_map) {
+ loader_delegate_->LoadStateChanged(
+ load_info.first.child_id, load_info.first.route_id,
+ load_info.second.url, load_info.second.load_state,
+ load_info.second.upload_position, load_info.second.upload_size);
+ }
}
void ResourceDispatcherHostImpl::BlockRequestsForRoute(
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 3d960faa85a..a7242ff35e9 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -16,7 +16,6 @@
#include <map>
#include <memory>
-#include <set>
#include <string>
#include <vector>
@@ -32,12 +31,7 @@
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/browser/loader/resource_scheduler.h"
#include "content/common/content_export.h"
-#include "content/common/resource_request_body.h"
-#include "content/public/browser/child_process_data.h"
-#include "content/public/browser/download_item.h"
-#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/global_request_id.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/resource_type.h"
@@ -65,6 +59,7 @@ class AppCacheService;
class AsyncRevalidationManager;
class CertStore;
class FrameTree;
+class LoaderDelegate;
class NavigationURLLoaderImplCore;
class RenderFrameHostImpl;
class ResourceContext;
@@ -74,7 +69,6 @@ class ResourceMessageFilter;
class ResourceRequestInfoImpl;
class SaveFileManager;
class ServiceWorkerNavigationHandleCore;
-class WebContentsImpl;
struct CommonNavigationParams;
struct DownloadSaveInfo;
struct NavigationRequestInfo;
@@ -135,12 +129,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// new requests). Cancels all pending requests.
void Shutdown();
- // Notify the ResourceDispatcherHostImpl of a new resource context.
- void AddResourceContext(ResourceContext* context);
-
- // Notify the ResourceDispatcherHostImpl of a resource context destruction.
- void RemoveResourceContext(ResourceContext* context);
-
// Force cancels any pending requests for the given |context|. This is
// necessary to ensure that before |context| goes away, all requests
// for it are dead.
@@ -155,7 +143,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
const Referrer& referrer,
bool is_content_initiated,
ResourceContext* context,
- int child_id,
+ int render_process_id,
int render_view_route_id,
int render_frame_route_id,
bool do_not_prompt_for_login);
@@ -176,7 +164,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Marks the request, with its current |response|, as "parked". This
// happens if a request is redirected cross-site and needs to be
- // resumed by a new render view.
+ // resumed by a new process.
void MarkAsTransferredNavigation(
const GlobalRequestID& id,
const scoped_refptr<ResourceResponse>& response);
@@ -185,7 +173,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// navigation was cancelled.
void CancelTransferringNavigation(const GlobalRequestID& id);
- // Resumes the request without transferring it to a new render view.
+ // Resumes the request without transferring it to a new process.
void ResumeDeferredNavigation(const GlobalRequestID& id);
// Returns the number of pending requests. This is designed for the unittests
@@ -227,7 +215,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Force cancels any pending requests for the given process.
void CancelRequestsForProcess(int child_id);
- void OnUserGesture(WebContentsImpl* contents);
+ void OnUserGesture();
// Retrieves a net::URLRequest. Must be called from the IO thread.
net::URLRequest* GetURLRequest(const GlobalRequestID& request_id);
@@ -268,8 +256,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Must be called after the ResourceRequestInfo has been created
// and associated with the request.
- // |id| should be |content::DownloadItem::kInvalidId| to request automatic
- // assignment. This is marked virtual so it can be overriden in testing.
+ // This is marked virtual so it can be overriden in testing.
virtual std::unique_ptr<ResourceHandler> CreateResourceHandlerForDownload(
net::URLRequest* request,
bool is_content_initiated,
@@ -308,16 +295,18 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// PlzNavigate: Begins a request for NavigationURLLoader. |loader| is the
// loader to attach to the leaf resource handler.
- void BeginNavigationRequest(
- ResourceContext* resource_context,
- const NavigationRequestInfo& info,
- NavigationURLLoaderImplCore* loader,
- ServiceWorkerNavigationHandleCore* service_worker_handle_core);
+ void BeginNavigationRequest(ResourceContext* resource_context,
+ const NavigationRequestInfo& info,
+ NavigationURLLoaderImplCore* loader);
// Turns on stale-while-revalidate support, regardless of command-line flags
// or experiment status. For unit tests only.
void EnableStaleWhileRevalidateForTesting();
+ // Sets the LoaderDelegate, which must outlive this object. Ownership is not
+ // transferred. The LoaderDelegate should be interacted with on the IO thread.
+ void SetLoaderDelegate(LoaderDelegate* loader_delegate);
+
private:
friend class LoaderIOThreadNotifier;
friend class ResourceDispatcherHostTest;
@@ -361,6 +350,8 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void DidReceiveRedirect(ResourceLoader* loader, const GURL& new_url) override;
void DidReceiveResponse(ResourceLoader* loader) override;
void DidFinishLoading(ResourceLoader* loader) override;
+ std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
+ ResourceLoader* loader) override;
// An init helper that runs on the IO thread.
void OnInit();
@@ -448,10 +439,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// waiting for a host name to resolve implies being stuck.
static bool LoadInfoIsMoreInteresting(const LoadInfo& a, const LoadInfo& b);
- // Used to marshal calls to LoadStateChanged from the IO to UI threads. All
- // are done as a single callback to avoid spamming the UI thread.
- static void UpdateLoadInfoOnUIThread(std::unique_ptr<LoadInfoMap> info_map);
-
// Gets the most interesting LoadInfo for each GlobalRoutingID.
std::unique_ptr<LoadInfoMap> GetLoadInfoForAllRoutes();
@@ -539,7 +526,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Returns whether the URLRequest identified by |transferred_request_id| is
// currently in the process of being transferred to a different renderer.
// This happens if a request is redirected cross-site and needs to be resumed
- // by a new render view.
+ // by a new process.
bool IsTransferredNavigation(
const GlobalRequestID& transferred_request_id) const;
@@ -643,16 +630,14 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
ResourceDispatcherHostDelegate* delegate_;
+ LoaderDelegate* loader_delegate_;
+
bool allow_cross_origin_auth_prompt_;
// AsyncRevalidationManager is non-NULL if and only if
// stale-while-revalidate is enabled.
std::unique_ptr<AsyncRevalidationManager> async_revalidation_manager_;
- // http://crbug.com/90971 - Assists in tracking down use-after-frees on
- // shutdown.
- std::set<const ResourceContext*> active_resource_contexts_;
-
typedef std::map<GlobalRequestID,
base::ObserverList<ResourceMessageDelegate>*> DelegateMap;
DelegateMap delegate_map_;
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index 18b98a88c6e..0051ed9b631 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -33,6 +33,7 @@
#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_delegate_impl.h"
#include "content/common/appcache_interfaces.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/navigation_params.h"
@@ -62,10 +63,10 @@
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
-#include "net/base/test_data_directory.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/http/http_util.h"
#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
@@ -174,7 +175,7 @@ static ResourceRequest CreateResourceRequest(const char* method,
// Spin up the message loop to kick off the request.
static void KickOffRequest() {
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
// We may want to move this to a shared space if it is useful for something else
@@ -898,6 +899,7 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
use_test_ssl_certificate_(false),
send_data_received_acks_(false),
auto_advance_(false) {
+ host_.SetLoaderDelegate(&loader_delegate_);
browser_context_.reset(new TestBrowserContext());
BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
base::RunLoop().RunUntilIdle();
@@ -1143,8 +1145,7 @@ 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, -1,
- scoped_refptr<ResourceRequestBody>()));
+ url::Origin(url), true, false, -1));
std::unique_ptr<NavigationURLLoader> test_loader =
NavigationURLLoader::Create(browser_context_.get(),
std::move(request_info), nullptr,
@@ -1162,7 +1163,7 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
// Flush all pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {
}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Sorts out all the messages we saw by request.
ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -1188,6 +1189,7 @@ class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
scoped_refptr<ForwardingFilter> filter_;
scoped_refptr<TestFilterSpecifyingChild> web_contents_filter_;
net::TestNetworkDelegate network_delegate_;
+ LoaderDelegateImpl loader_delegate_;
ResourceDispatcherHostImpl host_;
ResourceIPCAccumulator accum_;
std::string response_headers_;
@@ -1459,7 +1461,7 @@ TEST_P(ResourceDispatcherHostTest, TestMany) {
// Finish the redirection
ResourceHostMsg_FollowRedirect redirect_msg(5);
host_.OnMessageReceived(redirect_msg, filter_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// flush all the pending requests
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1503,7 +1505,7 @@ TEST_P(ResourceDispatcherHostTest, Cancel) {
// flush all the pending requests
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Everything should be out now.
EXPECT_EQ(0, host_.pending_requests());
@@ -1545,7 +1547,7 @@ TEST_P(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
ASSERT_TRUE(info->detachable_handler());
info->detachable_handler()->set_cancel_delay(
base::TimeDelta::FromMilliseconds(200));
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
RendererCancelRequest(1);
@@ -1619,7 +1621,7 @@ TEST_P(ResourceDispatcherHostTest, DeletedFilterDetached) {
EXPECT_EQ(2, host_.pending_requests());
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, host_.pending_requests());
EXPECT_EQ(2, network_delegate()->completed_requests());
@@ -1668,7 +1670,7 @@ TEST_P(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
// Finish up the request.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, host_.pending_requests());
EXPECT_EQ(1, network_delegate()->completed_requests());
@@ -1695,7 +1697,7 @@ TEST_P(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
// calling CancelRequest.
EXPECT_FALSE(was_deleted);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_deleted);
}
@@ -1722,7 +1724,7 @@ TEST_P(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
// However, it is still throttled because the defer happened above the
// DetachableResourceHandler.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(was_deleted);
// Resume the request.
@@ -1733,7 +1735,7 @@ TEST_P(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
// Now, the request completes.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_deleted);
EXPECT_EQ(1, network_delegate()->completed_requests());
EXPECT_EQ(0, network_delegate()->canceled_requests());
@@ -1751,7 +1753,7 @@ TEST_P(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
// flush all the pending requests
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
@@ -1776,7 +1778,7 @@ TEST_P(ResourceDispatcherHostTest, PausedStartError) {
// flush all the pending requests
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, host_.pending_requests());
}
@@ -1802,7 +1804,7 @@ TEST_P(ResourceDispatcherHostTest, ThrottleNetworkStart) {
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, network_delegate()->completed_requests());
EXPECT_EQ(0, host_.pending_requests());
@@ -1830,7 +1832,7 @@ TEST_P(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
ASSERT_FALSE(GenericResourceThrottle::active_throttle());
// The request is started asynchronously.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1857,7 +1859,7 @@ TEST_P(ResourceDispatcherHostTest, CancelInDelegate) {
// flush all the pending requests
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
@@ -1896,7 +1898,7 @@ TEST_P(ResourceDispatcherHostTest, TestProcessCancel) {
// Make sure all requests have finished stage one. test_url_1 will have
// finished.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// TODO(mbelshe):
// Now that the async IO path is in place, the IO always completes on the
@@ -2007,7 +2009,7 @@ TEST_P(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
ASSERT_TRUE(info->detachable_handler());
info->detachable_handler()->set_cancel_delay(
base::TimeDelta::FromMilliseconds(200));
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Cancel the requests to the test process.
host_.CancelRequestsForProcess(filter_->child_id());
@@ -2025,7 +2027,7 @@ TEST_P(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
// In case any messages are still to be processed.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
@@ -2318,7 +2320,7 @@ TEST_P(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Sorts out all the messages we saw by request.
ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -2387,7 +2389,7 @@ TEST_P(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Sorts out all the messages we saw by request.
ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -2610,8 +2612,7 @@ TEST_P(ResourceDispatcherHostTest, CancelRequestsForContext) {
common_params.url = download_url;
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, begin_params, download_url,
- url::Origin(download_url), true, false, -1,
- scoped_refptr<ResourceRequestBody>()));
+ url::Origin(download_url), true, false, -1));
std::unique_ptr<NavigationURLLoader> loader = NavigationURLLoader::Create(
browser_context_.get(), std::move(request_info), nullptr, &delegate);
@@ -2621,7 +2622,7 @@ TEST_P(ResourceDispatcherHostTest, CancelRequestsForContext) {
// Return some data so that the request is identified as a download
// and the proper resource handlers are created.
EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// The UI thread will be informed that the navigation failed with an error
// code of ERR_ABORTED because the navigation turns out to be a download.
@@ -2634,7 +2635,7 @@ TEST_P(ResourceDispatcherHostTest, CancelRequestsForContext) {
host_.CancelRequestsForContext(browser_context_->GetResourceContext());
EXPECT_EQ(0, host_.pending_requests());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
} else {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
download_url, RESOURCE_TYPE_MAIN_FRAME);
@@ -2771,7 +2772,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationHtml) {
kResponseBody);
ResourceHostMsg_FollowRedirect redirect_msg(request_id);
host_.OnMessageReceived(redirect_msg, filter_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Flush all the pending requests to get the response through the
// MimeTypeResourceHandler.
@@ -2794,7 +2795,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationHtml) {
ResourceHostMsg_RequestResource transfer_request_msg(
new_render_view_id, new_request_id, request);
host_.OnMessageReceived(transfer_request_msg, second_filter.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -2849,7 +2850,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationCertificateUpdate) {
SetTestSSLCertificate();
ResourceHostMsg_FollowRedirect redirect_msg(request_id);
host_.OnMessageReceived(redirect_msg, filter_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Flush all the pending requests to get the response through the
// MimeTypeResourceHandler.`
@@ -2877,7 +2878,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationCertificateUpdate) {
ResourceHostMsg_RequestResource transfer_request_msg(new_render_view_id,
new_request_id, request);
host_.OnMessageReceived(transfer_request_msg, second_filter.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -2961,7 +2962,7 @@ TEST_P(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
ResourceHostMsg_RequestResource transfer_request_msg(
new_render_view_id, new_request_id, request);
host_.OnMessageReceived(transfer_request_msg, second_filter.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Transfer the second request.
int new_second_request_id = 6;
@@ -2973,7 +2974,7 @@ TEST_P(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
ResourceHostMsg_RequestResource second_transfer_request_msg(
new_render_view_id, new_second_request_id, second_request);
host_.OnMessageReceived(second_transfer_request_msg, second_filter.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -3025,7 +3026,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationText) {
kResponseBody);
ResourceHostMsg_FollowRedirect redirect_msg(request_id);
host_.OnMessageReceived(redirect_msg, filter_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Flush all the pending requests to get the response through the
// MimeTypeResourceHandler.
@@ -3048,7 +3049,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationText) {
ResourceHostMsg_RequestResource transfer_request_msg(
new_render_view_id, new_request_id, request);
host_.OnMessageReceived(transfer_request_msg, second_filter.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -3097,7 +3098,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
ResourceHostMsg_RequestResource first_request_msg(
render_view_id, request_id, first_request);
host_.OnMessageReceived(first_request_msg, first_filter.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Now that we're blocked on the redirect, update the response and unblock
// by telling the AsyncResourceHandler to follow the redirect.
@@ -3106,7 +3107,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
kResponseBody);
ResourceHostMsg_FollowRedirect redirect_msg(request_id);
host_.OnMessageReceived(redirect_msg, first_filter.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Flush all the pending requests to get the response through the
// MimeTypeResourceHandler.
@@ -3136,7 +3137,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
ResourceHostMsg_RequestResource transfer_request_msg(
new_render_view_id, new_request_id, request);
host_.OnMessageReceived(transfer_request_msg, second_filter.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -3181,7 +3182,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
"Location: http://other.com/blerg\n\n");
ResourceHostMsg_FollowRedirect redirect_msg(request_id);
host_.OnMessageReceived(redirect_msg, filter_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Now that we're blocked on the second redirect, update the response and
// unblock by telling the AsyncResourceHandler to follow the redirect.
@@ -3193,7 +3194,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
kResponseBody);
ResourceHostMsg_FollowRedirect redirect_msg2(request_id);
host_.OnMessageReceived(redirect_msg2, filter_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Flush all the pending requests to get the response through the
// MimeTypeResourceHandler.
@@ -3229,7 +3230,7 @@ TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
EXPECT_EQ(second_filter.get(), info->filter());
// Let request complete.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
@@ -3372,7 +3373,7 @@ TEST_P(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
host_.OnMessageReceived(msg, filter_.get());
}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
msgs.clear();
accum_.GetClassifiedMessages(&msgs);
@@ -3426,7 +3427,7 @@ TEST_P(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) {
host_.OnMessageReceived(msg, filter_.get());
}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
msgs.clear();
accum_.GetClassifiedMessages(&msgs);
@@ -3729,7 +3730,7 @@ TEST_P(ResourceDispatcherHostTest, TransferResponseStarted) {
int initial_count = web_contents_observer_->resource_response_start_count();
MakeWebContentsAssociatedTestRequest(1, net::URLRequestTestJob::test_url_1());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(initial_count + 1,
web_contents_observer_->resource_response_start_count());
@@ -3742,7 +3743,7 @@ TEST_P(ResourceDispatcherHostTest, TransferRequestRedirected) {
MakeWebContentsAssociatedTestRequest(
1, net::URLRequestTestJob::test_url_redirect_to_url_2());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(initial_count + 1,
web_contents_observer_->resource_request_redirect_count());
@@ -3775,7 +3776,7 @@ TEST_P(ResourceDispatcherHostTest, DidChangePriority) {
// scheduled later, so it is not currently running.
ResourceHostMsg_DidChangePriority priority_msg(3, net::MAXIMUM_PRIORITY, 0);
host_.OnMessageReceived(priority_msg, filter_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(3, job_factory_->url_request_jobs_created_count());
@@ -3791,7 +3792,7 @@ TEST_P(ResourceDispatcherHostTest, TransferResponseStartedDownload) {
MakeWebContentsAssociatedDownloadRequest(
1, net::URLRequestTestJob::test_url_1());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(initial_count,
web_contents_observer_->resource_response_start_count());
}
@@ -3803,7 +3804,7 @@ TEST_P(ResourceDispatcherHostTest, TransferRequestRedirectedDownload) {
MakeWebContentsAssociatedDownloadRequest(
1, net::URLRequestTestJob::test_url_redirect_to_url_2());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(initial_count,
web_contents_observer_->resource_request_redirect_count());
}
diff --git a/chromium/content/browser/loader/resource_hints_impl.cc b/chromium/content/browser/loader/resource_hints_impl.cc
index 694947881e6..e6f18c00346 100644
--- a/chromium/content/browser/loader/resource_hints_impl.cc
+++ b/chromium/content/browser/loader/resource_hints_impl.cc
@@ -2,30 +2,48 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/public/browser/resource_hints.h"
-
+#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/browser/resource_hints.h"
+#include "net/base/address_list.h"
#include "net/base/load_flags.h"
+#include "net/dns/host_resolver.h"
+#include "net/dns/single_request_host_resolver.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_info.h"
#include "net/http/http_stream_factory.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
namespace content {
-void PreconnectUrl(net::URLRequestContextGetter* getter,
+namespace {
+
+// Note that the lifetime of |request| and |addresses| is managed by the caller.
+void OnResolveComplete(net::SingleRequestHostResolver* request,
+ net::AddressList* addresses,
+ const net::CompletionCallback& callback,
+ int result) {
+ // Plumb the resolution result into the callback if future consumers want
+ // that information.
+ callback.Run(result);
+}
+
+} // namespace
+
+void PreconnectUrl(content::ResourceContext* resource_context,
const GURL& url,
const GURL& first_party_for_cookies,
int count,
bool allow_credentials,
net::HttpRequestInfo::RequestMotivation motivation) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(getter);
+ DCHECK(resource_context);
- net::URLRequestContext* context = getter->GetURLRequestContext();
+ net::URLRequestContext* context = resource_context->GetRequestContext();
net::HttpTransactionFactory* factory = context->http_transaction_factory();
net::HttpNetworkSession* session = factory->GetSession();
@@ -57,4 +75,20 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
http_stream_factory->PreconnectStreams(count, request_info);
}
+int PreresolveUrl(content::ResourceContext* resource_context,
+ const GURL& url,
+ const net::CompletionCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(resource_context);
+
+ net::AddressList* addresses = new net::AddressList;
+ net::SingleRequestHostResolver* resolver =
+ new net::SingleRequestHostResolver(resource_context->GetHostResolver());
+ net::HostResolver::RequestInfo resolve_info(net::HostPortPair::FromURL(url));
+ return resolver->Resolve(resolve_info, net::IDLE, addresses,
+ base::Bind(&OnResolveComplete, base::Owned(resolver),
+ base::Owned(addresses), callback),
+ net::BoundNetLog());
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index 2bc362262e8..67f69502da2 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -27,7 +27,6 @@
#include "content/browser/ssl/ssl_policy.h"
#include "content/common/ssl_status_serialization.h"
#include "content/public/browser/cert_store.h"
-#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
@@ -324,8 +323,7 @@ void ResourceLoader::OnCertificateRequested(
DCHECK(!ssl_client_auth_handler_)
<< "OnCertificateRequested called with ssl_client_auth_handler pending";
ssl_client_auth_handler_.reset(new SSLClientAuthHandler(
- GetRequestInfo()->GetContext()->CreateClientCertStore(), request_.get(),
- cert_info, this));
+ delegate_->CreateClientCertStore(this), request_.get(), cert_info, this));
ssl_client_auth_handler_->SelectCertificate();
}
@@ -711,14 +709,20 @@ void ResourceLoader::CallDidFinishLoading() {
}
void ResourceLoader::RecordHistograms() {
+ ResourceRequestInfoImpl* info = GetRequestInfo();
if (request_->response_info().network_accessed) {
- UMA_HISTOGRAM_ENUMERATION("Net.HttpResponseInfo.ConnectionInfo",
- request_->response_info().connection_info,
- net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
+ if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
+ UMA_HISTOGRAM_ENUMERATION("Net.HttpResponseInfo.ConnectionInfo.MainFrame",
+ request_->response_info().connection_info,
+ net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Net.HttpResponseInfo.ConnectionInfo.SubResource",
+ request_->response_info().connection_info,
+ net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
+ }
}
- ResourceRequestInfoImpl* info = GetRequestInfo();
-
if (info->GetResourceType() == RESOURCE_TYPE_PREFETCH) {
PrefetchStatus status = STATUS_UNDEFINED;
TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
diff --git a/chromium/content/browser/loader/resource_loader_delegate.h b/chromium/content/browser/loader/resource_loader_delegate.h
index 38c8a38bf7a..098d3911c3c 100644
--- a/chromium/content/browser/loader/resource_loader_delegate.h
+++ b/chromium/content/browser/loader/resource_loader_delegate.h
@@ -9,6 +9,7 @@
namespace net {
class AuthChallengeInfo;
+class ClientCertStore;
}
namespace content {
@@ -33,6 +34,10 @@ class CONTENT_EXPORT ResourceLoaderDelegate {
// expects to be destroyed as a side-effect of this call.
virtual void DidFinishLoading(ResourceLoader* loader) = 0;
+ // Get platform ClientCertStore. May return nullptr.
+ virtual std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
+ ResourceLoader* loader) = 0;
+
protected:
virtual ~ResourceLoaderDelegate() {}
};
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index 0da06a122fb..04a551ff271 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -40,7 +40,6 @@
#include "net/base/mock_file_stream.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
-#include "net/base/test_data_directory.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/cert/x509_certificate.h"
#include "net/nqe/network_quality_estimator.h"
@@ -49,6 +48,7 @@
#include "net/ssl/ssl_private_key.h"
#include "net/test/cert_test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/test_data_directory.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_interceptor.h"
@@ -489,23 +489,6 @@ class SelectCertificateBrowserClient : public TestContentBrowserClient {
DISALLOW_COPY_AND_ASSIGN(SelectCertificateBrowserClient);
};
-class ResourceContextStub : public MockResourceContext {
- public:
- explicit ResourceContextStub(net::URLRequestContext* test_request_context)
- : MockResourceContext(test_request_context) {}
-
- std::unique_ptr<net::ClientCertStore> CreateClientCertStore() override {
- return std::move(dummy_cert_store_);
- }
-
- void SetClientCertStore(std::unique_ptr<net::ClientCertStore> store) {
- dummy_cert_store_ = std::move(store);
- }
-
- private:
- std::unique_ptr<net::ClientCertStore> dummy_cert_store_;
-};
-
// Wraps a ChunkedUploadDataStream to behave as non-chunked to enable upload
// progress reporting.
class NonChunkedUploadDataStream : public net::UploadDataStream {
@@ -659,6 +642,10 @@ class ResourceLoaderTest : public testing::Test,
base::RunLoop().RunUntilIdle();
}
+ void SetClientCertStore(std::unique_ptr<net::ClientCertStore> store) {
+ dummy_cert_store_ = std::move(store);
+ }
+
// ResourceLoaderDelegate:
ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
ResourceLoader* loader,
@@ -674,6 +661,10 @@ class ResourceLoaderTest : public testing::Test,
const GURL& new_url) override {}
void DidReceiveResponse(ResourceLoader* loader) override {}
void DidFinishLoading(ResourceLoader* loader) override {}
+ std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
+ ResourceLoader* loader) override {
+ return std::move(dummy_cert_store_);
+ }
TestBrowserThreadBundle thread_bundle_;
RenderViewHostTestEnabler rvh_test_enabler_;
@@ -681,9 +672,10 @@ class ResourceLoaderTest : public testing::Test,
net::URLRequestJobFactoryImpl job_factory_;
TestNetworkQualityEstimator network_quality_estimator_;
net::TestURLRequestContext test_url_request_context_;
- ResourceContextStub resource_context_;
+ MockResourceContext resource_context_;
std::unique_ptr<TestBrowserContext> browser_context_;
std::unique_ptr<TestWebContents> web_contents_;
+ std::unique_ptr<net::ClientCertStore> dummy_cert_store_;
// The ResourceLoader owns the URLRequest and the ResourceHandler.
ResourceHandlerStub* raw_ptr_resource_handler_;
@@ -740,11 +732,10 @@ TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) {
// Set up the test client cert store.
int store_request_count;
std::vector<std::string> store_requested_authorities;
- net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
- new net::X509Certificate("test", "test", base::Time(), base::Time())));
+ net::CertificateList dummy_certs(1, GetTestCert());
std::unique_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub(
dummy_certs, &store_request_count, &store_requested_authorities));
- resource_context_.SetClientCertStore(std::move(test_store));
+ SetClientCertStore(std::move(test_store));
// Plug in test content browser client.
SelectCertificateBrowserClient test_client;
@@ -854,7 +845,7 @@ TEST_F(ClientCertResourceLoaderTest, StoreAsyncCancel) {
LoaderDestroyingCertStore* test_store =
new LoaderDestroyingCertStore(&loader_,
loader_destroyed_run_loop.QuitClosure());
- resource_context_.SetClientCertStore(base::WrapUnique(test_store));
+ SetClientCertStore(base::WrapUnique(test_store));
loader_->StartRequest();
loader_destroyed_run_loop.Run();
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index 37f4e992fb1..a0e508bc669 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -61,35 +61,36 @@ void ResourceRequestInfo::AllocateForTesting(net::URLRequest* request,
// the main frame.
DCHECK(resource_type != RESOURCE_TYPE_MAIN_FRAME || is_main_frame);
- ResourceRequestInfoImpl* info =
- new ResourceRequestInfoImpl(
- PROCESS_TYPE_RENDERER, // process_type
- render_process_id, // child_id
- render_view_id, // route_id
- -1, // frame_tree_node_id
- 0, // origin_pid
- 0, // request_id
- render_frame_id, // render_frame_id
- is_main_frame, // is_main_frame
- parent_is_main_frame, // parent_is_main_frame
- resource_type, // resource_type
- ui::PAGE_TRANSITION_LINK, // transition_type
- false, // should_replace_current_entry
- false, // is_download
- false, // is_stream
- allow_download, // allow_download
- false, // has_user_gesture
- false, // enable load timing
- request->has_upload(), // enable upload progress
- false, // do_not_prompt_for_login
- blink::WebReferrerPolicyDefault, // referrer_policy
- blink::WebPageVisibilityStateVisible, // visibility_state
- context, // context
- base::WeakPtr<ResourceMessageFilter>(), // filter
- false, // report_raw_headers
- is_async, // is_async
- is_using_lofi, // is_using_lofi
- std::string()); // original_headers
+ ResourceRequestInfoImpl* info = new ResourceRequestInfoImpl(
+ PROCESS_TYPE_RENDERER, // process_type
+ render_process_id, // child_id
+ render_view_id, // route_id
+ -1, // frame_tree_node_id
+ 0, // origin_pid
+ 0, // request_id
+ render_frame_id, // render_frame_id
+ is_main_frame, // is_main_frame
+ parent_is_main_frame, // parent_is_main_frame
+ resource_type, // resource_type
+ ui::PAGE_TRANSITION_LINK, // transition_type
+ false, // should_replace_current_entry
+ false, // is_download
+ false, // is_stream
+ allow_download, // allow_download
+ false, // has_user_gesture
+ false, // enable load timing
+ request->has_upload(), // enable upload progress
+ false, // do_not_prompt_for_login
+ blink::WebReferrerPolicyDefault, // referrer_policy
+ blink::WebPageVisibilityStateVisible, // visibility_state
+ context, // context
+ base::WeakPtr<ResourceMessageFilter>(), // filter
+ false, // report_raw_headers
+ is_async, // is_async
+ is_using_lofi, // is_using_lofi
+ std::string(), // original_headers
+ nullptr, // body
+ false); // initiated_in_secure_context
info->AssociateWithRequest(request);
}
@@ -156,7 +157,9 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
bool report_raw_headers,
bool is_async,
bool is_using_lofi,
- const std::string& original_headers)
+ const std::string& original_headers,
+ const scoped_refptr<ResourceRequestBodyImpl> body,
+ bool initiated_in_secure_context)
: cross_site_handler_(NULL),
detachable_handler_(NULL),
process_type_(process_type),
@@ -188,8 +191,9 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
report_raw_headers_(report_raw_headers),
is_async_(is_async),
is_using_lofi_(is_using_lofi),
- original_headers_(original_headers) {
-}
+ original_headers_(original_headers),
+ body_(body),
+ initiated_in_secure_context_(initiated_in_secure_context) {}
ResourceRequestInfoImpl::~ResourceRequestInfoImpl() {
}
@@ -336,4 +340,8 @@ void ResourceRequestInfoImpl::UpdateForTransfer(
filter_ = filter;
}
+void ResourceRequestInfoImpl::ResetBody() {
+ body_ = nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index 1e383504c0b..635d13bdc83 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/referrer.h"
#include "content/public/common/resource_type.h"
@@ -66,7 +67,9 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool report_raw_headers,
bool is_async,
bool is_using_lofi,
- const std::string& original_headers);
+ const std::string& original_headers,
+ const scoped_refptr<ResourceRequestBodyImpl> body,
+ bool initiated_in_secure_context);
~ResourceRequestInfoImpl() override;
// ResourceRequestInfo implementation:
@@ -184,6 +187,16 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
}
const std::string& original_headers() const { return original_headers_; }
+ const scoped_refptr<ResourceRequestBodyImpl>& body() const { return body_; }
+ void ResetBody();
+
+ bool initiated_in_secure_context() const {
+ return initiated_in_secure_context_;
+ }
+ void set_initiated_in_secure_context_for_testing(bool secure) {
+ initiated_in_secure_context_ = secure;
+ }
+
private:
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
DeletedFilterDetached);
@@ -225,6 +238,8 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool is_async_;
bool is_using_lofi_;
const std::string original_headers_;
+ scoped_refptr<ResourceRequestBodyImpl> body_;
+ bool initiated_in_secure_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 176f6034a18..12e7361fef6 100644
--- a/chromium/content/browser/loader/resource_scheduler.cc
+++ b/chromium/content/browser/loader/resource_scheduler.cc
@@ -42,8 +42,6 @@ enum StartMode {
const char kRequestLimitFieldTrial[] = "OutstandingRequestLimiting";
const char kRequestLimitFieldTrialGroupPrefix[] = "Limit";
-const char kResourcePrioritiesFieldTrial[] = "ResourcePriorities";
-
// Flags identifying various attributes of the request that are used
// when making scheduling decisions.
using RequestAttributes = uint8_t;
@@ -54,11 +52,30 @@ const RequestAttributes kAttributeLayoutBlocking = 0x04;
} // namespace
-static const size_t kDefaultMaxNumDelayableRequestsPerClient = 10;
-static const size_t kMaxNumDelayableRequestsPerHost = 6;
-static const size_t kDefaultMaxNumDelayableWhileLayoutBlocking = 1;
+// The maximum number of delayable requests to allow to be in-flight at any
+// point in time (across all hosts).
+static const size_t kMaxNumDelayableRequestsPerClient = 10;
+
+// The maximum number of requests to allow be in-flight at any point in time per
+// host.
+static const size_t kMaxNumDelayableRequestsPerHostPerClient = 6;
+
+// The maximum number of delayable requests to allow to be in-flight at any
+// point in time while in the layout-blocking phase of loading.
+static const size_t kMaxNumDelayableWhileLayoutBlockingPerClient = 1;
+
+// The priority level above which resources are considered layout-blocking if
+// the html_body has not started.
static const net::RequestPriority
- kDefaultLayoutBlockingPriorityThreshold = net::LOW;
+ kLayoutBlockingPriorityThreshold = net::MEDIUM;
+
+// The priority level below which resources are considered to be delayable.
+static const net::RequestPriority
+ kDelayablePriorityThreshold = net::MEDIUM;
+
+// The number of in-flight layout-blocking requests above which all delayable
+// requests should be blocked.
+static const size_t kInFlightNonDelayableRequestCountPerClientThreshold = 1;
struct ResourceScheduler::RequestPriorityParams {
RequestPriorityParams()
@@ -330,8 +347,9 @@ class ResourceScheduler::Client {
// First start any pending requests so that they will be moved into
// in_flight_requests_. This may exceed the limits
// kDefaultMaxNumDelayableRequestsPerClient and
- // kMaxNumDelayableRequestsPerHost, so this method must not do anything that
- // depends on those limits before calling ClearInFlightRequests() below.
+ // kMaxNumDelayableRequestsPerHostPerClient, so this method must not do
+ // anything that depends on those limits before calling
+ // ClearInFlightRequests() below.
while (!pending_requests_.IsEmpty()) {
ScheduledResourceRequest* request =
*pending_requests_.GetNextHighestIterator();
@@ -496,14 +514,14 @@ class ResourceScheduler::Client {
attributes |= kAttributeLayoutBlocking;
} else if (!has_html_body_ &&
request->url_request()->priority() >
- scheduler_->non_delayable_threshold()) {
+ kLayoutBlockingPriorityThreshold) {
// Requests that are above the non_delayable threshold before the HTML
// body has been parsed are inferred to be layout-blocking.
attributes |= kAttributeLayoutBlocking;
} else if (request->url_request()->priority() <
- scheduler_->non_delayable_threshold()) {
- // Resources below the non_delayable_threshold that are being requested
- // from a server that does not support native prioritization are
+ 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 =
@@ -524,7 +542,7 @@ class ResourceScheduler::Client {
net::HostPortPair::FromURL((*it)->url_request()->url());
if (active_request_host.Equals(host_port_pair)) {
same_host_count++;
- if (same_host_count >= kMaxNumDelayableRequestsPerHost)
+ if (same_host_count >= kMaxNumDelayableRequestsPerHostPerClient)
return true;
}
}
@@ -564,10 +582,11 @@ class ResourceScheduler::Client {
// * Non-delayable, High-priority and request-priority capable requests are
// issued immediately.
// * Low priority requests are delayable.
- // * While layout-blocking requests are loading or the body tag has not
- // yet been parsed, limit the number of delayable requests that may be
- // in flight (to 1 by default, or to zero if there's an outstanding
- // request limit in place).
+ // * While kInFlightNonDelayableRequestCountPerClientThreshold
+ // layout-blocking requests are loading or the body tag has not yet been
+ // parsed, limit the number of delayable requests that may be in flight
+ // (to kMaxNumDelayableWhileLayoutBlockingPerClient by default, or to zero
+ // if there's an outstanding request limit in place).
// * If no high priority or layout-blocking requests are in flight, start
// loading delayable requests.
// * Never exceed 10 delayable requests in flight per client.
@@ -611,10 +630,8 @@ class ResourceScheduler::Client {
if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable))
return START_REQUEST;
- if (in_flight_delayable_count_ >=
- scheduler_->max_num_delayable_requests()) {
+ if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient)
return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
- }
if (ShouldKeepSearching(host_port_pair)) {
// There may be other requests for other hosts that may be allowed,
@@ -630,30 +647,19 @@ class ResourceScheduler::Client {
if (!has_html_body_ || total_layout_blocking_count_ != 0) {
size_t non_delayable_requests_in_flight_count =
in_flight_requests_.size() - in_flight_delayable_count_;
- if (scheduler_->enable_in_flight_non_delayable_threshold()) {
- if (non_delayable_requests_in_flight_count >
- scheduler_->in_flight_non_delayable_threshold()) {
- // Too many higher priority in-flight requests to allow lower priority
- // requests through.
- return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
- }
- if (in_flight_requests_.size() > 0 &&
- (scheduler_->limit_outstanding_requests() ||
- in_flight_delayable_count_ >=
- scheduler_->max_num_delayable_while_layout_blocking())) {
- // Block the request if at least one request is in flight and the
- // number of in-flight delayable requests has hit the configured
- // limit.
- return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
- }
- } else if (non_delayable_requests_in_flight_count > 0 &&
+ if (non_delayable_requests_in_flight_count >
+ kInFlightNonDelayableRequestCountPerClientThreshold) {
+ // Too many higher priority in-flight requests to allow lower priority
+ // requests through.
+ return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
+ }
+ if (in_flight_requests_.size() > 0 &&
(scheduler_->limit_outstanding_requests() ||
in_flight_delayable_count_ >=
- scheduler_->max_num_delayable_while_layout_blocking())) {
- // If there are no high-priority requests in flight the floodgates open.
- // If there are high-priority requests in-flight then limit the number
- // of lower-priority requests (or zero if a limit field trial is
- // active).
+ kMaxNumDelayableWhileLayoutBlockingPerClient)) {
+ // Block the request if at least one request is in flight and the
+ // number of in-flight delayable requests has hit the configured
+ // limit.
return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
}
}
@@ -714,13 +720,7 @@ class ResourceScheduler::Client {
ResourceScheduler::ResourceScheduler()
: limit_outstanding_requests_(false),
- outstanding_request_limit_(0),
- non_delayable_threshold_(kDefaultLayoutBlockingPriorityThreshold),
- enable_in_flight_non_delayable_threshold_(false),
- in_flight_non_delayable_threshold_(0),
- max_num_delayable_while_layout_blocking_(
- kDefaultMaxNumDelayableWhileLayoutBlocking),
- max_num_delayable_requests_(kDefaultMaxNumDelayableRequestsPerClient) {
+ outstanding_request_limit_(0) {
std::string outstanding_limit_trial_group =
base::FieldTrialList::FindFullName(kRequestLimitFieldTrial);
std::vector<std::string> split_group(
@@ -734,42 +734,6 @@ ResourceScheduler::ResourceScheduler()
limit_outstanding_requests_ = true;
outstanding_request_limit_ = outstanding_limit;
}
-
- // Set up the ResourceScheduling field trial options.
- // The field trial parameters are also encoded into the group name since
- // the variations component is not available from here and plumbing the
- // options through the code is overkill for a short experiment.
- //
- // The group name encoding looks like this:
- // <descriptiveName>_ABCDE_E2_F_G
- // A - fetchDeferLateScripts (1 for true, 0 for false)
- // B - fetchIncreaseFontPriority (1 for true, 0 for false)
- // C - fetchIncreaseAsyncScriptPriority (1 for true, 0 for false)
- // D - fetchIncreasePriorities (1 for true, 0 for false)
- // E - fetchEnableLayoutBlockingThreshold (1 for true, 0 for false)
- // E2 - fetchLayoutBlockingThreshold (Numeric)
- // F - fetchMaxNumDelayableWhileLayoutBlocking (Numeric)
- // G - fetchMaxNumDelayableRequests (Numeric)
- std::string resource_priorities_trial_group =
- base::FieldTrialList::FindFullName(kResourcePrioritiesFieldTrial);
- std::vector<std::string> resource_priorities_split_group(
- base::SplitString(resource_priorities_trial_group, "_",
- base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL));
- if (resource_priorities_split_group.size() == 5 &&
- resource_priorities_split_group[1].length() == 5) {
- // fetchIncreasePriorities
- if (resource_priorities_split_group[1].at(3) == '1')
- non_delayable_threshold_ = net::MEDIUM;
- enable_in_flight_non_delayable_threshold_ =
- resource_priorities_split_group[1].at(4) == '1';
- size_t numeric_value = 0;
- if (base::StringToSizeT(resource_priorities_split_group[2], &numeric_value))
- in_flight_non_delayable_threshold_ = numeric_value;
- if (base::StringToSizeT(resource_priorities_split_group[3], &numeric_value))
- max_num_delayable_while_layout_blocking_ = numeric_value;
- if (base::StringToSizeT(resource_priorities_split_group[4], &numeric_value))
- max_num_delayable_requests_ = numeric_value;
- }
}
ResourceScheduler::~ResourceScheduler() {
diff --git a/chromium/content/browser/loader/resource_scheduler.h b/chromium/content/browser/loader/resource_scheduler.h
index a2f114a1a0e..85442f0f37c 100644
--- a/chromium/content/browser/loader/resource_scheduler.h
+++ b/chromium/content/browser/loader/resource_scheduler.h
@@ -116,35 +116,6 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
return outstanding_request_limit_;
}
- // Returns the priority level above which resources are considered
- // layout-blocking if the html_body has not started. It is also the threshold
- // below which resources are considered delayable (and for completeness,
- // a request that matches the threshold level is a high-priority but not
- // layout-blocking request).
- net::RequestPriority non_delayable_threshold() const {
- return non_delayable_threshold_;
- }
-
- // Returns true if all delayable requests should be blocked while at least
- // in_flight_layout_blocking_threshold() layout-blocking requests are
- // in-flight during the layout-blocking phase of loading.
- bool enable_in_flight_non_delayable_threshold() const {
- return enable_in_flight_non_delayable_threshold_;
- }
-
- // Returns the number of in-flight layout-blocking requests above which
- // all delayable requests should be blocked when
- // enable_layout_blocking_threshold is set.
- size_t in_flight_non_delayable_threshold() const {
- return in_flight_non_delayable_threshold_;
- }
-
- // Returns the maximum number of delayable requests to allow be in-flight
- // at any point in time while in the layout-blocking phase of loading.
- size_t max_num_delayable_while_layout_blocking() const {
- return max_num_delayable_while_layout_blocking_;
- }
-
// Returns the maximum number of delayable requests to all be in-flight at
// any point in time (across all hosts).
size_t max_num_delayable_requests() const {
@@ -176,10 +147,6 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
ClientMap client_map_;
bool limit_outstanding_requests_;
size_t outstanding_request_limit_;
- net::RequestPriority non_delayable_threshold_;
- bool enable_in_flight_non_delayable_threshold_;
- size_t in_flight_non_delayable_threshold_;
- size_t max_num_delayable_while_layout_blocking_;
size_t max_num_delayable_requests_;
RequestSet unowned_requests_;
diff --git a/chromium/content/browser/loader/resource_scheduler_unittest.cc b/chromium/content/browser/loader/resource_scheduler_unittest.cc
index c9139385577..fbe518b9b30 100644
--- a/chromium/content/browser/loader/resource_scheduler_unittest.cc
+++ b/chromium/content/browser/loader/resource_scheduler_unittest.cc
@@ -131,7 +131,7 @@ class ResourceSchedulerTest : public testing::Test {
io_thread_(BrowserThread::IO, &message_loop_),
field_trial_list_(new base::MockEntropyProvider()) {
InitializeScheduler();
- context_.set_http_server_properties(http_server_properties_.GetWeakPtr());
+ context_.set_http_server_properties(&http_server_properties_);
}
~ResourceSchedulerTest() override {
@@ -269,20 +269,6 @@ TEST_F(ResourceSchedulerTest, OneIsolatedLowRequest) {
EXPECT_TRUE(request->started());
}
-TEST_F(ResourceSchedulerTest, OneLowLoadsUntilIdle) {
- 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));
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(low->started());
- EXPECT_FALSE(low2->started());
-
- high.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low2->started());
-}
-
TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInserted) {
std::unique_ptr<TestRequest> high(
NewRequest("http://host/high", net::HIGHEST));
@@ -294,9 +280,7 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInserted) {
high.reset();
base::RunLoop().RunUntilIdle();
- // TODO(mmenke): The name of this test implies this should be false.
- // Investigate if this is now expected, remove or update this test if it is.
- EXPECT_TRUE(low2->started());
+ EXPECT_FALSE(low2->started());
scheduler()->OnWillInsertBody(kChildId, kRouteId);
base::RunLoop().RunUntilIdle();
@@ -321,13 +305,17 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilCriticalComplete) {
EXPECT_TRUE(low2->started());
}
-TEST_F(ResourceSchedulerTest, LowDoesNotBlockCriticalComplete) {
- std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOW));
+TEST_F(ResourceSchedulerTest, MediumDoesNotBlockCriticalComplete) {
+ // kLayoutBlockingPriorityThreshold determines what priority level above which
+ // requests are considered layout-blocking and must be completed before the
+ // critical loading period is complete. It is currently set to net::MEDIUM.
+ std::unique_ptr<TestRequest> medium(
+ NewRequest("http://host/low", net::MEDIUM));
std::unique_ptr<TestRequest> lowest(
NewRequest("http://host/lowest", net::LOWEST));
std::unique_ptr<TestRequest> lowest2(
NewRequest("http://host/lowest", net::LOWEST));
- EXPECT_TRUE(low->started());
+ EXPECT_TRUE(medium->started());
EXPECT_TRUE(lowest->started());
EXPECT_FALSE(lowest2->started());
@@ -341,14 +329,14 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
url::SchemeHostPort("https", "spdyhost", 443), true);
std::unique_ptr<TestRequest> high(
NewRequest("http://host/high", net::HIGHEST));
- std::unique_ptr<TestRequest> low_spdy(
- NewRequest("https://spdyhost/low", net::LOWEST));
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_spdy->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
+ EXPECT_TRUE(low_spdy->started());
scheduler()->OnWillInsertBody(kChildId, kRouteId);
high.reset();
@@ -356,6 +344,24 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
EXPECT_TRUE(low2->started());
}
+TEST_F(ResourceSchedulerTest, SpdyLowBlocksOtherLowUntilBodyInserted) {
+ 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_spdy(
+ NewRequest("https://spdyhost/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ EXPECT_TRUE(high->started());
+ EXPECT_TRUE(low_spdy->started());
+ EXPECT_FALSE(low->started());
+
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ high.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(low->started());
+}
+
TEST_F(ResourceSchedulerTest, NavigationResetsState) {
scheduler()->OnWillInsertBody(kChildId, kRouteId);
scheduler()->OnNavigate(kChildId, kRouteId);
@@ -375,7 +381,11 @@ TEST_F(ResourceSchedulerTest, BackgroundRequestStartsImmediately) {
EXPECT_TRUE(request->started());
}
-TEST_F(ResourceSchedulerTest, StartMultipleLowRequestsWhenIdle) {
+TEST_F(ResourceSchedulerTest, MoreThanOneHighRequestBlocksDelayableRequests) {
+ // If there are more than kInFlightNonDelayableRequestCountThreshold (=1)
+ // high-priority / non-delayable requests, block all low priority fetches and
+ // allow them through one at a time once the number of high priority requests
+ // drops.
std::unique_ptr<TestRequest> high1(
NewRequest("http://host/high1", net::HIGHEST));
std::unique_ptr<TestRequest> high2(
@@ -384,16 +394,13 @@ TEST_F(ResourceSchedulerTest, StartMultipleLowRequestsWhenIdle) {
std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high1->started());
EXPECT_TRUE(high2->started());
- EXPECT_TRUE(low->started());
+ EXPECT_FALSE(low->started());
EXPECT_FALSE(low2->started());
high1.reset();
base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
-
- high2.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low2->started());
}
TEST_F(ResourceSchedulerTest, CancelOtherRequestsWhileResuming) {
@@ -419,6 +426,7 @@ TEST_F(ResourceSchedulerTest, CancelOtherRequestsWhileResuming) {
EXPECT_TRUE(high->started());
EXPECT_FALSE(low2->started());
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
high.reset();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low1->started());
@@ -686,75 +694,77 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
}
TEST_F(ResourceSchedulerTest, OustandingRequestLimitEnforced) {
- const int kRequestLimit = 3;
- ASSERT_TRUE(InitializeFieldTrials(
- base::StringPrintf("OutstandingRequestLimiting/Limit=%d/",
- kRequestLimit)));
- InitializeScheduler();
-
- // Throw in requests up to the above limit; make sure they are started.
- ScopedVector<TestRequest> requests;
- for (int i = 0; i < kRequestLimit; ++i) {
+ const int kRequestLimit = 3;
+ ASSERT_TRUE(InitializeFieldTrials(
+ base::StringPrintf("OutstandingRequestLimiting/Limit=%d/",
+ kRequestLimit)));
+ InitializeScheduler();
+
+ // Throw in requests up to the above limit; make sure they are started.
+ ScopedVector<TestRequest> requests;
+ for (int i = 0; i < kRequestLimit; ++i) {
+ string url = "http://host/medium";
+ requests.push_back(NewRequest(url.c_str(), net::MEDIUM));
+ EXPECT_TRUE(requests[i]->started());
+ }
+
+ // Confirm that another request will indeed fail.
string url = "http://host/medium";
requests.push_back(NewRequest(url.c_str(), net::MEDIUM));
- EXPECT_TRUE(requests[i]->started());
+ EXPECT_FALSE(requests[kRequestLimit]->started());
}
- // Confirm that another request will indeed fail.
- string url = "http://host/medium";
- requests.push_back(NewRequest(url.c_str(), net::MEDIUM));
- EXPECT_FALSE(requests[kRequestLimit]->started());
-}
+ // Confirm that outstanding requests limits apply to requests to hosts
+ // that support request priority.
+ TEST_F(ResourceSchedulerTest,
+ OutstandingRequestsLimitsEnforcedForRequestPriority) {
+ const int kRequestLimit = 3;
+ ASSERT_TRUE(InitializeFieldTrials(
+ base::StringPrintf("OutstandingRequestLimiting/Limit=%d/",
+ kRequestLimit)));
+ InitializeScheduler();
-// Confirm that outstanding requests limits apply to requests to hosts
-// that support request priority.
-TEST_F(ResourceSchedulerTest,
- OutstandingRequestsLimitsEnforcedForRequestPriority) {
- const int kRequestLimit = 3;
- ASSERT_TRUE(InitializeFieldTrials(
- base::StringPrintf("OutstandingRequestLimiting/Limit=%d/",
- kRequestLimit)));
- InitializeScheduler();
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("https", "spdyhost", 443), true);
- http_server_properties_.SetSupportsSpdy(
- url::SchemeHostPort("https", "spdyhost", 443), true);
+ // Throw in requests up to the above limit; make sure they are started.
+ ScopedVector<TestRequest> requests;
+ for (int i = 0; i < kRequestLimit; ++i) {
+ string url = "http://spdyhost/medium";
+ requests.push_back(NewRequest(url.c_str(), net::MEDIUM));
+ EXPECT_TRUE(requests[i]->started());
+ }
- // Throw in requests up to the above limit; make sure they are started.
- ScopedVector<TestRequest> requests;
- for (int i = 0; i < kRequestLimit; ++i) {
+ // Confirm that another request will indeed fail.
string url = "http://spdyhost/medium";
requests.push_back(NewRequest(url.c_str(), net::MEDIUM));
- EXPECT_TRUE(requests[i]->started());
+ EXPECT_FALSE(requests[kRequestLimit]->started());
}
- // Confirm that another request will indeed fail.
- string url = "http://spdyhost/medium";
- requests.push_back(NewRequest(url.c_str(), net::MEDIUM));
- EXPECT_FALSE(requests[kRequestLimit]->started());
-}
-
-TEST_F(ResourceSchedulerTest, OutstandingRequestLimitDelays) {
- const int kRequestLimit = 3;
- ASSERT_TRUE(InitializeFieldTrials(
- base::StringPrintf("OutstandingRequestLimiting/Limit=%d/",
- kRequestLimit)));
+ TEST_F(ResourceSchedulerTest, OutstandingRequestLimitDelays) {
+ const int kRequestLimit = 3;
+ ASSERT_TRUE(InitializeFieldTrials(
+ base::StringPrintf("OutstandingRequestLimiting/Limit=%d/",
+ kRequestLimit)));
- 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> low2(NewRequest("http://host/low", net::LOWEST));
- EXPECT_TRUE(high->started());
- EXPECT_FALSE(low->started());
- EXPECT_FALSE(low2->started());
-
- high.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low->started());
- EXPECT_TRUE(low2->started());
-}
-
-// Async revalidations which are not started when the tab is closed must be
+ 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> low2(NewRequest("http://host/low",
+ net::LOWEST));
+ EXPECT_TRUE(high->started());
+ EXPECT_FALSE(low->started());
+ EXPECT_FALSE(low2->started());
+
+ high.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(low->started());
+ 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.
TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeleted) {
@@ -799,380 +809,6 @@ TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeletedManyDelayable) {
EXPECT_TRUE(lowest->started());
}
-TEST_F(ResourceSchedulerTest, DefaultLayoutBlockingPriority) {
- const int kDeferLateScripts = 0;
- const int kIncreaseFontPriority = 0;
- const int kIncreaseAsyncScriptPriority = 0;
- const int kEnablePriorityIncrease = 0;
- const int kEnableLayoutBlockingThreshold = 0;
- const int kLayoutBlockingThreshold = 0;
- const int kMaxNumDelayableWhileLayoutBlocking = 1;
- const int kMaxNumDelayableRequestsPerClient = 10;
- ASSERT_TRUE(InitializeFieldTrials(base::StringPrintf(
- "ResourcePriorities/LayoutBlocking_%d%d%d%d%d_%d_%d_%d/",
- kDeferLateScripts,
- kIncreaseFontPriority,
- kIncreaseAsyncScriptPriority,
- kEnablePriorityIncrease,
- kEnableLayoutBlockingThreshold,
- kLayoutBlockingThreshold,
- kMaxNumDelayableWhileLayoutBlocking,
- kMaxNumDelayableRequestsPerClient)));
- InitializeScheduler();
- std::unique_ptr<TestRequest> high(
- NewRequest("http://hosthigh/high", net::HIGHEST));
- std::unique_ptr<TestRequest> high2(
- NewRequest("http://hosthigh/high", net::HIGHEST));
- std::unique_ptr<TestRequest> medium(
- NewRequest("http://hostmedium/medium", net::MEDIUM));
- std::unique_ptr<TestRequest> medium2(
- NewRequest("http://hostmedium/medium", net::MEDIUM));
- std::unique_ptr<TestRequest> low(NewRequest("http://hostlow/low", net::LOW));
- std::unique_ptr<TestRequest> low2(NewRequest("http://hostlow/low", net::LOW));
- std::unique_ptr<TestRequest> lowest(
- NewRequest("http://hostlowest/lowest", net::LOWEST));
- std::unique_ptr<TestRequest> lowest2(
- NewRequest("http://hostlowest/lowest", net::LOWEST));
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(high2->started());
- EXPECT_TRUE(medium->started());
- EXPECT_TRUE(medium2->started());
- EXPECT_TRUE(low->started());
- EXPECT_TRUE(low2->started());
- EXPECT_TRUE(lowest->started());
- EXPECT_FALSE(lowest2->started());
-
- lowest.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(lowest2->started());
-}
-
-TEST_F(ResourceSchedulerTest, IncreaseLayoutBlockingPriority) {
- // Changes the level of priorities that are allowed during layout-blocking
- // from net::LOWEST to net::LOW.
- const int kDeferLateScripts = 0;
- const int kIncreaseFontPriority = 0;
- const int kIncreaseAsyncScriptPriority = 0;
- const int kEnablePriorityIncrease = 1;
- const int kEnableLayoutBlockingThreshold = 0;
- const int kLayoutBlockingThreshold = 0;
- const int kMaxNumDelayableWhileLayoutBlocking = 1;
- const int kMaxNumDelayableRequestsPerClient = 10;
- ASSERT_TRUE(InitializeFieldTrials(base::StringPrintf(
- "ResourcePriorities/LayoutBlocking_%d%d%d%d%d_%d_%d_%d/",
- kDeferLateScripts,
- kIncreaseFontPriority,
- kIncreaseAsyncScriptPriority,
- kEnablePriorityIncrease,
- kEnableLayoutBlockingThreshold,
- kLayoutBlockingThreshold,
- kMaxNumDelayableWhileLayoutBlocking,
- kMaxNumDelayableRequestsPerClient)));
- InitializeScheduler();
- std::unique_ptr<TestRequest> high(
- NewRequest("http://hosthigh/high", net::HIGHEST));
- std::unique_ptr<TestRequest> high2(
- NewRequest("http://hosthigh/high", net::HIGHEST));
- std::unique_ptr<TestRequest> medium(
- NewRequest("http://hostmedium/medium", net::MEDIUM));
- std::unique_ptr<TestRequest> medium2(
- NewRequest("http://hostmedium/medium", net::MEDIUM));
- std::unique_ptr<TestRequest> low(NewRequest("http://hostlow/low", net::LOW));
- std::unique_ptr<TestRequest> low2(NewRequest("http://hostlow/low", net::LOW));
- std::unique_ptr<TestRequest> lowest(
- NewRequest("http://hostlowest/lowest", net::LOWEST));
- std::unique_ptr<TestRequest> lowest2(
- NewRequest("http://hostlowest/lowest", net::LOWEST));
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(high2->started());
- EXPECT_TRUE(medium->started());
- EXPECT_TRUE(medium2->started());
- EXPECT_TRUE(low->started());
- EXPECT_FALSE(low2->started());
- EXPECT_FALSE(lowest->started());
- EXPECT_FALSE(lowest2->started());
-
- low.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low2->started());
- EXPECT_FALSE(lowest->started());
- EXPECT_FALSE(lowest2->started());
-
- low2.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(lowest->started());
- EXPECT_FALSE(lowest2->started());
-
- lowest.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(lowest2->started());
-}
-
-TEST_F(ResourceSchedulerTest, UseLayoutBlockingThresholdOne) {
- // Prevents any low priority requests from starting while more than
- // N high priority requests are pending (before body).
- const int kDeferLateScripts = 0;
- const int kIncreaseFontPriority = 0;
- const int kIncreaseAsyncScriptPriority = 0;
- const int kEnablePriorityIncrease = 0;
- const int kEnableLayoutBlockingThreshold = 1;
- const int kLayoutBlockingThreshold = 1;
- const int kMaxNumDelayableWhileLayoutBlocking = 1;
- const int kMaxNumDelayableRequestsPerClient = 10;
- ASSERT_TRUE(InitializeFieldTrials(base::StringPrintf(
- "ResourcePriorities/LayoutBlocking_%d%d%d%d%d_%d_%d_%d/",
- kDeferLateScripts,
- kIncreaseFontPriority,
- kIncreaseAsyncScriptPriority,
- kEnablePriorityIncrease,
- kEnableLayoutBlockingThreshold,
- kLayoutBlockingThreshold,
- kMaxNumDelayableWhileLayoutBlocking,
- kMaxNumDelayableRequestsPerClient)));
- InitializeScheduler();
- std::unique_ptr<TestRequest> high(
- NewRequest("http://host/high", net::HIGHEST));
- std::unique_ptr<TestRequest> high2(
- 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));
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(high2->started());
- EXPECT_FALSE(low->started());
- EXPECT_FALSE(low2->started());
-
- high.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low->started());
- EXPECT_FALSE(low2->started());
-
- high2.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(low2->started());
-
- scheduler()->OnWillInsertBody(kChildId, kRouteId);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low2->started());
-}
-
-TEST_F(ResourceSchedulerTest, UseLayoutBlockingThresholdTwo) {
- // Prevents any low priority requests from starting while more than
- // N high priority requests are pending (before body).
- const int kDeferLateScripts = 0;
- const int kIncreaseFontPriority = 0;
- const int kIncreaseAsyncScriptPriority = 0;
- const int kEnablePriorityIncrease = 0;
- const int kEnableLayoutBlockingThreshold = 1;
- const int kLayoutBlockingThreshold = 2;
- const int kMaxNumDelayableWhileLayoutBlocking = 1;
- const int kMaxNumDelayableRequestsPerClient = 10;
- ASSERT_TRUE(InitializeFieldTrials(base::StringPrintf(
- "ResourcePriorities/LayoutBlocking_%d%d%d%d%d_%d_%d_%d/",
- kDeferLateScripts,
- kIncreaseFontPriority,
- kIncreaseAsyncScriptPriority,
- kEnablePriorityIncrease,
- kEnableLayoutBlockingThreshold,
- kLayoutBlockingThreshold,
- kMaxNumDelayableWhileLayoutBlocking,
- kMaxNumDelayableRequestsPerClient)));
- InitializeScheduler();
- std::unique_ptr<TestRequest> high(
- NewRequest("http://host/high", net::HIGHEST));
- std::unique_ptr<TestRequest> high2(
- NewRequest("http://host/high", net::HIGHEST));
- std::unique_ptr<TestRequest> high3(
- 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));
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(high2->started());
- EXPECT_TRUE(high3->started());
- EXPECT_FALSE(low->started());
- EXPECT_FALSE(low2->started());
-
- high.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low->started());
- EXPECT_FALSE(low2->started());
-
- high2.reset();
- high3.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(low2->started());
-
- scheduler()->OnWillInsertBody(kChildId, kRouteId);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low2->started());
-}
-
-TEST_F(ResourceSchedulerTest, TwoDelayableLoadsUntilBodyInserted) {
- // Allow for two low priority requests to be in flight at any point in time
- // during the layout-blocking phase of loading.
- const int kDeferLateScripts = 0;
- const int kIncreaseFontPriority = 0;
- const int kIncreaseAsyncScriptPriority = 0;
- const int kEnablePriorityIncrease = 0;
- const int kEnableLayoutBlockingThreshold = 0;
- const int kLayoutBlockingThreshold = 0;
- const int kMaxNumDelayableWhileLayoutBlocking = 2;
- const int kMaxNumDelayableRequestsPerClient = 10;
- ASSERT_TRUE(InitializeFieldTrials(base::StringPrintf(
- "ResourcePriorities/LayoutBlocking_%d%d%d%d%d_%d_%d_%d/",
- kDeferLateScripts,
- kIncreaseFontPriority,
- kIncreaseAsyncScriptPriority,
- kEnablePriorityIncrease,
- kEnableLayoutBlockingThreshold,
- kLayoutBlockingThreshold,
- kMaxNumDelayableWhileLayoutBlocking,
- kMaxNumDelayableRequestsPerClient)));
- 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> low2(NewRequest("http://host/low", net::LOWEST));
- std::unique_ptr<TestRequest> low3(NewRequest("http://host/low", net::LOWEST));
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(low->started());
- EXPECT_TRUE(low2->started());
- EXPECT_FALSE(low3->started());
-
- high.reset();
- scheduler()->OnWillInsertBody(kChildId, kRouteId);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low3->started());
-}
-
-TEST_F(ResourceSchedulerTest,
- UseLayoutBlockingThresholdOneAndTwoDelayableLoadsUntilBodyInserted) {
- // Allow for two low priority requests to be in flight during the
- // layout-blocking phase of loading but only when there is not more than one
- // in-flight high priority request.
- const int kDeferLateScripts = 0;
- const int kIncreaseFontPriority = 0;
- const int kIncreaseAsyncScriptPriority = 0;
- const int kEnablePriorityIncrease = 0;
- const int kEnableLayoutBlockingThreshold = 1;
- const int kLayoutBlockingThreshold = 1;
- const int kMaxNumDelayableWhileLayoutBlocking = 2;
- const int kMaxNumDelayableRequestsPerClient = 10;
- ASSERT_TRUE(InitializeFieldTrials(base::StringPrintf(
- "ResourcePriorities/LayoutBlocking_%d%d%d%d%d_%d_%d_%d/",
- kDeferLateScripts,
- kIncreaseFontPriority,
- kIncreaseAsyncScriptPriority,
- kEnablePriorityIncrease,
- kEnableLayoutBlockingThreshold,
- kLayoutBlockingThreshold,
- kMaxNumDelayableWhileLayoutBlocking,
- kMaxNumDelayableRequestsPerClient)));
- InitializeScheduler();
- std::unique_ptr<TestRequest> high(
- NewRequest("http://host/high", net::HIGHEST));
- std::unique_ptr<TestRequest> high2(
- 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> low3(NewRequest("http://host/low", net::LOWEST));
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(high2->started());
- EXPECT_FALSE(low->started());
- EXPECT_FALSE(low2->started());
- EXPECT_FALSE(low3->started());
-
- high.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low->started());
- EXPECT_TRUE(low2->started());
- EXPECT_FALSE(low3->started());
-
- high2.reset();
- scheduler()->OnWillInsertBody(kChildId, kRouteId);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(low3->started());
-}
-
-TEST_F(ResourceSchedulerTest, TwentyMaxNumDelayableRequestsPerClient) {
- // Do not exceed 20 low-priority requests to be in flight across all hosts
- // at any point in time.
- const int kDeferLateScripts = 0;
- const int kIncreaseFontPriority = 0;
- const int kIncreaseAsyncScriptPriority = 0;
- const int kEnablePriorityIncrease = 0;
- const int kEnableLayoutBlockingThreshold = 0;
- const int kLayoutBlockingThreshold = 0;
- const int kMaxNumDelayableWhileLayoutBlocking = 1;
- const int kMaxNumDelayableRequestsPerClient = 20;
- ASSERT_TRUE(InitializeFieldTrials(base::StringPrintf(
- "ResourcePriorities/LayoutBlocking_%d%d%d%d%d_%d_%d_%d/",
- kDeferLateScripts,
- kIncreaseFontPriority,
- kIncreaseAsyncScriptPriority,
- kEnablePriorityIncrease,
- kEnableLayoutBlockingThreshold,
- kLayoutBlockingThreshold,
- kMaxNumDelayableWhileLayoutBlocking,
- kMaxNumDelayableRequestsPerClient)));
- InitializeScheduler();
-
- // Only load low priority resources if there's a body.
- scheduler()->OnWillInsertBody(kChildId, kRouteId);
-
- // Queue requests from different hosts until the total limit is reached.
- ScopedVector<TestRequest> lows_different_host;
- for (int i = 0; i < kMaxNumDelayableRequestsPerClient; ++i) {
- string url = "http://host" + base::IntToString(i) + "/low";
- lows_different_host.push_back(NewRequest(url.c_str(), net::LOWEST));
- EXPECT_TRUE(lows_different_host[i]->started());
- }
-
- std::unique_ptr<TestRequest> last_different_host(
- NewRequest("http://host_new/last", net::LOWEST));
- EXPECT_FALSE(last_different_host->started());
-}
-
-TEST_F(ResourceSchedulerTest,
- TwentyMaxNumDelayableRequestsPerClientWithEverythingEnabled) {
- // Do not exceed 20 low-priority requests to be in flight across all hosts
- // at any point in time and make sure it still works correctly when the other
- // options are toggled.
- const int kDeferLateScripts = 1;
- const int kIncreaseFontPriority = 1;
- const int kIncreaseAsyncScriptPriority = 1;
- const int kEnablePriorityIncrease = 1;
- const int kEnableLayoutBlockingThreshold = 1;
- const int kLayoutBlockingThreshold = 1;
- const int kMaxNumDelayableWhileLayoutBlocking = 1;
- const int kMaxNumDelayableRequestsPerClient = 20;
- ASSERT_TRUE(InitializeFieldTrials(base::StringPrintf(
- "ResourcePriorities/LayoutBlocking_%d%d%d%d%d_%d_%d_%d/",
- kDeferLateScripts,
- kIncreaseFontPriority,
- kIncreaseAsyncScriptPriority,
- kEnablePriorityIncrease,
- kEnableLayoutBlockingThreshold,
- kLayoutBlockingThreshold,
- kMaxNumDelayableWhileLayoutBlocking,
- kMaxNumDelayableRequestsPerClient)));
- InitializeScheduler();
-
- // Only load low priority resources if there's a body.
- scheduler()->OnWillInsertBody(kChildId, kRouteId);
-
- // Queue requests from different hosts until the total limit is reached.
- ScopedVector<TestRequest> lows_different_host;
- for (int i = 0; i < kMaxNumDelayableRequestsPerClient; ++i) {
- string url = "http://host" + base::IntToString(i) + "/low";
- lows_different_host.push_back(NewRequest(url.c_str(), net::LOWEST));
- EXPECT_TRUE(lows_different_host[i]->started());
- }
-
- std::unique_ptr<TestRequest> last_different_host(
- NewRequest("http://host_new/last", net::LOWEST));
- EXPECT_FALSE(last_different_host->started());
-}
-
} // unnamed namespace
} // namespace content
diff --git a/chromium/content/browser/loader/temporary_file_stream_unittest.cc b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
index d492254ee69..4db92d3111c 100644
--- a/chromium/content/browser/loader/temporary_file_stream_unittest.cc
+++ b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
@@ -111,7 +111,7 @@ TEST(TemporaryFileStreamTest, Basic) {
// Release everything. The file should be gone now.
file_stream_waiter.Release();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// The temporary should be gone now.
EXPECT_FALSE(base::PathExists(file_path));
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.cc b/chromium/content/browser/loader/upload_data_stream_builder.cc
index f6d614ae37b..d9bc7255323 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder.cc
@@ -15,7 +15,7 @@
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "content/browser/fileapi/upload_file_system_file_element_reader.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_file_element_reader.h"
@@ -31,45 +31,47 @@ class Entry;
namespace content {
namespace {
-// A subclass of net::UploadBytesElementReader which owns ResourceRequestBody.
+// A subclass of net::UploadBytesElementReader which owns
+// ResourceRequestBodyImpl.
class BytesElementReader : public net::UploadBytesElementReader {
public:
- BytesElementReader(ResourceRequestBody* resource_request_body,
- const ResourceRequestBody::Element& element)
+ BytesElementReader(ResourceRequestBodyImpl* resource_request_body,
+ const ResourceRequestBodyImpl::Element& element)
: net::UploadBytesElementReader(element.bytes(), element.length()),
resource_request_body_(resource_request_body) {
- DCHECK_EQ(ResourceRequestBody::Element::TYPE_BYTES, element.type());
+ DCHECK_EQ(ResourceRequestBodyImpl::Element::TYPE_BYTES, element.type());
}
~BytesElementReader() override {}
private:
- scoped_refptr<ResourceRequestBody> resource_request_body_;
+ scoped_refptr<ResourceRequestBodyImpl> resource_request_body_;
DISALLOW_COPY_AND_ASSIGN(BytesElementReader);
};
-// A subclass of net::UploadFileElementReader which owns ResourceRequestBody.
+// A subclass of net::UploadFileElementReader which owns
+// ResourceRequestBodyImpl.
// This class is necessary to ensure the BlobData and any attached shareable
// files survive until upload completion.
class FileElementReader : public net::UploadFileElementReader {
public:
- FileElementReader(ResourceRequestBody* resource_request_body,
+ FileElementReader(ResourceRequestBodyImpl* resource_request_body,
base::TaskRunner* task_runner,
- const ResourceRequestBody::Element& element)
+ const ResourceRequestBodyImpl::Element& element)
: net::UploadFileElementReader(task_runner,
element.path(),
element.offset(),
element.length(),
element.expected_modification_time()),
resource_request_body_(resource_request_body) {
- DCHECK_EQ(ResourceRequestBody::Element::TYPE_FILE, element.type());
+ DCHECK_EQ(ResourceRequestBodyImpl::Element::TYPE_FILE, element.type());
}
~FileElementReader() override {}
private:
- scoped_refptr<ResourceRequestBody> resource_request_body_;
+ scoped_refptr<ResourceRequestBodyImpl> resource_request_body_;
DISALLOW_COPY_AND_ASSIGN(FileElementReader);
};
@@ -77,22 +79,22 @@ class FileElementReader : public net::UploadFileElementReader {
} // namespace
std::unique_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
- ResourceRequestBody* body,
+ ResourceRequestBodyImpl* body,
storage::BlobStorageContext* blob_context,
storage::FileSystemContext* file_system_context,
base::SingleThreadTaskRunner* file_task_runner) {
std::vector<std::unique_ptr<net::UploadElementReader>> element_readers;
for (const auto& element : *body->elements()) {
switch (element.type()) {
- case ResourceRequestBody::Element::TYPE_BYTES:
+ case ResourceRequestBodyImpl::Element::TYPE_BYTES:
element_readers.push_back(
base::WrapUnique(new BytesElementReader(body, element)));
break;
- case ResourceRequestBody::Element::TYPE_FILE:
+ case ResourceRequestBodyImpl::Element::TYPE_FILE:
element_readers.push_back(base::WrapUnique(
new FileElementReader(body, file_task_runner, element)));
break;
- case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
+ case ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM:
// If |body| contains any filesystem URLs, the caller should have
// supplied a FileSystemContext.
DCHECK(file_system_context);
@@ -101,7 +103,7 @@ std::unique_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
file_system_context, element.filesystem_url(), element.offset(),
element.length(), element.expected_modification_time())));
break;
- case ResourceRequestBody::Element::TYPE_BLOB: {
+ case ResourceRequestBodyImpl::Element::TYPE_BLOB: {
DCHECK_EQ(std::numeric_limits<uint64_t>::max(), element.length());
DCHECK_EQ(0ul, element.offset());
std::unique_ptr<storage::BlobDataHandle> handle =
@@ -111,9 +113,9 @@ std::unique_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
std::move(handle), file_system_context, file_task_runner)));
break;
}
- case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY:
- case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION:
- case ResourceRequestBody::Element::TYPE_UNKNOWN:
+ case ResourceRequestBodyImpl::Element::TYPE_DISK_CACHE_ENTRY:
+ case ResourceRequestBodyImpl::Element::TYPE_BYTES_DESCRIPTION:
+ case ResourceRequestBodyImpl::Element::TYPE_UNKNOWN:
NOTREACHED();
break;
}
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.h b/chromium/content/browser/loader/upload_data_stream_builder.h
index fae5f3a70ca..9b2bfcbf275 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.h
+++ b/chromium/content/browser/loader/upload_data_stream_builder.h
@@ -27,7 +27,7 @@ class BlobStorageContext;
namespace content {
-class ResourceRequestBody;
+class ResourceRequestBodyImpl;
class CONTENT_EXPORT UploadDataStreamBuilder {
public:
@@ -35,14 +35,14 @@ class CONTENT_EXPORT UploadDataStreamBuilder {
//
// If |body| contains any blob references, the caller is responsible for
// making sure them outlive the returned value of UploadDataStream. We do this
- // by binding the BlobDataHandles of them to ResourceRequestBody in
+ // by binding the BlobDataHandles of them to ResourceRequestBodyImpl in
// ResourceDispatcherHostImpl::BeginRequest().
//
// |file_system_context| is used to create a FileStreamReader for files with
// filesystem URLs. |file_task_runner| is used to perform file operations
// when the data gets uploaded.
static std::unique_ptr<net::UploadDataStream> Build(
- ResourceRequestBody* body,
+ ResourceRequestBodyImpl* body,
storage::BlobStorageContext* blob_context,
storage::FileSystemContext* file_system_context,
base::SingleThreadTaskRunner* file_task_runner);
diff --git a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
index fc5cf956a36..c39d83cd0e8 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -15,7 +15,7 @@
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
@@ -38,7 +38,8 @@ namespace content {
TEST(UploadDataStreamBuilderTest, CreateUploadDataStream) {
base::MessageLoop message_loop;
{
- scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody;
+ scoped_refptr<ResourceRequestBodyImpl> request_body =
+ new ResourceRequestBodyImpl;
const std::string kBlob = "blobuuid";
const std::string kBlobData = "blobdata";
@@ -115,13 +116,14 @@ TEST(UploadDataStreamBuilderTest,
std::unique_ptr<BlobDataHandle> handle =
blob_storage_context.AddFinishedBlob(blob_data_builder.get());
- scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
+ scoped_refptr<ResourceRequestBodyImpl> request_body(
+ new ResourceRequestBodyImpl());
std::unique_ptr<net::UploadDataStream> upload(
UploadDataStreamBuilder::Build(
request_body.get(), &blob_storage_context, NULL,
base::ThreadTaskRunnerHandle::Get().get()));
- request_body = new ResourceRequestBody();
+ request_body = new ResourceRequestBodyImpl();
request_body->AppendBlob(blob_id);
request_body->AppendBlob(blob_id);
request_body->AppendBlob(blob_id);
@@ -159,7 +161,8 @@ TEST(UploadDataStreamBuilderTest,
TEST(UploadDataStreamBuilderTest, ResetUploadStreamWithBlob) {
base::MessageLoopForIO message_loop;
{
- scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody;
+ scoped_refptr<ResourceRequestBodyImpl> request_body =
+ new ResourceRequestBodyImpl;
const std::string kBlob = "blobuuid";
const std::string kBlobData = "blobdata";
diff --git a/chromium/content/browser/loader_delegate_impl.cc b/chromium/content/browser/loader_delegate_impl.cc
new file mode 100644
index 00000000000..36ba82a7287
--- /dev/null
+++ b/chromium/content/browser/loader_delegate_impl.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/loader_delegate_impl.h"
+
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+namespace {
+
+void NotifyLoadStateChangedOnUI(int child_id,
+ int route_id,
+ const GURL& url,
+ const net::LoadStateWithParam& load_state,
+ uint64_t upload_position,
+ uint64_t upload_size) {
+ RenderViewHostImpl* view = RenderViewHostImpl::FromID(child_id, route_id);
+ if (view)
+ view->LoadStateChanged(url, load_state, upload_position, upload_size);
+}
+
+void DidGetResourceResponseStartOnUI(
+ int render_process_id,
+ int render_frame_host,
+ std::unique_ptr<ResourceRequestDetails> details) {
+ RenderFrameHostImpl* host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_host);
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host));
+ if (!web_contents)
+ return;
+ web_contents->DidGetResourceResponseStart(*details.get());
+}
+
+void DidGetRedirectForResourceRequestOnUI(
+ int render_process_id,
+ int render_frame_host,
+ std::unique_ptr<ResourceRedirectDetails> details) {
+ RenderFrameHostImpl* host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_host);
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host));
+ if (!web_contents)
+ return;
+ web_contents->DidGetRedirectForResourceRequest(host, *details.get());
+}
+
+} // namespace
+
+LoaderDelegateImpl::~LoaderDelegateImpl() {}
+
+void LoaderDelegateImpl::LoadStateChanged(
+ int child_id,
+ int route_id,
+ const GURL& url,
+ const net::LoadStateWithParam& load_state,
+ uint64_t upload_position,
+ uint64_t upload_size) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&NotifyLoadStateChangedOnUI, child_id, route_id, url,
+ load_state, upload_position, upload_size));
+}
+
+void LoaderDelegateImpl::DidGetResourceResponseStart(
+ int render_process_id,
+ int render_frame_host,
+ std::unique_ptr<ResourceRequestDetails> details) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DidGetResourceResponseStartOnUI, render_process_id,
+ render_frame_host, base::Passed(std::move(details))));
+}
+
+void LoaderDelegateImpl::DidGetRedirectForResourceRequest(
+ int render_process_id,
+ int render_frame_host,
+ std::unique_ptr<ResourceRedirectDetails> details) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DidGetRedirectForResourceRequestOnUI, render_process_id,
+ render_frame_host, base::Passed(std::move(details))));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader_delegate_impl.h b/chromium/content/browser/loader_delegate_impl.h
new file mode 100644
index 00000000000..887347b0e69
--- /dev/null
+++ b/chromium/content/browser/loader_delegate_impl.h
@@ -0,0 +1,36 @@
+// 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_DELEGATE_IMPL_H_
+#define CONTENT_BROWSER_LOADER_DELEGATE_IMPL_H_
+
+#include "content/browser/loader/loader_delegate.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class CONTENT_EXPORT LoaderDelegateImpl : public LoaderDelegate {
+ public:
+ ~LoaderDelegateImpl() override;
+
+ // LoaderDelegate implementation:
+ void LoadStateChanged(int child_id,
+ int route_id,
+ const GURL& url,
+ const net::LoadStateWithParam& load_state,
+ uint64_t upload_position,
+ uint64_t upload_size) override;
+ void DidGetResourceResponseStart(
+ int render_process_id,
+ int render_frame_host,
+ std::unique_ptr<ResourceRequestDetails> details) override;
+ void DidGetRedirectForResourceRequest(
+ int render_process_id,
+ int render_frame_host,
+ std::unique_ptr<ResourceRedirectDetails> details) override;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_DELEGATE_IMPL_H_
diff --git a/chromium/content/browser/mach_broker_mac_unittest.cc b/chromium/content/browser/mach_broker_mac_unittest.cc
index 65eaa91a7c3..261f500a563 100644
--- a/chromium/content/browser/mach_broker_mac_unittest.cc
+++ b/chromium/content/browser/mach_broker_mac_unittest.cc
@@ -19,7 +19,9 @@ class MachBrokerTest : public testing::Test,
public base::PortProvider::Observer {
public:
MachBrokerTest()
- : event_(true, false), received_process_(base::kNullProcessHandle) {
+ : event_(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ received_process_(base::kNullProcessHandle) {
broker_.AddObserver(this);
}
~MachBrokerTest() override {
diff --git a/chromium/content/browser/manifest/manifest_browsertest.cc b/chromium/content/browser/manifest/manifest_browsertest.cc
index bcac1071485..cc6a9058602 100644
--- a/chromium/content/browser/manifest/manifest_browsertest.cc
+++ b/chromium/content/browser/manifest/manifest_browsertest.cc
@@ -247,7 +247,7 @@ IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, DynamicManifest) {
std::string manifest_url =
GetTestUrl("manifest", "dummy-manifest.json").spec();
ASSERT_TRUE(content::ExecuteScript(
- shell()->web_contents(), "setManifestTo('" + manifest_url + "')"));
+ shell(), "setManifestTo('" + manifest_url + "')"));
GetManifestAndWait();
EXPECT_FALSE(manifest().IsEmpty());
@@ -260,7 +260,7 @@ IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, DynamicManifest) {
std::string manifest_url =
GetTestUrl("manifest", "empty-manifest.json").spec();
ASSERT_TRUE(content::ExecuteScript(
- shell()->web_contents(), "setManifestTo('" + manifest_url + "')"));
+ shell(), "setManifestTo('" + manifest_url + "')"));
GetManifestAndWait();
EXPECT_TRUE(manifest().IsEmpty());
@@ -290,8 +290,8 @@ IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, CORSManifest) {
std::string manifest_url = cors_embedded_test_server()->GetURL(
"/manifest/dummy-manifest.json").spec();
- ASSERT_TRUE(content::ExecuteScript(shell()->web_contents(),
- "setManifestTo('" + manifest_url + "')"));
+ ASSERT_TRUE(
+ content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')"));
GetManifestAndWait();
EXPECT_TRUE(manifest().IsEmpty());
@@ -308,8 +308,8 @@ IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, CORSManifest) {
// it is actually fully loaded.
manifest_url =
embedded_test_server()->GetURL("/manifest/dummy-manifest.json").spec();
- ASSERT_TRUE(content::ExecuteScript(shell()->web_contents(),
- "setManifestTo('" + manifest_url + "')"));
+ ASSERT_TRUE(
+ content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')"));
GetManifestAndWait();
}
@@ -330,8 +330,8 @@ IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, CORSManifestWithAcessControls) {
std::string manifest_url = cors_embedded_test_server()->GetURL(
"/manifest/manifest-cors.json").spec();
- ASSERT_TRUE(content::ExecuteScript(shell()->web_contents(),
- "setManifestTo('" + manifest_url + "')"));
+ ASSERT_TRUE(
+ content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')"));
GetManifestAndWait();
EXPECT_FALSE(manifest().IsEmpty());
@@ -360,8 +360,8 @@ IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, MixedContentManifest) {
std::string manifest_url =
https_server->GetURL("/manifest/dummy-manifest.json").spec();
- ASSERT_TRUE(content::ExecuteScript(shell()->web_contents(),
- "setManifestTo('" + manifest_url + "')"));
+ ASSERT_TRUE(
+ content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')"));
GetManifestAndWait();
EXPECT_TRUE(manifest().IsEmpty());
@@ -441,8 +441,7 @@ IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, PushStateNavigation) {
{
TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
ASSERT_TRUE(content::ExecuteScript(
- shell()->web_contents(),
- "history.pushState({foo: \"bar\"}, 'page', 'page.html');"));
+ shell(), "history.pushState({foo: \"bar\"}, 'page', 'page.html');"));
navigation_observer.Wait();
}
@@ -470,7 +469,7 @@ IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, AnchorNavigation) {
{
TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
ASSERT_TRUE(content::ExecuteScript(
- shell()->web_contents(),
+ shell(),
"var a = document.createElement('a'); a.href='#foo';"
"document.body.appendChild(a); a.click();"));
navigation_observer.Wait();
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 684020f4564..b4c9ab02a6e 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.cc
+++ b/chromium/content/browser/media/android/browser_media_player_manager.cc
@@ -62,7 +62,7 @@ class BrowserSurfaceTexturePeer : public gpu::SurfaceTexturePeer {
void EstablishSurfaceTexturePeer(
base::ProcessHandle render_process_handle,
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
+ scoped_refptr<gl::SurfaceTexture> surface_texture,
int render_frame_id,
int player_id) override;
@@ -86,7 +86,7 @@ BrowserSurfaceTexturePeer::~BrowserSurfaceTexturePeer() {
void BrowserSurfaceTexturePeer::EstablishSurfaceTexturePeer(
base::ProcessHandle render_process_handle,
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
+ scoped_refptr<gl::SurfaceTexture> surface_texture,
int render_frame_id,
int player_id) {
if (!surface_texture.get())
@@ -130,7 +130,7 @@ void BrowserMediaPlayerManager::InitSurfaceTexturePeer() {
// static
void BrowserMediaPlayerManager::SetSurfacePeer(
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
+ scoped_refptr<gl::SurfaceTexture> surface_texture,
base::ProcessHandle render_process_handle,
int render_frame_id,
int player_id) {
@@ -173,7 +173,7 @@ void BrowserMediaPlayerManager::SetSurfacePeer(
}
if (player != player_manager->GetFullscreenPlayer()) {
- gfx::ScopedJavaSurface scoped_surface(surface_texture.get());
+ gl::ScopedJavaSurface scoped_surface(surface_texture.get());
player->SetVideoSurface(std::move(scoped_surface));
}
}
@@ -316,7 +316,7 @@ void BrowserMediaPlayerManager::DidExitFullscreen(bool release_media_player) {
if (release_media_player)
ReleaseFullscreenPlayer(player);
else
- player->SetVideoSurface(gfx::ScopedJavaSurface());
+ player->SetVideoSurface(gl::ScopedJavaSurface());
#endif // defined(USE_AURA)
}
@@ -328,8 +328,7 @@ void BrowserMediaPlayerManager::OnTimeUpdate(
RoutingID(), player_id, current_timestamp, current_time_ticks));
}
-void BrowserMediaPlayerManager::SetVideoSurface(
- gfx::ScopedJavaSurface surface) {
+void BrowserMediaPlayerManager::SetVideoSurface(gl::ScopedJavaSurface surface) {
MediaPlayerAndroid* player = GetFullscreenPlayer();
if (!player)
return;
@@ -466,14 +465,14 @@ void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
MediaPlayerAndroid* player = GetPlayer(player_id);
if (player) {
player->SetVideoSurface(
- gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
+ gl::ScopedJavaSurface::AcquireExternalSurface(surface));
}
}
void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
MediaPlayerAndroid* player = GetPlayer(player_id);
if (player)
- player->SetVideoSurface(gfx::ScopedJavaSurface());
+ player->SetVideoSurface(gl::ScopedJavaSurface());
}
void BrowserMediaPlayerManager::OnFrameInfoUpdated() {
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 15ca2fc1711..11bb42895db 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.h
+++ b/chromium/content/browser/media/android/browser_media_player_manager.h
@@ -59,7 +59,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// Pass a java surface object to the MediaPlayerAndroid object
// identified by render process handle, render frame ID and player ID.
- static void SetSurfacePeer(scoped_refptr<gfx::SurfaceTexture> surface_texture,
+ static void SetSurfacePeer(scoped_refptr<gl::SurfaceTexture> surface_texture,
base::ProcessHandle render_process_handle,
int render_frame_id,
int player_id);
@@ -75,7 +75,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// ContentVideoView::Client implementation.
void DidExitFullscreen(bool release_media_player) override;
- void SetVideoSurface(gfx::ScopedJavaSurface surface) override;
+ void SetVideoSurface(gl::ScopedJavaSurface surface) override;
// Called when browser player wants the renderer media element to seek.
// Any actual seek started by renderer will be handled by browser in OnSeek().
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 3141d2ad728..b720e691086 100644
--- a/chromium/content/browser/media/android/browser_surface_view_manager.cc
+++ b/chromium/content/browser/media/android/browser_surface_view_manager.cc
@@ -37,8 +37,7 @@ BrowserSurfaceViewManager::BrowserSurfaceViewManager(
BrowserSurfaceViewManager::~BrowserSurfaceViewManager() {}
-void BrowserSurfaceViewManager::SetVideoSurface(
- gfx::ScopedJavaSurface surface) {
+void BrowserSurfaceViewManager::SetVideoSurface(gl::ScopedJavaSurface surface) {
TRACE_EVENT0("media", "BrowserSurfaceViewManager::SetVideoSurface");
if (surface.IsEmpty()) {
DCHECK_NE(surface_id_, media::SurfaceManager::kNoSurfaceID);
@@ -107,7 +106,8 @@ void BrowserSurfaceViewManager::SendDestroyingVideoSurfaceIfRequired(
if (base::android::BuildInfo::GetInstance()->sdk_int() >= 18)
return;
- base::WaitableEvent waiter(false, false);
+ base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
// Unretained is okay because we're waiting on the callback.
if (BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
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 fbfeab45b68..f32f6b888ce 100644
--- a/chromium/content/browser/media/android/browser_surface_view_manager.h
+++ b/chromium/content/browser/media/android/browser_surface_view_manager.h
@@ -28,7 +28,7 @@ class CONTENT_EXPORT BrowserSurfaceViewManager
~BrowserSurfaceViewManager();
// ContentVideoView::Client overrides.
- void SetVideoSurface(gfx::ScopedJavaSurface surface) override;
+ void SetVideoSurface(gl::ScopedJavaSurface surface) override;
void DidExitFullscreen(bool release_media_player) override;
void OnCreateFullscreenSurface(const gfx::Size& video_natural_size);
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager.cc b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
index f8b8b3a5b18..5de94815e15 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
@@ -62,7 +62,13 @@ void AudioMirroringManager::RemoveDiverter(Diverter* diverter) {
// diverted, it is stopped.
for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
if (it->diverter == diverter) {
- ChangeRoute(&(*it), NULL);
+ // Stop the diverted flow.
+ RouteDivertedFlow(&(*it), NULL);
+
+ // Stop duplication flows.
+ for (auto& dup : it->duplications) {
+ diverter->StopDuplicating(dup.second);
+ }
routes_.erase(it);
return;
}
@@ -81,12 +87,12 @@ void AudioMirroringManager::StartMirroring(MirroringDestination* destination) {
sessions_.push_back(destination);
}
+ std::set<SourceFrameRef> candidates;
+
// Query the MirroringDestination to see which of the audio streams should be
// diverted.
- std::set<SourceFrameRef> candidates;
for (StreamRoutes::const_iterator it = routes_.begin(); it != routes_.end();
++it) {
- if (!it->destination || it->destination == destination)
candidates.insert(it->source_render_frame);
}
if (!candidates.empty()) {
@@ -108,9 +114,14 @@ void AudioMirroringManager::StopMirroring(MirroringDestination* destination) {
std::set<SourceFrameRef> redivert_candidates;
for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
if (it->destination == destination) {
- ChangeRoute(&(*it), NULL);
+ RouteDivertedFlow(&(*it), NULL);
redivert_candidates.insert(it->source_render_frame);
}
+ auto dup_it = it->duplications.find(destination);
+ if (dup_it != it->duplications.end()) {
+ it->diverter->StopDuplicating(dup_it->second);
+ it->duplications.erase(dup_it);
+ }
}
if (!redivert_candidates.empty())
InitiateQueriesToFindNewDestination(destination, redivert_candidates);
@@ -132,20 +143,30 @@ void AudioMirroringManager::InitiateQueriesToFindNewDestination(
for (Destinations::const_iterator it = sessions_.begin();
it != sessions_.end(); ++it) {
- if (*it != old_destination) {
- (*it)->QueryForMatches(
- candidates,
- base::Bind(&AudioMirroringManager::UpdateRoutesToDestination,
- base::Unretained(this),
- *it,
- true));
- }
+ if (*it == old_destination)
+ continue;
+
+ (*it)->QueryForMatches(
+ candidates,
+ base::Bind(&AudioMirroringManager::UpdateRoutesToDestination,
+ base::Unretained(this), *it, true));
}
}
void AudioMirroringManager::UpdateRoutesToDestination(
MirroringDestination* destination,
bool add_only,
+ const std::set<SourceFrameRef>& matches,
+ bool is_duplicate) {
+ if (is_duplicate)
+ UpdateRoutesToDuplicateDestination(destination, add_only, matches);
+ else
+ UpdateRoutesToDivertDestination(destination, add_only, matches);
+}
+
+void AudioMirroringManager::UpdateRoutesToDivertDestination(
+ MirroringDestination* destination,
+ bool add_only,
const std::set<SourceFrameRef>& matches) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -164,11 +185,11 @@ void AudioMirroringManager::UpdateRoutesToDestination(
if (matches.find(it->source_render_frame) != matches.end()) {
// Only change the route if the stream is not already being diverted.
if (!it->destination)
- ChangeRoute(&(*it), destination);
+ RouteDivertedFlow(&(*it), destination);
} else if (!add_only) {
// Only stop diverting if the stream is currently routed to |destination|.
if (it->destination == destination) {
- ChangeRoute(&(*it), NULL);
+ RouteDivertedFlow(&(*it), NULL);
redivert_candidates.insert(it->source_render_frame);
}
}
@@ -177,9 +198,47 @@ void AudioMirroringManager::UpdateRoutesToDestination(
InitiateQueriesToFindNewDestination(destination, redivert_candidates);
}
+void AudioMirroringManager::UpdateRoutesToDuplicateDestination(
+ MirroringDestination* destination,
+ bool add_only,
+ const std::set<SourceFrameRef>& matches) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (std::find(sessions_.begin(), sessions_.end(), destination) ==
+ sessions_.end()) {
+ return; // Query result callback invoked after StopMirroring().
+ }
+
+ for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
+ if (matches.find(it->source_render_frame) != matches.end()) {
+ // The same destination cannot have both a diverted audio flow and a
+ // duplicated flow from the same source.
+ DCHECK_NE(it->destination, destination);
+
+ media::AudioPushSink*& pusher = it->duplications[destination];
+ if (!pusher) {
+ pusher = destination->AddPushInput(it->diverter->GetAudioParameters());
+ DCHECK(pusher);
+ it->diverter->StartDuplicating(pusher);
+ }
+ } else if (!add_only) {
+ auto dup_it = it->duplications.find(destination);
+ if (dup_it != it->duplications.end()) {
+ it->diverter->StopDuplicating(dup_it->second);
+ it->duplications.erase(dup_it);
+ }
+ }
+ }
+}
+
// static
-void AudioMirroringManager::ChangeRoute(
- StreamRoutingState* route, MirroringDestination* new_destination) {
+void AudioMirroringManager::RouteDivertedFlow(
+ StreamRoutingState* route,
+ MirroringDestination* new_destination) {
+ // The same destination cannot have both a diverted audio flow and a
+ // duplicated flow from the same source.
+ DCHECK(route->duplications.find(new_destination) ==
+ route->duplications.end());
+
if (route->destination == new_destination)
return; // No change.
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager.h b/chromium/content/browser/media/capture/audio_mirroring_manager.h
index a624a0824be..b98cf018c59 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager.h
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager.h
@@ -32,6 +32,7 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_
+#include <map>
#include <set>
#include <utility>
#include <vector>
@@ -64,21 +65,33 @@ class CONTENT_EXPORT AudioMirroringManager {
// Asynchronously query whether this MirroringDestination wants to consume
// audio sourced from each of the |candidates|. |results_callback| is run
// to indicate which of them (or none) should have audio routed to this
- // MirroringDestination. |results_callback| must be run on the same thread
- // as the one that called QueryForMatches().
- typedef base::Callback<void(const std::set<SourceFrameRef>&)>
+ // MirroringDestination. The second parameter of |results_callback|
+ // indicates whether the MirroringDestination wants either: 1) exclusive
+ // access to a diverted audio flow versus 2) a duplicate copy of the audio
+ // flow. |results_callback| must be run on the same thread as the one that
+ // called QueryForMatches().
+ typedef base::Callback<void(const std::set<SourceFrameRef>&, bool)>
MatchesCallback;
virtual void QueryForMatches(
const std::set<SourceFrameRef>& candidates,
const MatchesCallback& results_callback) = 0;
// Create a consumer of audio data in the format specified by |params|, and
- // connect it as an input to mirroring. When Close() is called on the
- // returned AudioOutputStream, the input is disconnected and the object
- // becomes invalid.
+ // connect it as an input to mirroring. This is used to provide
+ // MirroringDestination with exclusive access to pull the audio flow from
+ // the source. When Close() is called on the returned AudioOutputStream, the
+ // input is disconnected and the object becomes invalid.
virtual media::AudioOutputStream* AddInput(
const media::AudioParameters& params) = 0;
+ // Create a consumer of audio data in the format specified by |params|, and
+ // connect it as an input to mirroring. This is used to provide
+ // MirroringDestination with duplicate audio data, which is pushed from the
+ // main audio flow. When Close() is called on the returned AudioPushSink,
+ // the input is disconnected and the object becomes invalid.
+ virtual media::AudioPushSink* AddPushInput(
+ const media::AudioParameters& params) = 0;
+
protected:
virtual ~MirroringDestination() {}
};
@@ -120,6 +133,11 @@ class CONTENT_EXPORT AudioMirroringManager {
// destination.
MirroringDestination* destination;
+ // The destinations to which audio stream is duplicated. AudioPushSink is
+ // owned by the Diverter, but AudioMirroringManager must guarantee
+ // StopDuplicating() is called to release them.
+ std::map<MirroringDestination*, media::AudioPushSink*> duplications;
+
StreamRoutingState(const SourceFrameRef& source_frame,
Diverter* stream_diverter);
StreamRoutingState(const StreamRoutingState& other);
@@ -136,17 +154,35 @@ class CONTENT_EXPORT AudioMirroringManager {
const std::set<SourceFrameRef>& candidates);
// MirroringDestination query callback. |matches| contains all RenderFrame
- // sources that will be diverted to |destination|. If |add_only| is false,
- // then any Diverters currently routed to |destination| but not found in
- // |matches| will be stopped.
+ // sources that will be diverted or duplicated to |destination|.
+ // If |add_only| is false, then any audio flows currently routed to
+ // |destination| but not found in |matches| will be stopped.
+ // If |is_duplicate| is true, the audio data flow will be duplicated to the
+ // destination instead of diverted.
void UpdateRoutesToDestination(MirroringDestination* destination,
bool add_only,
- const std::set<SourceFrameRef>& matches);
+ const std::set<SourceFrameRef>& matches,
+ bool is_duplicate);
+
+ // |matches| contains all RenderFrame sources that will be diverted to
+ // |destination|. If |add_only| is false, then any Diverters currently routed
+ // to |destination| but not found in |matches| will be stopped.
+ void UpdateRoutesToDivertDestination(MirroringDestination* destination,
+ bool add_only,
+ const std::set<SourceFrameRef>& matches);
+
+ // |matches| contains all RenderFrame sources that will be duplicated to
+ // |destination|. If |add_only| is false, then any Diverters currently
+ // duplicating to |destination| but not found in |matches| will be stopped.
+ void UpdateRoutesToDuplicateDestination(
+ MirroringDestination* destination,
+ bool add_only,
+ const std::set<SourceFrameRef>& matches);
// Starts diverting audio to the |new_destination|, if not NULL. Otherwise,
// stops diverting audio.
- static void ChangeRoute(StreamRoutingState* route,
- MirroringDestination* new_destination);
+ static void RouteDivertedFlow(StreamRoutingState* route,
+ MirroringDestination* new_destination);
// Routing table. Contains one entry for each Diverter.
StreamRoutes routes_;
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 616fd86234d..2b883521e5c 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
@@ -19,6 +19,7 @@
using media::AudioOutputStream;
using media::AudioParameters;
+using media::AudioPushSink;
using testing::_;
using testing::Invoke;
using testing::NotNull;
@@ -35,6 +36,8 @@ class MockDiverter : public AudioMirroringManager::Diverter {
MOCK_METHOD0(GetAudioParameters, const AudioParameters&());
MOCK_METHOD1(StartDiverting, void(AudioOutputStream*));
MOCK_METHOD0(StopDiverting, void());
+ MOCK_METHOD1(StartDuplicating, void(AudioPushSink*));
+ MOCK_METHOD1(StopDuplicating, void(AudioPushSink*));
};
class MockMirroringDestination
@@ -42,10 +45,13 @@ class MockMirroringDestination
public:
typedef AudioMirroringManager::SourceFrameRef SourceFrameRef;
- MockMirroringDestination(int render_process_id, int render_frame_id)
+ MockMirroringDestination(int render_process_id,
+ int render_frame_id,
+ bool is_duplication)
: render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
- query_count_(0) {}
+ query_count_(0),
+ is_duplication_(is_duplication) {}
MOCK_METHOD2(QueryForMatches,
void(const std::set<SourceFrameRef>& candidates,
@@ -53,6 +59,9 @@ class MockMirroringDestination
MOCK_METHOD1(AddInput,
media::AudioOutputStream*(const media::AudioParameters& params));
+ MOCK_METHOD1(AddPushInput,
+ media::AudioPushSink*(const media::AudioParameters& params));
+
void SimulateQuery(const std::set<SourceFrameRef>& candidates,
const MatchesCallback& results_callback) {
++query_count_;
@@ -62,7 +71,7 @@ class MockMirroringDestination
candidates.end()) {
result.insert(SourceFrameRef(render_process_id_, render_frame_id_));
}
- results_callback.Run(result);
+ results_callback.Run(result, is_duplication_);
}
media::AudioOutputStream* SimulateAddInput(
@@ -72,6 +81,13 @@ class MockMirroringDestination
return kNonNullPointer;
}
+ media::AudioPushSink* SimulateAddPushInput(
+ const media::AudioParameters& params) {
+ static AudioPushSink* const kNonNullPointer =
+ reinterpret_cast<AudioPushSink*>(0x11111110);
+ return kNonNullPointer;
+ }
+
int query_count() const {
return query_count_;
}
@@ -80,6 +96,7 @@ class MockMirroringDestination
const int render_process_id_;
const int render_frame_id_;
int query_count_;
+ bool is_duplication_;
};
} // namespace
@@ -96,19 +113,32 @@ class AudioMirroringManagerTest : public testing::Test {
AudioParameters::kAudioCDSampleRate, 16,
AudioParameters::kAudioCDSampleRate / 10) {}
- MockDiverter* CreateStream(
- int render_process_id, int render_frame_id, int expected_times_diverted) {
+ MockDiverter* CreateStream(int render_process_id,
+ int render_frame_id,
+ int expected_times_diverted,
+ int expected_times_duplicated) {
MockDiverter* const diverter = new MockDiverter();
- if (expected_times_diverted > 0) {
+
+ if (expected_times_diverted + expected_times_duplicated > 0) {
EXPECT_CALL(*diverter, GetAudioParameters())
- .Times(expected_times_diverted)
+ .Times(expected_times_diverted + expected_times_duplicated)
.WillRepeatedly(ReturnRef(params_));
+ }
+
+ if (expected_times_diverted > 0) {
EXPECT_CALL(*diverter, StartDiverting(NotNull()))
.Times(expected_times_diverted);
EXPECT_CALL(*diverter, StopDiverting())
.Times(expected_times_diverted);
}
+ if (expected_times_duplicated > 0) {
+ EXPECT_CALL(*diverter, StartDuplicating(NotNull()))
+ .Times(expected_times_duplicated);
+ EXPECT_CALL(*diverter, StopDuplicating(NotNull()))
+ .Times(expected_times_duplicated);
+ }
+
mirroring_manager_.AddDiverter(
render_process_id, render_frame_id, diverter);
@@ -121,7 +151,8 @@ class AudioMirroringManagerTest : public testing::Test {
}
void StartMirroringTo(const std::unique_ptr<MockMirroringDestination>& dest,
- int expected_inputs_added) {
+ int expected_inputs_added,
+ int expected_push_inputs_added) {
EXPECT_CALL(*dest, QueryForMatches(_, _))
.WillRepeatedly(Invoke(dest.get(),
&MockMirroringDestination::SimulateQuery));
@@ -133,6 +164,14 @@ class AudioMirroringManagerTest : public testing::Test {
.RetiresOnSaturation();
}
+ if (expected_push_inputs_added > 0) {
+ EXPECT_CALL(*dest, AddPushInput(Ref(params_)))
+ .Times(expected_push_inputs_added)
+ .WillRepeatedly(Invoke(
+ dest.get(), &MockMirroringDestination::SimulateAddPushInput))
+ .RetiresOnSaturation();
+ }
+
mirroring_manager_.StartMirroring(dest.get());
}
@@ -151,6 +190,17 @@ class AudioMirroringManagerTest : public testing::Test {
return count;
}
+ int CountStreamsDuplicatedTo(
+ const std::unique_ptr<MockMirroringDestination>& dest) const {
+ int count = 0;
+ for (StreamRoutes::const_iterator it = mirroring_manager_.routes_.begin();
+ it != mirroring_manager_.routes_.end(); ++it) {
+ if (it->duplications.find(dest.get()) != it->duplications.end())
+ ++count;
+ }
+ return count;
+ }
+
void ExpectNoLongerManagingAnything() const {
EXPECT_TRUE(mirroring_manager_.routes_.empty());
EXPECT_TRUE(mirroring_manager_.sessions_.empty());
@@ -176,8 +226,8 @@ const int kYetAnotherRenderFrameId = 7890;
TEST_F(AudioMirroringManagerTest, MirroringSessionOfNothing) {
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 0);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 0, 0);
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
StopMirroringTo(destination);
@@ -188,8 +238,8 @@ TEST_F(AudioMirroringManagerTest, MirroringSessionOfNothing) {
TEST_F(AudioMirroringManagerTest, TwoMirroringSessionsOfNothing) {
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 0);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 0, 0);
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
StopMirroringTo(destination);
@@ -197,8 +247,8 @@ TEST_F(AudioMirroringManagerTest, TwoMirroringSessionsOfNothing) {
const std::unique_ptr<MockMirroringDestination> another_destination(
new MockMirroringDestination(kAnotherRenderProcessId,
- kAnotherRenderFrameId));
- StartMirroringTo(another_destination, 0);
+ kAnotherRenderFrameId, false));
+ StartMirroringTo(another_destination, 0, 0);
EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
StopMirroringTo(another_destination);
@@ -211,10 +261,10 @@ TEST_F(AudioMirroringManagerTest, TwoMirroringSessionsOfNothing) {
// will be diverted to it.
TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundMirroringSession) {
MockDiverter* const stream =
- CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1, 0);
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
@@ -233,13 +283,13 @@ TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundMirroringSession) {
// will be diverted to it.
TEST_F(AudioMirroringManagerTest, StreamLifetimeWithinMirroringSession) {
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 1, 0);
EXPECT_EQ(0, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
MockDiverter* const stream =
- CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
@@ -258,11 +308,11 @@ TEST_F(AudioMirroringManagerTest, StreamLifetimeWithinMirroringSession) {
// go.
TEST_F(AudioMirroringManagerTest, StreamLifetimeAcrossTwoMirroringSessions) {
MockDiverter* const stream =
- CreateStream(kRenderProcessId, kRenderFrameId, 2);
+ CreateStream(kRenderProcessId, kRenderFrameId, 2, 0);
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
@@ -271,8 +321,8 @@ TEST_F(AudioMirroringManagerTest, StreamLifetimeAcrossTwoMirroringSessions) {
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
const std::unique_ptr<MockMirroringDestination> second_destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(second_destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(second_destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
EXPECT_EQ(1, second_destination->query_count());
@@ -297,38 +347,38 @@ TEST_F(AudioMirroringManagerTest, StreamLifetimeAcrossTwoMirroringSessions) {
// match for it.
TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_1) {
MockDiverter* const stream =
- CreateStream(kRenderProcessId, kRenderFrameId, 2);
+ CreateStream(kRenderProcessId, kRenderFrameId, 2, 0);
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
const std::unique_ptr<MockMirroringDestination> replacement_destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(replacement_destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(replacement_destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
- EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(1, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
StopMirroringTo(destination);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(2, replacement_destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(replacement_destination));
StopMirroringTo(replacement_destination);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(2, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
KillStream(stream);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(2, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
ExpectNoLongerManagingAnything();
@@ -338,38 +388,38 @@ TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_1) {
// operations that should have the same effects.
TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_2) {
MockDiverter* const stream =
- CreateStream(kRenderProcessId, kRenderFrameId, 2);
+ CreateStream(kRenderProcessId, kRenderFrameId, 2, 0);
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
const std::unique_ptr<MockMirroringDestination> replacement_destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(replacement_destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(replacement_destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
- EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(1, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
StopMirroringTo(destination);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(2, replacement_destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(replacement_destination));
KillStream(stream);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(2, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
StopMirroringTo(replacement_destination);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(2, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
ExpectNoLongerManagingAnything();
@@ -380,38 +430,38 @@ TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_2) {
// destination should never see the stream.
TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_3) {
MockDiverter* const stream =
- CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1, 0);
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
const std::unique_ptr<MockMirroringDestination> replacement_destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(replacement_destination, 0);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(replacement_destination, 0, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
- EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(1, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
KillStream(stream);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(1, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
StopMirroringTo(destination);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(1, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
StopMirroringTo(replacement_destination);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(1, replacement_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
ExpectNoLongerManagingAnything();
@@ -420,21 +470,21 @@ TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_3) {
// Tests that multiple streams are diverted/mixed to one destination.
TEST_F(AudioMirroringManagerTest, MultipleStreamsInOneMirroringSession) {
MockDiverter* const stream1 =
- CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1, 0);
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 3);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 3, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
MockDiverter* const stream2 =
- CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1, 0);
EXPECT_EQ(2, destination->query_count());
EXPECT_EQ(2, CountStreamsDivertedTo(destination));
MockDiverter* const stream3 =
- CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1, 0);
EXPECT_EQ(3, destination->query_count());
EXPECT_EQ(3, CountStreamsDivertedTo(destination));
@@ -461,50 +511,50 @@ TEST_F(AudioMirroringManagerTest, MultipleStreamsInOneMirroringSession) {
// has one stream mirrored to one destination.
TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
MockDiverter* const stream =
- CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1, 0);
const std::unique_ptr<MockMirroringDestination> destination(
- new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
- StartMirroringTo(destination, 1);
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
const std::unique_ptr<MockMirroringDestination> another_destination(
new MockMirroringDestination(kAnotherRenderProcessId,
- kAnotherRenderFrameId));
- StartMirroringTo(another_destination, 1);
+ kAnotherRenderFrameId, false));
+ StartMirroringTo(another_destination, 1, 0);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
- EXPECT_EQ(0, another_destination->query_count());
+ EXPECT_EQ(1, another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
MockDiverter* const another_stream =
- CreateStream(kAnotherRenderProcessId, kAnotherRenderFrameId, 1);
+ CreateStream(kAnotherRenderProcessId, kAnotherRenderFrameId, 1, 0);
EXPECT_EQ(2, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
- EXPECT_EQ(1, another_destination->query_count());
+ EXPECT_EQ(2, another_destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(another_destination));
KillStream(stream);
EXPECT_EQ(2, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(1, another_destination->query_count());
+ EXPECT_EQ(2, another_destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(another_destination));
MockDiverter* const yet_another_stream =
- CreateStream(kYetAnotherRenderProcessId, kYetAnotherRenderFrameId, 1);
+ CreateStream(kYetAnotherRenderProcessId, kYetAnotherRenderFrameId, 1, 0);
EXPECT_EQ(3, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(3, another_destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(another_destination));
const std::unique_ptr<MockMirroringDestination> yet_another_destination(
new MockMirroringDestination(kYetAnotherRenderProcessId,
- kYetAnotherRenderFrameId));
- StartMirroringTo(yet_another_destination, 1);
+ kYetAnotherRenderFrameId, false));
+ StartMirroringTo(yet_another_destination, 1, 0);
EXPECT_EQ(3, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(3, another_destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(another_destination));
EXPECT_EQ(1, yet_another_destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(yet_another_destination));
@@ -512,7 +562,7 @@ TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
StopMirroringTo(another_destination);
EXPECT_EQ(4, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(3, another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
EXPECT_EQ(2, yet_another_destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(yet_another_destination));
@@ -520,7 +570,7 @@ TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
StopMirroringTo(yet_another_destination);
EXPECT_EQ(5, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(3, another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
EXPECT_EQ(2, yet_another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(yet_another_destination));
@@ -528,7 +578,7 @@ TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
StopMirroringTo(destination);
EXPECT_EQ(5, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(3, another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
EXPECT_EQ(2, yet_another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(yet_another_destination));
@@ -536,7 +586,7 @@ TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
KillStream(another_stream);
EXPECT_EQ(5, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(3, another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
EXPECT_EQ(2, yet_another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(yet_another_destination));
@@ -544,7 +594,7 @@ TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
KillStream(yet_another_stream);
EXPECT_EQ(5, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(3, another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
EXPECT_EQ(2, yet_another_destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(yet_another_destination));
@@ -552,4 +602,173 @@ TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
ExpectNoLongerManagingAnything();
}
+// Tests that a stream can be successfully duplicated.
+TEST_F(AudioMirroringManagerTest, DuplicationToOneDestination) {
+ MockDiverter* const stream =
+ CreateStream(kRenderProcessId, kRenderFrameId, 1, 1);
+
+ const std::unique_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 1, 0);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
+ const std::unique_ptr<MockMirroringDestination> duplicated_destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, true));
+ StartMirroringTo(duplicated_destination, 0, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, duplicated_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination));
+
+ StopMirroringTo(duplicated_destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination));
+
+ KillStream(stream);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination));
+
+ ExpectNoLongerManagingAnything();
+}
+
+// Tests that a stream can be successfully duplicated to multiple destinations
+// simultaneously.
+TEST_F(AudioMirroringManagerTest, DuplicationToMultipleDestinations) {
+ MockDiverter* const stream =
+ CreateStream(kRenderProcessId, kRenderFrameId, 1, 2);
+
+ const std::unique_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(destination, 1, 0);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
+ const std::unique_ptr<MockMirroringDestination> duplicated_destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, true));
+ StartMirroringTo(duplicated_destination, 0, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, duplicated_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination));
+
+ const std::unique_ptr<MockMirroringDestination> duplicated_destination2(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, true));
+ StartMirroringTo(duplicated_destination2, 0, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, duplicated_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination));
+ EXPECT_EQ(1, duplicated_destination2->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination2));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination));
+ EXPECT_EQ(2, duplicated_destination2->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination2));
+
+ StopMirroringTo(duplicated_destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination));
+ EXPECT_EQ(2, duplicated_destination2->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination2));
+
+ StopMirroringTo(duplicated_destination2);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination));
+ EXPECT_EQ(2, duplicated_destination2->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination2));
+
+ KillStream(stream);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination));
+ EXPECT_EQ(2, duplicated_destination2->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination2));
+
+ ExpectNoLongerManagingAnything();
+}
+
+// Tests that duplication should not be affected when the major flow gets
+// diverted to another destination
+TEST_F(AudioMirroringManagerTest,
+ DuplicationUnaffectedBySwitchingDivertedFlow) {
+ MockDiverter* const stream =
+ CreateStream(kRenderProcessId, kRenderFrameId, 2, 1);
+
+ const std::unique_ptr<MockMirroringDestination> duplicated_destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, true));
+ StartMirroringTo(duplicated_destination, 0, 1);
+ EXPECT_EQ(1, duplicated_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination));
+
+ const std::unique_ptr<MockMirroringDestination> divert_destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(divert_destination, 1, 0);
+ EXPECT_EQ(1, divert_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(divert_destination));
+ EXPECT_EQ(1, duplicated_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination));
+
+ const std::unique_ptr<MockMirroringDestination> divert_destination2(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId, false));
+ StartMirroringTo(divert_destination2, 1, 0);
+ EXPECT_EQ(1, divert_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(divert_destination));
+ EXPECT_EQ(1, duplicated_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination));
+ EXPECT_EQ(1, divert_destination2->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(divert_destination2));
+
+ StopMirroringTo(divert_destination);
+ EXPECT_EQ(1, divert_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(divert_destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDuplicatedTo(duplicated_destination));
+ EXPECT_EQ(2, divert_destination2->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(divert_destination2));
+
+ StopMirroringTo(duplicated_destination);
+ EXPECT_EQ(1, divert_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(divert_destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination));
+ EXPECT_EQ(2, divert_destination2->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(divert_destination2));
+
+ StopMirroringTo(divert_destination2);
+ EXPECT_EQ(1, divert_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(divert_destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination));
+ EXPECT_EQ(2, divert_destination2->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(divert_destination2));
+
+ KillStream(stream);
+ EXPECT_EQ(1, divert_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(divert_destination));
+ EXPECT_EQ(2, duplicated_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDuplicatedTo(duplicated_destination));
+
+ ExpectNoLongerManagingAnything();
+}
+
} // namespace content
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 6aff1cbc36c..426bc895aac 100644
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.cc
+++ b/chromium/content/browser/media/capture/aura_window_capture_machine.cc
@@ -15,7 +15,7 @@
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/power_save_blocker.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"
@@ -85,11 +85,11 @@ bool AuraWindowCaptureMachine::InternalStart(
return false;
compositor->AddAnimationObserver(this);
- power_save_blocker_.reset(
- PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
- PowerSaveBlocker::kReasonOther,
- "DesktopCaptureDevice is running").release());
+ power_save_blocker_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ device::PowerSaveBlocker::kReasonOther, "DesktopCaptureDevice is running",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
return true;
}
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 ceb6e7f61af..848c3251de8 100644
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.h
+++ b/chromium/content/browser/media/capture/aura_window_capture_machine.h
@@ -18,19 +18,19 @@
#include "ui/compositor/compositor_animation_observer.h"
namespace cc {
-
class CopyOutputResult;
-
} // namespace cc
+namespace device {
+class PowerSaveBlocker;
+} // namespace device
+
namespace display_compositor {
class ReadbackYUVInterface;
}
namespace content {
-class PowerSaveBlocker;
-
class AuraWindowCaptureMachine
: public media::VideoCaptureMachine,
public aura::WindowObserver,
@@ -124,7 +124,7 @@ class AuraWindowCaptureMachine
// TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the
// screen from sleeping for the drive-by web.
- std::unique_ptr<PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
// WeakPtrs are used for the asynchronous capture callbacks passed to external
// modules. They are only valid on the UI thread and become invalidated
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura.cc b/chromium/content/browser/media/capture/cursor_renderer_aura.cc
index 6beceea099f..b4a2ba5a4a1 100644
--- a/chromium/content/browser/media/capture/cursor_renderer_aura.cc
+++ b/chromium/content/browser/media/capture/cursor_renderer_aura.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/time/default_tick_clock.h"
+#include "skia/ext/image_operations.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
@@ -102,7 +103,11 @@ bool CursorRendererAura::SnapshotCursorState(const gfx::Rect& region_in_frame) {
if (!window_->IsRootWindow()) {
aura::client::ActivationClient* activation_client =
aura::client::GetActivationClient(window_->GetRootWindow());
- DCHECK(activation_client);
+ if (!activation_client) {
+ DVLOG(2) << "Assume window inactive with invalid activation_client";
+ Clear();
+ return false;
+ }
aura::Window* active_window = activation_client->GetActiveWindow();
if (!active_window->Contains(window_)) {
// Return early if the target window is not active.
@@ -115,7 +120,7 @@ bool CursorRendererAura::SnapshotCursorState(const gfx::Rect& region_in_frame) {
if (cursor_display_setting_ == kCursorEnabledOnMouseMovement) {
if (cursor_displayed_) {
// Stop displaying cursor if there has been no mouse movement
- base::TimeDelta now = tick_clock_->NowTicks() - base::TimeTicks();
+ base::TimeTicks now = tick_clock_->NowTicks();
if ((now - last_mouse_movement_timestamp_) >
base::TimeDelta::FromSeconds(MAX_IDLE_TIME_SECONDS)) {
cursor_displayed_ = false;
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura.h b/chromium/content/browser/media/capture/cursor_renderer_aura.h
index eaa1790d471..19019cf50ac 100644
--- a/chromium/content/browser/media/capture/cursor_renderer_aura.h
+++ b/chromium/content/browser/media/capture/cursor_renderer_aura.h
@@ -13,7 +13,7 @@
#include "content/browser/media/capture/cursor_renderer.h"
#include "content/common/content_export.h"
#include "media/base/video_frame.h"
-#include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/window.h"
#include "ui/base/cursor/cursor.h"
#include "ui/events/event_handler.h"
@@ -67,7 +67,7 @@ class CONTENT_EXPORT CursorRendererAura : public CursorRenderer,
// Updated in mouse event listener and used to make a decision on
// when the cursor is rendered.
- base::TimeDelta last_mouse_movement_timestamp_;
+ base::TimeTicks last_mouse_movement_timestamp_;
float last_mouse_position_x_;
float last_mouse_position_y_;
bool cursor_displayed_;
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc b/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
index c3989455eb8..d4577b1ed18 100644
--- a/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
+++ b/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
@@ -64,9 +64,7 @@ class CursorRendererAuraTest : public AuraTestBase {
cursor_renderer_->tick_clock_ = clock;
}
- base::TimeDelta Now() {
- return cursor_renderer_->tick_clock_->NowTicks() - base::TimeTicks();
- }
+ base::TimeTicks Now() { return cursor_renderer_->tick_clock_->NowTicks(); }
bool CursorDisplayed() { return cursor_renderer_->cursor_displayed_; }
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.cc b/chromium/content/browser/media/capture/desktop_capture_device.cc
index a76bc8d4fd9..f5a73646a1f 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device.cc
@@ -22,7 +22,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/browser/power_save_blocker.h"
+#include "device/power_save_blocker/power_save_blocker.h"
#include "media/base/video_util.h"
#include "media/capture/content/capture_resolution_chooser.h"
#include "third_party/libyuv/include/libyuv/scale_argb.h"
@@ -75,9 +75,10 @@ class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
void SetNotificationWindowId(gfx::NativeViewId window_id);
private:
-
- // webrtc::DesktopCapturer::Callback interface
- void OnCaptureCompleted(webrtc::DesktopFrame* frame) override;
+ // webrtc::DesktopCapturer::Callback interface.
+ void OnCaptureResult(
+ webrtc::DesktopCapturer::Result result,
+ std::unique_ptr<webrtc::DesktopFrame> frame) override;
// Method that is scheduled on |task_runner_| to be called on regular interval
// to capture a frame.
@@ -126,11 +127,14 @@ class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
// The type of the capturer.
DesktopMediaID::Type capturer_type_;
+ // The system time when we receive the first frame.
+ base::TimeTicks first_ref_time_;
+
std::unique_ptr<webrtc::BasicDesktopFrame> black_frame_;
// TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the
// screen from sleeping for the drive-by web.
- std::unique_ptr<PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
@@ -169,11 +173,11 @@ void DesktopCaptureDevice::Core::AllocateAndStart(
params.requested_format.frame_size,
params.resolution_change_policy));
- power_save_blocker_.reset(
- PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
- PowerSaveBlocker::kReasonOther,
- "DesktopCaptureDevice is running").release());
+ power_save_blocker_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ device::PowerSaveBlocker::kReasonOther, "DesktopCaptureDevice is running",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
desktop_capturer_->Start(this);
@@ -187,28 +191,32 @@ void DesktopCaptureDevice::Core::SetNotificationWindowId(
desktop_capturer_->SetExcludedWindow(window_id);
}
-void DesktopCaptureDevice::Core::OnCaptureCompleted(
- webrtc::DesktopFrame* frame) {
+void DesktopCaptureDevice::Core::OnCaptureResult(
+ webrtc::DesktopCapturer::Result result,
+ std::unique_ptr<webrtc::DesktopFrame> frame) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(capture_in_progress_);
+ capture_in_progress_ = false;
+
+ bool success = result == webrtc::DesktopCapturer::Result::SUCCESS;
if (!first_capture_returned_) {
first_capture_returned_ = true;
if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
- IncrementDesktopCaptureCounter(frame ? FIRST_SCREEN_CAPTURE_SUCCEEDED
- : FIRST_SCREEN_CAPTURE_FAILED);
+ IncrementDesktopCaptureCounter(success ? FIRST_SCREEN_CAPTURE_SUCCEEDED
+ : FIRST_SCREEN_CAPTURE_FAILED);
} else {
- IncrementDesktopCaptureCounter(frame ? FIRST_WINDOW_CAPTURE_SUCCEEDED
- : FIRST_WINDOW_CAPTURE_FAILED);
+ IncrementDesktopCaptureCounter(success ? FIRST_WINDOW_CAPTURE_SUCCEEDED
+ : FIRST_WINDOW_CAPTURE_FAILED);
}
}
- capture_in_progress_ = false;
-
- if (!frame) {
- client_->OnError(FROM_HERE, "Failed to capture a frame.");
+ if (!success) {
+ if (result == webrtc::DesktopCapturer::Result::ERROR_PERMANENT)
+ client_->OnError(FROM_HERE, "The desktop capturer has failed.");
return;
}
+ DCHECK(frame);
if (!client_)
return;
@@ -224,8 +232,6 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
}
- std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame);
-
// If the frame size has changed, drop the output frame (if any), and
// determine the new output size.
if (!previous_frame_size_.equals(frame->size())) {
@@ -242,26 +248,22 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
if (output_size.is_empty())
return;
- // On OSX We receive a 1x1 frame when the shared window is minimized. It
- // cannot be subsampled to I420 and will be dropped downstream. So we replace
- // it with a black frame to avoid the video appearing frozen at the last
- // frame.
- if (frame->size().width() == 1 || frame->size().height() == 1) {
- if (!black_frame_) {
+ size_t output_bytes = output_size.width() * output_size.height() *
+ webrtc::DesktopFrame::kBytesPerPixel;
+ const uint8_t* output_data = nullptr;
+
+ if (frame->size().equals(webrtc::DesktopSize(1, 1))) {
+ // On OSX We receive a 1x1 frame when the shared window is minimized. It
+ // cannot be subsampled to I420 and will be dropped downstream. So we
+ // replace it with a black frame to avoid the video appearing frozen at the
+ // last frame.
+ if (!black_frame_ || !black_frame_->size().equals(output_size)) {
black_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
- memset(black_frame_->data(),
- 0,
+ memset(black_frame_->data(), 0,
black_frame_->stride() * black_frame_->size().height());
}
- owned_frame.reset();
- frame = black_frame_.get();
- }
-
- size_t output_bytes = output_size.width() * output_size.height() *
- webrtc::DesktopFrame::kBytesPerPixel;
- const uint8_t* output_data = NULL;
-
- if (!frame->size().equals(output_size)) {
+ output_data = black_frame_->data();
+ } else if (!frame->size().equals(output_size)) {
// Down-scale and/or letterbox to the target format if the frame does not
// match the output size.
@@ -278,16 +280,14 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
// using ARGBScaleClip().
const webrtc::DesktopRect output_rect =
ComputeLetterboxRect(output_size, frame->size());
- uint8_t* output_rect_data = output_frame_->data() +
- output_frame_->stride() * output_rect.top() +
- webrtc::DesktopFrame::kBytesPerPixel * output_rect.left();
- libyuv::ARGBScale(frame->data(), frame->stride(),
- frame->size().width(), frame->size().height(),
- output_rect_data, output_frame_->stride(),
- output_rect.width(), output_rect.height(),
- libyuv::kFilterBilinear);
+ uint8_t* output_rect_data =
+ output_frame_->GetFrameDataAtPos(output_rect.top_left());
+ libyuv::ARGBScale(frame->data(), frame->stride(), frame->size().width(),
+ frame->size().height(), output_rect_data,
+ output_frame_->stride(), output_rect.width(),
+ output_rect.height(), libyuv::kFilterBilinear);
output_data = output_frame_->data();
- } else if (IsFrameUnpackedOrInverted(frame)) {
+ } else if (IsFrameUnpackedOrInverted(frame.get())) {
// If |frame| is not packed top-to-bottom then create a packed top-to-bottom
// copy.
// This is required if the frame is inverted (see crbug.com/306876), or if
@@ -297,10 +297,8 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
memset(output_frame_->data(), 0, output_bytes);
}
- output_frame_->CopyPixelsFrom(
- *frame,
- webrtc::DesktopVector(),
- webrtc::DesktopRect::MakeSize(frame->size()));
+ output_frame_->CopyPixelsFrom(*frame, webrtc::DesktopVector(),
+ webrtc::DesktopRect::MakeSize(frame->size()));
output_data = output_frame_->data();
} else {
// If the captured frame matches the output size, we can return the pixel
@@ -308,12 +306,15 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
output_data = frame->data();
}
+ base::TimeTicks now = base::TimeTicks::Now();
+ if (first_ref_time_.is_null())
+ first_ref_time_ = now;
client_->OnIncomingCapturedData(
output_data, output_bytes,
media::VideoCaptureFormat(
gfx::Size(output_size.width(), output_size.height()),
requested_frame_rate_, media::PIXEL_FORMAT_ARGB),
- 0, base::TimeTicks::Now());
+ 0, now, now - first_ref_time_);
}
void DesktopCaptureDevice::Core::OnCaptureTimer() {
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 e4bef80946c..cca139f7333 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
@@ -41,22 +41,13 @@ const int kFrameRate = 30;
class MockDeviceClient : public media::VideoCaptureDevice::Client {
public:
- MOCK_METHOD5(OnIncomingCapturedData,
+ MOCK_METHOD6(OnIncomingCapturedData,
void(const uint8_t* data,
int length,
const media::VideoCaptureFormat& frame_format,
int rotation,
- const base::TimeTicks& timestamp));
- MOCK_METHOD9(OnIncomingCapturedYuvData,
- void(const uint8_t* y_data,
- const uint8_t* u_data,
- const uint8_t* v_data,
- size_t y_stride,
- size_t u_stride,
- size_t v_stride,
- const media::VideoCaptureFormat& frame_format,
- int clockwise_rotation,
- const base::TimeTicks& timestamp));
+ base::TimeTicks reference_time,
+ base::TimeDelta tiemstamp));
MOCK_METHOD0(DoReserveOutputBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
@@ -77,13 +68,13 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
}
void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer,
const media::VideoCaptureFormat& frame_format,
- const base::TimeTicks& timestamp) override {
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp) override {
DoOnIncomingCapturedBuffer();
}
void OnIncomingCapturedVideoFrame(
std::unique_ptr<Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp) override {
+ const scoped_refptr<media::VideoFrame>& frame) override {
DoOnIncomingCapturedVideoFrame();
}
std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
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 a1dc021360d..63f655f4b34 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -60,22 +60,13 @@ const uint8_t kFakePixelValueFirst = 2;
class MockDeviceClient : public media::VideoCaptureDevice::Client {
public:
- MOCK_METHOD5(OnIncomingCapturedData,
+ MOCK_METHOD6(OnIncomingCapturedData,
void(const uint8_t* data,
int length,
const media::VideoCaptureFormat& frame_format,
int rotation,
- const base::TimeTicks& timestamp));
- MOCK_METHOD9(OnIncomingCapturedYuvData,
- void(const uint8_t* y_data,
- const uint8_t* u_data,
- const uint8_t* v_data,
- size_t y_stride,
- size_t u_stride,
- size_t v_stride,
- const media::VideoCaptureFormat& frame_format,
- int clockwise_rotation,
- const base::TimeTicks& timestamp));
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp));
MOCK_METHOD0(DoReserveOutputBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
@@ -96,13 +87,13 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
}
void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer,
const media::VideoCaptureFormat& frame_format,
- const base::TimeTicks& timestamp) override {
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp) override {
DoOnIncomingCapturedBuffer();
}
void OnIncomingCapturedVideoFrame(
std::unique_ptr<Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp) override {
+ const scoped_refptr<media::VideoFrame>& frame) override {
DoOnIncomingCapturedVideoFrame();
}
std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
@@ -120,15 +111,15 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
// Creates a DesktopFrame that has the first pixel bytes set to
// kFakePixelValueFirst, and the rest of the bytes set to kFakePixelValue, for
// UnpackedFrame and InvertedFrame verification.
-webrtc::BasicDesktopFrame* CreateBasicFrame(const webrtc::DesktopSize& size) {
- webrtc::BasicDesktopFrame* frame = new webrtc::BasicDesktopFrame(size);
+std::unique_ptr<webrtc::BasicDesktopFrame> CreateBasicFrame(
+ const webrtc::DesktopSize& size) {
+ std::unique_ptr<webrtc::BasicDesktopFrame> frame(
+ new webrtc::BasicDesktopFrame(size));
DCHECK_EQ(frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel,
frame->stride());
- memset(frame->data(),
- kFakePixelValue,
+ memset(frame->data(), kFakePixelValue,
frame->stride() * frame->size().height());
- memset(frame->data(),
- kFakePixelValueFirst,
+ memset(frame->data(), kFakePixelValueFirst,
webrtc::DesktopFrame::kBytesPerPixel);
return frame;
}
@@ -138,16 +129,16 @@ webrtc::BasicDesktopFrame* CreateBasicFrame(const webrtc::DesktopSize& size) {
class InvertedDesktopFrame : public webrtc::DesktopFrame {
public:
// Takes ownership of |frame|.
- explicit InvertedDesktopFrame(webrtc::DesktopFrame* frame)
+ explicit InvertedDesktopFrame(std::unique_ptr<webrtc::DesktopFrame> frame)
: webrtc::DesktopFrame(
frame->size(),
-frame->stride(),
frame->data() + (frame->size().height() - 1) * frame->stride(),
- frame->shared_memory()),
- original_frame_(frame) {
+ frame->shared_memory()) {
set_dpi(frame->dpi());
set_capture_time_ms(frame->capture_time_ms());
mutable_updated_region()->Swap(frame->mutable_updated_region());
+ original_frame_ = std::move(frame);
}
~InvertedDesktopFrame() override {}
@@ -161,17 +152,15 @@ class InvertedDesktopFrame : public webrtc::DesktopFrame {
class UnpackedDesktopFrame : public webrtc::DesktopFrame {
public:
// Takes ownership of |frame|.
- explicit UnpackedDesktopFrame(webrtc::DesktopFrame* frame)
+ explicit UnpackedDesktopFrame(std::unique_ptr<webrtc::DesktopFrame> frame)
: webrtc::DesktopFrame(
frame->size(),
frame->stride() * 2,
new uint8_t[frame->stride() * 2 * frame->size().height()],
- NULL) {
+ nullptr) {
memset(data(), kFramePaddingValue, stride() * size().height());
- CopyPixelsFrom(*frame,
- webrtc::DesktopVector(),
+ CopyPixelsFrom(*frame, webrtc::DesktopVector(),
webrtc::DesktopRect::MakeSize(size()));
- delete frame;
}
~UnpackedDesktopFrame() override {
delete[] data_;
@@ -212,14 +201,15 @@ class FakeScreenCapturer : public webrtc::ScreenCapturer {
}
frame_index_++;
- webrtc::DesktopFrame* frame = CreateBasicFrame(size);
+ std::unique_ptr<webrtc::DesktopFrame> frame = CreateBasicFrame(size);
if (generate_inverted_frames_) {
- frame = new InvertedDesktopFrame(frame);
+ frame.reset(new InvertedDesktopFrame(std::move(frame)));
} else if (generate_cropped_frames_) {
- frame = new UnpackedDesktopFrame(frame);
+ frame.reset(new UnpackedDesktopFrame(std::move(frame)));
}
- callback_->OnCaptureCompleted(frame);
+ callback_->OnCaptureResult(webrtc::DesktopCapturer::Result::SUCCESS,
+ std::move(frame));
}
bool GetScreenList(ScreenList* screens) override { return false; }
@@ -269,8 +259,12 @@ class DesktopCaptureDeviceTest : public testing::Test {
std::move(capturer), DesktopMediaID::TYPE_SCREEN));
}
- void CopyFrame(const uint8_t* frame, int size,
- const media::VideoCaptureFormat&, int, base::TimeTicks) {
+ void CopyFrame(const uint8_t* frame,
+ int size,
+ const media::VideoCaptureFormat&,
+ int,
+ base::TimeTicks,
+ base::TimeDelta) {
ASSERT_TRUE(output_frame_);
ASSERT_EQ(output_frame_->stride() * output_frame_->size().height(), size);
memcpy(output_frame_->data(), frame, size);
@@ -296,15 +290,17 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
CreateScreenCaptureDevice(std::move(capturer));
media::VideoCaptureFormat format;
- base::WaitableEvent done_event(false, false);
+ base::WaitableEvent done_event(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
int frame_size;
std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_, _)).Times(0);
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
- DoAll(SaveArg<1>(&frame_size),
- SaveArg<2>(&format),
- InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ DoAll(SaveArg<1>(&frame_size), SaveArg<2>(&format),
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(640, 480);
@@ -332,14 +328,17 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
FormatChecker format_checker(gfx::Size(kTestFrameWidth1, kTestFrameHeight1),
gfx::Size(kTestFrameWidth1, kTestFrameHeight1));
- base::WaitableEvent done_event(false, false);
+ base::WaitableEvent done_event(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_, _)).Times(0);
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
- DoAll(WithArg<2>(Invoke(&format_checker,
- &FormatChecker::ExpectAcceptableSize)),
- InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ DoAll(WithArg<2>(Invoke(&format_checker,
+ &FormatChecker::ExpectAcceptableSize)),
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestFrameWidth1,
@@ -373,14 +372,17 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeFixedAspectRatio) {
std::unique_ptr<webrtc::DesktopCapturer>(mock_capturer));
FormatChecker format_checker(gfx::Size(888, 500), gfx::Size(532, 300));
- base::WaitableEvent done_event(false, false);
+ base::WaitableEvent done_event(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_,_)).Times(0);
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
- DoAll(WithArg<2>(Invoke(&format_checker,
- &FormatChecker::ExpectAcceptableSize)),
- InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ DoAll(WithArg<2>(Invoke(&format_checker,
+ &FormatChecker::ExpectAcceptableSize)),
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
media::VideoCaptureParams capture_params;
const gfx::Size high_def_16_by_9(1920, 1080);
@@ -418,14 +420,17 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
FormatChecker format_checker(gfx::Size(kTestFrameWidth1, kTestFrameHeight1),
gfx::Size(kTestFrameWidth2, kTestFrameHeight2));
- base::WaitableEvent done_event(false, false);
+ base::WaitableEvent done_event(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_,_)).Times(0);
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
- DoAll(WithArg<2>(Invoke(&format_checker,
- &FormatChecker::ExpectAcceptableSize)),
- InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ DoAll(WithArg<2>(Invoke(&format_checker,
+ &FormatChecker::ExpectAcceptableSize)),
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
media::VideoCaptureParams capture_params;
const gfx::Size high_def_16_by_9(1920, 1080);
@@ -461,7 +466,9 @@ TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) {
std::unique_ptr<webrtc::DesktopCapturer>(mock_capturer));
media::VideoCaptureFormat format;
- base::WaitableEvent done_event(false, false);
+ base::WaitableEvent done_event(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
int frame_size = 0;
output_frame_.reset(new webrtc::BasicDesktopFrame(
@@ -469,10 +476,11 @@ TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) {
std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_,_)).Times(0);
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
- DoAll(Invoke(this, &DesktopCaptureDeviceTest::CopyFrame),
- SaveArg<1>(&frame_size),
- InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ DoAll(Invoke(this, &DesktopCaptureDeviceTest::CopyFrame),
+ SaveArg<1>(&frame_size),
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestFrameWidth1,
@@ -489,8 +497,8 @@ TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) {
// Verifies that |output_frame_| has the same data as a packed frame of the
// same size.
- std::unique_ptr<webrtc::BasicDesktopFrame> expected_frame(CreateBasicFrame(
- webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1)));
+ std::unique_ptr<webrtc::BasicDesktopFrame> expected_frame = CreateBasicFrame(
+ webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1));
EXPECT_EQ(output_frame_->stride() * output_frame_->size().height(),
frame_size);
EXPECT_EQ(
@@ -505,7 +513,9 @@ TEST_F(DesktopCaptureDeviceTest, InvertedFrame) {
std::unique_ptr<webrtc::DesktopCapturer>(mock_capturer));
media::VideoCaptureFormat format;
- base::WaitableEvent done_event(false, false);
+ base::WaitableEvent done_event(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
int frame_size = 0;
output_frame_.reset(new webrtc::BasicDesktopFrame(
@@ -513,10 +523,11 @@ TEST_F(DesktopCaptureDeviceTest, InvertedFrame) {
std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_,_)).Times(0);
- EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
- DoAll(Invoke(this, &DesktopCaptureDeviceTest::CopyFrame),
- SaveArg<1>(&frame_size),
- InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
+ EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ DoAll(Invoke(this, &DesktopCaptureDeviceTest::CopyFrame),
+ SaveArg<1>(&frame_size),
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestFrameWidth1,
diff --git a/chromium/content/browser/media/capture/image_capture_impl.cc b/chromium/content/browser/media/capture/image_capture_impl.cc
index 7a22bc9f7f5..19002a320b5 100644
--- a/chromium/content/browser/media/capture/image_capture_impl.cc
+++ b/chromium/content/browser/media/capture/image_capture_impl.cc
@@ -4,56 +4,88 @@
#include "content/browser/media/capture/image_capture_impl.h"
+#include <utility>
+
#include "base/bind_helpers.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_stream_options.h"
#include "content/public/browser/browser_thread.h"
+#include "media/base/bind_to_current_loop.h"
#include "media/capture/video/video_capture_device.h"
namespace content {
namespace {
-void RunMojoCallback(const ImageCaptureImpl::TakePhotoCallback& callback,
- const std::string& mime_type,
- mojo::Array<uint8_t> data) {
- callback.Run(mime_type, std::move(data));
+void RunGetCapabilitiesCallbackOnUIThread(
+ const ImageCaptureImpl::GetCapabilitiesCallback& callback,
+ media::mojom::PhotoCapabilitiesPtr capabilities) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, base::Passed(&capabilities)));
}
-void RunTakePhotoCallback(const ImageCaptureImpl::TakePhotoCallback& callback,
- const std::string& mime_type,
- std::unique_ptr<std::vector<uint8_t>> data) {
- DCHECK(data.get());
+void RunFailedGetCapabilitiesCallback(
+ const ImageCaptureImpl::GetCapabilitiesCallback& cb) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ media::mojom::PhotoCapabilitiesPtr empty_capabilities =
+ media::mojom::PhotoCapabilities::New();
+ empty_capabilities->zoom = media::mojom::Range::New();
+ cb.Run(std::move(empty_capabilities));
+}
+
+void RunTakePhotoCallbackOnUIThread(
+ const ImageCaptureImpl::TakePhotoCallback& callback,
+ mojo::String mime_type,
+ mojo::Array<uint8_t> data) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RunMojoCallback, callback, mime_type,
- base::Passed(mojo::Array<uint8_t>::From(*data))));
+ base::Bind(callback, mime_type, base::Passed(std::move(data))));
+}
+
+void RunFailedTakePhotoCallback(const ImageCaptureImpl::TakePhotoCallback& cb) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ cb.Run("", mojo::Array<uint8_t>());
+}
+
+void GetCapabilitiesOnIOThread(
+ const mojo::String& source_id,
+ MediaStreamManager* media_stream_manager,
+ media::ScopedResultCallback<ImageCaptureImpl::GetCapabilitiesCallback>
+ callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ const int session_id =
+ media_stream_manager->VideoDeviceIdToSessionId(source_id);
+
+ if (session_id == StreamDeviceInfo::kNoId)
+ return;
+ media_stream_manager->video_capture_manager()->GetPhotoCapabilities(
+ session_id, std::move(callback));
}
-void TakePhotoOnIOThread(const mojo::String& source_id,
- const ImageCaptureImpl::TakePhotoCallback& callback,
- MediaStreamManager* media_stream_manager) {
+void TakePhotoOnIOThread(
+ const mojo::String& source_id,
+ MediaStreamManager* media_stream_manager,
+ media::ScopedResultCallback<ImageCaptureImpl::TakePhotoCallback> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const int session_id =
media_stream_manager->VideoDeviceIdToSessionId(source_id);
- if (session_id == StreamDeviceInfo::kNoId ||
- !media_stream_manager->video_capture_manager()->TakePhoto(
- session_id, base::Bind(&RunTakePhotoCallback, callback))) {
- std::unique_ptr<std::vector<uint8_t>> empty_vector(
- new std::vector<uint8_t>());
- RunTakePhotoCallback(callback, "", std::move(empty_vector));
- }
+ if (session_id == StreamDeviceInfo::kNoId)
+ return;
+ media_stream_manager->video_capture_manager()->TakePhoto(session_id,
+ std::move(callback));
}
} // anonymous namespace
// static
void ImageCaptureImpl::Create(
- mojo::InterfaceRequest<blink::mojom::ImageCapture> request) {
+ mojo::InterfaceRequest<media::mojom::ImageCapture> request) {
// |binding_| will take ownership of ImageCaptureImpl.
new ImageCaptureImpl(std::move(request));
}
@@ -65,25 +97,46 @@ void ImageCaptureImpl::GetCapabilities(
const GetCapabilitiesCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- blink::mojom::PhotoCapabilitiesPtr empty_capabilities =
- blink::mojom::PhotoCapabilities::New();
- empty_capabilities->zoom = blink::mojom::Range::New();
- callback.Run(std::move(empty_capabilities));
+ media::ScopedResultCallback<GetCapabilitiesCallback> scoped_callback(
+ base::Bind(&RunGetCapabilitiesCallbackOnUIThread, callback),
+ media::BindToCurrentLoop(base::Bind(&RunFailedGetCapabilitiesCallback)));
+
+ // BrowserMainLoop::GetInstance() can only be called on UI thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&GetCapabilitiesOnIOThread, source_id,
+ BrowserMainLoop::GetInstance()->media_stream_manager(),
+ base::Passed(&scoped_callback)));
}
+void ImageCaptureImpl::SetOptions(const mojo::String& source_id,
+ media::mojom::PhotoSettingsPtr settings,
+ const SetOptionsCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // TODO(mcasas): This is just a stub and needs wiring to VideoCaptureManager
+ // etc, see https://crbug.com/518807.
+ callback.Run(false);
+}
void ImageCaptureImpl::TakePhoto(const mojo::String& source_id,
const TakePhotoCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // media_stream_manager() can only be called on UI thread.
+
+ media::ScopedResultCallback<TakePhotoCallback> scoped_callback(
+ base::Bind(&RunTakePhotoCallbackOnUIThread, callback),
+ media::BindToCurrentLoop(base::Bind(&RunFailedTakePhotoCallback)));
+
+ // BrowserMainLoop::GetInstance() can only be called on UI thread.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&TakePhotoOnIOThread, source_id, callback,
- BrowserMainLoop::GetInstance()->media_stream_manager()));
+ base::Bind(&TakePhotoOnIOThread, source_id,
+ BrowserMainLoop::GetInstance()->media_stream_manager(),
+ base::Passed(&scoped_callback)));
}
ImageCaptureImpl::ImageCaptureImpl(
- mojo::InterfaceRequest<blink::mojom::ImageCapture> request)
+ mojo::InterfaceRequest<media::mojom::ImageCapture> request)
: binding_(this, std::move(request)) {}
} // namespace content
diff --git a/chromium/content/browser/media/capture/image_capture_impl.h b/chromium/content/browser/media/capture/image_capture_impl.h
index 8ca23dae59b..4aa90733d45 100644
--- a/chromium/content/browser/media/capture/image_capture_impl.h
+++ b/chromium/content/browser/media/capture/image_capture_impl.h
@@ -5,30 +5,34 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_IMAGE_CAPTURE_IMPL_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_IMAGE_CAPTURE_IMPL_H_
+#include "media/mojo/interfaces/image_capture.mojom.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/string.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "third_party/WebKit/public/platform/modules/imagecapture/image_capture.mojom.h"
namespace content {
-class ImageCaptureImpl : public blink::mojom::ImageCapture {
+class ImageCaptureImpl : public media::mojom::ImageCapture {
public:
static void Create(
- mojo::InterfaceRequest<blink::mojom::ImageCapture> request);
+ mojo::InterfaceRequest<media::mojom::ImageCapture> request);
~ImageCaptureImpl() override;
void GetCapabilities(const mojo::String& source_id,
const GetCapabilitiesCallback& callback) override;
+ void SetOptions(const mojo::String& source_id,
+ media::mojom::PhotoSettingsPtr settings,
+ const SetOptionsCallback& callback) override;
+
void TakePhoto(const mojo::String& source_id,
const TakePhotoCallback& callback) override;
private:
explicit ImageCaptureImpl(
- mojo::InterfaceRequest<blink::mojom::ImageCapture> request);
+ mojo::InterfaceRequest<media::mojom::ImageCapture> request);
- mojo::StrongBinding<blink::mojom::ImageCapture> binding_;
+ mojo::StrongBinding<media::mojom::ImageCapture> binding_;
DISALLOW_COPY_AND_ASSIGN(ImageCaptureImpl);
};
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 ce8f7f46419..4a58cc34c09 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
@@ -20,6 +20,7 @@
#include "content/public/browser/web_contents_media_capture_id.h"
#include "media/audio/virtual_audio_input_stream.h"
#include "media/audio/virtual_audio_output_stream.h"
+#include "media/audio/virtual_audio_sink.h"
#include "media/base/bind_to_current_loop.h"
namespace content {
@@ -29,10 +30,12 @@ class WebContentsAudioInputStream::Impl
public AudioMirroringManager::MirroringDestination {
public:
// Takes ownership of |mixer_stream|. The rest outlive this instance.
- Impl(int render_process_id, int main_render_frame_id,
+ Impl(int render_process_id,
+ int main_render_frame_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
- media::VirtualAudioInputStream* mixer_stream);
+ media::VirtualAudioInputStream* mixer_stream,
+ bool is_duplication);
// Open underlying VirtualAudioInputStream and start tracker.
bool Open();
@@ -86,9 +89,12 @@ class WebContentsAudioInputStream::Impl
const MatchesCallback& results_callback);
media::AudioOutputStream* AddInput(
const media::AudioParameters& params) override;
+ media::AudioPushSink* AddPushInput(
+ const media::AudioParameters& params) override;
// Callback which is run when |stream| is closed. Deletes |stream|.
void ReleaseInput(media::VirtualAudioOutputStream* stream);
+ void ReleasePushInput(media::VirtualAudioSink* sink);
// Called by WebContentsTracker when the target of the audio mirroring has
// changed.
@@ -112,16 +118,22 @@ class WebContentsAudioInputStream::Impl
// Current callback used to consume the resulting mixed audio data.
AudioInputCallback* callback_;
+ // If true, this WebContentsAudioInputStream will request a duplication of
+ // audio data, instead of exclusive access to pull the audio data.
+ bool is_duplication_;
+
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(Impl);
};
WebContentsAudioInputStream::Impl::Impl(
- int render_process_id, int main_render_frame_id,
+ int render_process_id,
+ int main_render_frame_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
- media::VirtualAudioInputStream* mixer_stream)
+ media::VirtualAudioInputStream* mixer_stream,
+ bool is_duplication)
: initial_render_process_id_(render_process_id),
initial_main_render_frame_id_(main_render_frame_id),
mirroring_manager_(mirroring_manager),
@@ -129,7 +141,8 @@ WebContentsAudioInputStream::Impl::Impl(
mixer_stream_(mixer_stream),
state_(CONSTRUCTED),
is_target_lost_(false),
- callback_(NULL) {
+ callback_(NULL),
+ is_duplication_(is_duplication) {
DCHECK(mirroring_manager_);
DCHECK(tracker_);
DCHECK(mixer_stream_);
@@ -283,7 +296,7 @@ void WebContentsAudioInputStream::Impl::QueryForMatchesOnUIThread(
}
}
- results_callback.Run(matches);
+ results_callback.Run(matches, is_duplication_);
}
media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput(
@@ -302,6 +315,20 @@ void WebContentsAudioInputStream::Impl::ReleaseInput(
delete stream;
}
+media::AudioPushSink* WebContentsAudioInputStream::Impl::AddPushInput(
+ const media::AudioParameters& params) {
+ // Note: The closure created here holds a reference to "this," which will
+ // guarantee the VirtualAudioInputStream (mixer_stream_) outlives the
+ // VirtualAudioSink.
+ return new media::VirtualAudioSink(params, mixer_stream_.get(),
+ base::Bind(&Impl::ReleasePushInput, this));
+}
+
+void WebContentsAudioInputStream::Impl::ReleasePushInput(
+ media::VirtualAudioSink* stream) {
+ delete stream;
+}
+
void WebContentsAudioInputStream::Impl::OnTargetChanged(bool had_target) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -322,7 +349,8 @@ WebContentsAudioInputStream* WebContentsAudioInputStream::Create(
const std::string& device_id,
const media::AudioParameters& params,
const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner,
- AudioMirroringManager* audio_mirroring_manager) {
+ AudioMirroringManager* audio_mirroring_manager,
+ bool is_duplication) {
int render_process_id;
int main_render_frame_id;
if (!WebContentsMediaCaptureId::ExtractTabCaptureTarget(
@@ -331,21 +359,27 @@ WebContentsAudioInputStream* WebContentsAudioInputStream::Create(
}
return new WebContentsAudioInputStream(
- render_process_id, main_render_frame_id,
- audio_mirroring_manager,
+ render_process_id, main_render_frame_id, audio_mirroring_manager,
new WebContentsTracker(false),
new media::VirtualAudioInputStream(
params, worker_task_runner,
- media::VirtualAudioInputStream::AfterCloseCallback()));
+ media::VirtualAudioInputStream::AfterCloseCallback()),
+ is_duplication);
}
WebContentsAudioInputStream::WebContentsAudioInputStream(
- int render_process_id, int main_render_frame_id,
+ int render_process_id,
+ int main_render_frame_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
- media::VirtualAudioInputStream* mixer_stream)
- : impl_(new Impl(render_process_id, main_render_frame_id,
- mirroring_manager, tracker, mixer_stream)) {}
+ media::VirtualAudioInputStream* mixer_stream,
+ bool is_duplication)
+ : impl_(new Impl(render_process_id,
+ main_render_frame_id,
+ mirroring_manager,
+ tracker,
+ mixer_stream,
+ is_duplication)) {}
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 ef994e83ac9..1c444434767 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,7 +61,8 @@ 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);
+ AudioMirroringManager* audio_mirroring_manager,
+ bool is_duplication);
private:
friend class WebContentsAudioInputStreamTest;
@@ -73,11 +74,12 @@ class CONTENT_EXPORT WebContentsAudioInputStream
// thread, and the VirtualAudioOuputStreams on the audio thread.
class Impl;
- WebContentsAudioInputStream(
- int render_process_id, int main_render_frame_id,
- AudioMirroringManager* mirroring_manager,
- const scoped_refptr<WebContentsTracker>& tracker,
- media::VirtualAudioInputStream* mixer_stream);
+ WebContentsAudioInputStream(int render_process_id,
+ int main_render_frame_id,
+ AudioMirroringManager* mirroring_manager,
+ const scoped_refptr<WebContentsTracker>& tracker,
+ media::VirtualAudioInputStream* mixer_stream,
+ bool is_duplication);
~WebContentsAudioInputStream() override;
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
index 6ec220f767a..35243a6ce1c 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
@@ -33,9 +33,11 @@ using ::testing::NotNull;
using ::testing::SaveArg;
using ::testing::WithArgs;
+using media::AudioBus;
using media::AudioInputStream;
using media::AudioOutputStream;
using media::AudioParameters;
+using media::AudioPushSink;
using media::SineWaveAudioSource;
using media::VirtualAudioInputStream;
using media::VirtualAudioOutputStream;
@@ -119,12 +121,12 @@ class MockVirtualAudioInputStream : public VirtualAudioInputStream {
ON_CALL(*this, GetAutomaticGainControl())
.WillByDefault(
Invoke(&real_, &VirtualAudioInputStream::GetAutomaticGainControl));
- ON_CALL(*this, AddOutputStream(NotNull(), _))
+ ON_CALL(*this, AddInputProvider(NotNull(), _))
.WillByDefault(
- Invoke(&real_, &VirtualAudioInputStream::AddOutputStream));
- ON_CALL(*this, RemoveOutputStream(NotNull(), _))
+ Invoke(&real_, &VirtualAudioInputStream::AddInputProvider));
+ ON_CALL(*this, RemoveInputProvider(NotNull(), _))
.WillByDefault(
- Invoke(&real_, &VirtualAudioInputStream::RemoveOutputStream));
+ Invoke(&real_, &VirtualAudioInputStream::RemoveInputProvider));
}
~MockVirtualAudioInputStream() {
@@ -140,10 +142,12 @@ class MockVirtualAudioInputStream : public VirtualAudioInputStream {
MOCK_METHOD0(GetVolume, double());
MOCK_METHOD1(SetAutomaticGainControl, bool(bool));
MOCK_METHOD0(GetAutomaticGainControl, bool());
- MOCK_METHOD2(AddOutputStream, void(VirtualAudioOutputStream*,
- const AudioParameters&));
- MOCK_METHOD2(RemoveOutputStream, void(VirtualAudioOutputStream*,
- const AudioParameters&));
+ MOCK_METHOD2(AddInputProvider,
+ void(media::AudioConverter::InputCallback*,
+ const AudioParameters&));
+ MOCK_METHOD2(RemoveInputProvider,
+ void(media::AudioConverter::InputCallback*,
+ const AudioParameters&));
private:
void OnRealStreamHasClosed(VirtualAudioInputStream* stream) {
@@ -175,7 +179,7 @@ class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
} // namespace
-class WebContentsAudioInputStreamTest : public testing::Test {
+class WebContentsAudioInputStreamTest : public testing::TestWithParam<bool> {
public:
WebContentsAudioInputStreamTest()
: thread_bundle_(new TestBrowserThreadBundle(
@@ -188,7 +192,8 @@ class WebContentsAudioInputStreamTest : public testing::Test {
destination_(NULL),
current_render_process_id_(kRenderProcessId),
current_render_frame_id_(kRenderFrameId),
- on_data_event_(false, false) {
+ on_data_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED) {
audio_thread_.Start();
}
@@ -203,6 +208,12 @@ class WebContentsAudioInputStreamTest : public testing::Test {
DCHECK(sources_.empty());
}
+ // If this value is true, we are testing a WebContentsAudioInputStream
+ // instance, which requests duplicate audio.
+ // Otherwise, we are testing a WebContentsAudioInputStream instance, which
+ // requests diverting audio.
+ bool is_duplication() const { return GetParam(); }
+
void Open() {
mock_vais_ = new MockVirtualAudioInputStream(audio_thread_.task_runner());
EXPECT_CALL(*mock_vais_, Open());
@@ -222,8 +233,8 @@ class WebContentsAudioInputStreamTest : public testing::Test {
wcais_ = new WebContentsAudioInputStream(
current_render_process_id_, current_render_frame_id_,
- mock_mirroring_manager_.get(),
- mock_tracker_, mock_vais_);
+ mock_mirroring_manager_.get(), mock_tracker_, mock_vais_,
+ is_duplication());
wcais_->Open();
}
@@ -270,36 +281,62 @@ class WebContentsAudioInputStreamTest : public testing::Test {
// Note: WCAIS posts a task to invoke
// MockAudioMirroringManager::StartMirroring() on the IO thread, which
// causes our mock to set |destination_|. Block until that has happened.
- base::WaitableEvent done(false, false);
+ base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE, base::Bind(
&base::WaitableEvent::Signal, base::Unretained(&done)));
done.Wait();
ASSERT_TRUE(destination_);
- EXPECT_CALL(*mock_vais_, AddOutputStream(NotNull(), _))
+ EXPECT_CALL(*mock_vais_, AddInputProvider(NotNull(), _))
.RetiresOnSaturation();
// Later, when stream is closed:
- EXPECT_CALL(*mock_vais_, RemoveOutputStream(NotNull(), _))
+ EXPECT_CALL(*mock_vais_, RemoveInputProvider(NotNull(), _))
.RetiresOnSaturation();
const AudioParameters& params = TestAudioParameters();
- AudioOutputStream* const out = destination_->AddInput(params);
- ASSERT_TRUE(out);
- streams_.push_back(out);
- EXPECT_TRUE(out->Open());
SineWaveAudioSource* const source = new SineWaveAudioSource(
params.channel_layout(), 200.0, params.sample_rate());
sources_.push_back(source);
- out->Start(source);
+ if (is_duplication()) {
+ media::AudioPushSink* out = destination_->AddPushInput(params);
+ ASSERT_TRUE(out);
+ sinks_.push_back(out);
+ std::unique_ptr<media::AudioBus> audio_data = AudioBus::Create(params);
+ base::TimeTicks now = base::TimeTicks::Now();
+ // 20 Audio buses are enough for all test cases.
+ const int kAudioBusesNumber = 20;
+ for (int i = 0; i < kAudioBusesNumber; i++) {
+ int frames = source->OnMoreData(audio_data.get(), 0, 0);
+ std::unique_ptr<media::AudioBus> copy = AudioBus::Create(params);
+ audio_data->CopyTo(copy.get());
+ out->OnData(std::move(copy), now);
+ now += base::TimeDelta::FromMillisecondsD(
+ frames * params.GetMicrosecondsPerFrame());
+ }
+ } else {
+ AudioOutputStream* const out = destination_->AddInput(params);
+ ASSERT_TRUE(out);
+ streams_.push_back(out);
+ EXPECT_TRUE(out->Open());
+ out->Start(source);
+ }
}
void RemoveOneInputInFIFOOrder() {
- ASSERT_FALSE(streams_.empty());
- AudioOutputStream* const out = streams_.front();
- streams_.pop_front();
- out->Stop();
- out->Close(); // Self-deletes.
+ if (is_duplication()) {
+ ASSERT_FALSE(sinks_.empty());
+ AudioPushSink* const out = sinks_.front();
+ sinks_.pop_front();
+ out->Close(); // Self-deletes.
+ } else {
+ ASSERT_FALSE(streams_.empty());
+ AudioOutputStream* const out = streams_.front();
+ streams_.pop_front();
+ out->Stop();
+ out->Close(); // Self-deletes.
+ }
ASSERT_TRUE(!sources_.empty());
delete sources_.front();
sources_.pop_front();
@@ -390,6 +427,7 @@ class WebContentsAudioInputStreamTest : public testing::Test {
// Streams provided by calls to WebContentsAudioInputStream::AddInput(). Each
// is started with a simulated source of audio data.
std::list<AudioOutputStream*> streams_;
+ std::list<media::AudioPushSink*> sinks_;
std::list<SineWaveAudioSource*> sources_; // 1:1 with elements in streams_.
base::WaitableEvent on_data_event_;
@@ -401,12 +439,12 @@ class WebContentsAudioInputStreamTest : public testing::Test {
RunOnAudioThread(base::Bind(&WebContentsAudioInputStreamTest::method, \
base::Unretained(this)))
-TEST_F(WebContentsAudioInputStreamTest, OpenedButNeverStarted) {
+TEST_P(WebContentsAudioInputStreamTest, OpenedButNeverStarted) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Close);
}
-TEST_F(WebContentsAudioInputStreamTest, MirroringNothing) {
+TEST_P(WebContentsAudioInputStreamTest, MirroringNothing) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Start);
WaitForData();
@@ -414,7 +452,7 @@ TEST_F(WebContentsAudioInputStreamTest, MirroringNothing) {
RUN_ON_AUDIO_THREAD(Close);
}
-TEST_F(WebContentsAudioInputStreamTest, MirroringOutputOutlivesSession) {
+TEST_P(WebContentsAudioInputStreamTest, MirroringOutputOutlivesSession) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Start);
RUN_ON_AUDIO_THREAD(AddAnotherInput);
@@ -424,7 +462,7 @@ TEST_F(WebContentsAudioInputStreamTest, MirroringOutputOutlivesSession) {
RUN_ON_AUDIO_THREAD(RemoveOneInputInFIFOOrder);
}
-TEST_F(WebContentsAudioInputStreamTest, MirroringOutputWithinSession) {
+TEST_P(WebContentsAudioInputStreamTest, MirroringOutputWithinSession) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Start);
RUN_ON_AUDIO_THREAD(AddAnotherInput);
@@ -434,7 +472,7 @@ TEST_F(WebContentsAudioInputStreamTest, MirroringOutputWithinSession) {
RUN_ON_AUDIO_THREAD(Close);
}
-TEST_F(WebContentsAudioInputStreamTest, MirroringNothingWithTargetChange) {
+TEST_P(WebContentsAudioInputStreamTest, MirroringNothingWithTargetChange) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Start);
RUN_ON_AUDIO_THREAD(ChangeMirroringTarget);
@@ -442,7 +480,7 @@ TEST_F(WebContentsAudioInputStreamTest, MirroringNothingWithTargetChange) {
RUN_ON_AUDIO_THREAD(Close);
}
-TEST_F(WebContentsAudioInputStreamTest, MirroringOneStreamAfterTargetChange) {
+TEST_P(WebContentsAudioInputStreamTest, MirroringOneStreamAfterTargetChange) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Start);
RUN_ON_AUDIO_THREAD(ChangeMirroringTarget);
@@ -453,7 +491,7 @@ TEST_F(WebContentsAudioInputStreamTest, MirroringOneStreamAfterTargetChange) {
RUN_ON_AUDIO_THREAD(RemoveOneInputInFIFOOrder);
}
-TEST_F(WebContentsAudioInputStreamTest, MirroringOneStreamWithTargetChange) {
+TEST_P(WebContentsAudioInputStreamTest, MirroringOneStreamWithTargetChange) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Start);
RUN_ON_AUDIO_THREAD(AddAnotherInput);
@@ -467,7 +505,7 @@ TEST_F(WebContentsAudioInputStreamTest, MirroringOneStreamWithTargetChange) {
RUN_ON_AUDIO_THREAD(RemoveOneInputInFIFOOrder);
}
-TEST_F(WebContentsAudioInputStreamTest, MirroringLostTarget) {
+TEST_P(WebContentsAudioInputStreamTest, MirroringLostTarget) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Start);
RUN_ON_AUDIO_THREAD(AddAnotherInput);
@@ -478,7 +516,7 @@ TEST_F(WebContentsAudioInputStreamTest, MirroringLostTarget) {
RUN_ON_AUDIO_THREAD(Close);
}
-TEST_F(WebContentsAudioInputStreamTest, MirroringMultipleStreamsAndTargets) {
+TEST_P(WebContentsAudioInputStreamTest, MirroringMultipleStreamsAndTargets) {
RUN_ON_AUDIO_THREAD(Open);
RUN_ON_AUDIO_THREAD(Start);
RUN_ON_AUDIO_THREAD(AddAnotherInput);
@@ -502,4 +540,6 @@ TEST_F(WebContentsAudioInputStreamTest, MirroringMultipleStreamsAndTargets) {
RUN_ON_AUDIO_THREAD(Close);
}
+INSTANTIATE_TEST_CASE_P(, WebContentsAudioInputStreamTest, ::testing::Bool());
+
} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_audio_muter.cc b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
index e99c768d4bc..63df637666d 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_muter.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
@@ -104,7 +104,7 @@ class WebContentsAudioMuter::MuteDestination
if (contents_containing_frame == web_contents_)
matches.insert(*i);
}
- results_callback.Run(matches);
+ results_callback.Run(matches, false);
}
media::AudioOutputStream* AddInput(
@@ -112,6 +112,12 @@ class WebContentsAudioMuter::MuteDestination
return new AudioDiscarder(params);
}
+ media::AudioPushSink* AddPushInput(
+ const media::AudioParameters& params) override {
+ NOTREACHED();
+ return nullptr;
+ }
+
WebContents* const web_contents_;
DISALLOW_COPY_AND_ASSIGN(MuteDestination);
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 1babd42075a..9193125b961 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
@@ -336,22 +336,13 @@ class StubClient : public media::VideoCaptureDevice::Client {
}
~StubClient() override {}
- MOCK_METHOD5(OnIncomingCapturedData,
+ MOCK_METHOD6(OnIncomingCapturedData,
void(const uint8_t* data,
int length,
const media::VideoCaptureFormat& frame_format,
int rotation,
- const base::TimeTicks& timestamp));
- MOCK_METHOD9(OnIncomingCapturedYuvData,
- void(const uint8_t* y_data,
- const uint8_t* u_data,
- const uint8_t* v_data,
- size_t y_stride,
- size_t u_stride,
- size_t v_stride,
- const media::VideoCaptureFormat& frame_format,
- int clockwise_rotation,
- const base::TimeTicks& timestamp));
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp));
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
@@ -374,14 +365,14 @@ class StubClient : public media::VideoCaptureDevice::Client {
// Trampoline method to workaround GMOCK problems with std::unique_ptr<>.
void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer,
const media::VideoCaptureFormat& frame_format,
- const base::TimeTicks& timestamp) override {
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp) override {
DoOnIncomingCapturedBuffer();
}
void OnIncomingCapturedVideoFrame(
std::unique_ptr<Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp) override {
+ const scoped_refptr<media::VideoFrame>& frame) override {
EXPECT_FALSE(frame->visible_rect().IsEmpty());
EXPECT_EQ(media::PIXEL_FORMAT_I420, frame->format());
double frame_rate = 0;
diff --git a/chromium/content/browser/media/capture/window_activity_tracker_mac.h b/chromium/content/browser/media/capture/window_activity_tracker_mac.h
index 64c91a03ea1..9fa880a0f57 100644
--- a/chromium/content/browser/media/capture/window_activity_tracker_mac.h
+++ b/chromium/content/browser/media/capture/window_activity_tracker_mac.h
@@ -49,7 +49,6 @@ class CONTENT_EXPORT WindowActivityTrackerMac : public WindowActivityTracker {
private:
void OnMouseActivity();
- NSView* const view_;
base::scoped_nsobject<MouseTracker> mouse_tracker_;
base::WeakPtrFactory<WindowActivityTrackerMac> weak_factory_;
diff --git a/chromium/content/browser/media/capture/window_activity_tracker_mac.mm b/chromium/content/browser/media/capture/window_activity_tracker_mac.mm
index a0ec7d31afc..962582619f5 100644
--- a/chromium/content/browser/media/capture/window_activity_tracker_mac.mm
+++ b/chromium/content/browser/media/capture/window_activity_tracker_mac.mm
@@ -60,7 +60,7 @@ std::unique_ptr<WindowActivityTracker> WindowActivityTracker::Create(
}
WindowActivityTrackerMac::WindowActivityTrackerMac(NSView* view)
- : view_(view), weak_factory_(this) {
+ : weak_factory_(this) {
mouse_tracker_.reset([[MouseTracker alloc] initWithView:view]);
[mouse_tracker_ registerMouseInteractionObserver:
base::Bind(&WindowActivityTrackerMac::OnMouseActivity,
diff --git a/chromium/content/browser/media/media_browsertest.cc b/chromium/content/browser/media/media_browsertest.cc
index 929ab347732..6d28a8afd2b 100644
--- a/chromium/content/browser/media/media_browsertest.cc
+++ b/chromium/content/browser/media/media_browsertest.cc
@@ -134,7 +134,13 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearSilentWebm) {
}
#if defined(USE_PROPRIETARY_CODECS)
-IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMp4) {
+// Crashes on Mac only. http://crbug.com/621857
+#if defined(OS_MACOSX)
+#define MAYBE_VideoBearMp4 DISABLED_VideoBearMp4
+#else
+#define MAYBE_VideoBearMp4 VideoBearMp4
+#endif
+IN_PROC_BROWSER_TEST_P(MediaTest, MAYBE_VideoBearMp4) {
PlayVideo("bear.mp4", GetParam());
}
@@ -142,7 +148,13 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearHighBitDepthMp4) {
PlayVideo("bear-320x180-hi10p.mp4", GetParam());
}
-IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearSilentMp4) {
+// Crashes on Mac only. http://crbug.com/621857
+#if defined(OS_MACOSX)
+#define MAYBE_VideoBearSilentMp4 DISABLED_VideoBearSilentMp4
+#else
+#define MAYBE_VideoBearSilentMp4 VideoBearSilentMp4
+#endif
+IN_PROC_BROWSER_TEST_P(MediaTest, MAYBE_VideoBearSilentMp4) {
PlayVideo("bear_silent.mp4", GetParam());
}
diff --git a/chromium/content/browser/media/media_canplaytype_browsertest.cc b/chromium/content/browser/media/media_canplaytype_browsertest.cc
index cce3e47c9d6..d0c8589c673 100644
--- a/chromium/content/browser/media/media_canplaytype_browsertest.cc
+++ b/chromium/content/browser/media/media_canplaytype_browsertest.cc
@@ -4,12 +4,14 @@
#include <string>
+#include "base/command_line.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "content/browser/media/media_browsertest.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
+#include "media/base/media_switches.h"
#include "media/media_features.h"
#if defined(OS_ANDROID)
@@ -80,14 +82,6 @@ const char* kHi10pProbably = kPropProbably;
const char* kHi10pProbably = kPropMaybe;
#endif
-#if BUILDFLAG(ENABLE_MP4_VP9_DEMUXING)
-const char* kMp4Vp9Probably = kPropProbably;
-const char* kMP4Vp9Maybe = kMaybe;
-#else
-const char* kMp4Vp9Probably = kNot;
-const char* kMP4Vp9Maybe = kNot;
-#endif
-
namespace content {
class MediaCanPlayTypeTest : public MediaBrowserTest {
@@ -103,8 +97,7 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
std::string result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
- "window.domAutomationController.send(" + command + ");",
+ shell(), "window.domAutomationController.send(" + command + ");",
&result));
return result;
}
@@ -772,8 +765,9 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kHevcSupported,
CanPlay("'video/mp4; codecs=\"hvc1.1.6.L93.B0, mp4a.40.5\"'"));
- EXPECT_EQ(kMp4Vp9Probably,
- CanPlay("'video/mp4; codecs=\"vp09.00.01.08.02.01.01.00\"'"));
+ // Note: set to kPropProbably when switches::kEnableVp9InMp4 is enabled by
+ // default.
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.00.01.08.02.01.01.00\"'"));
TestMPEGUnacceptableCombinations("video/mp4");
// This result is incorrect. See https://crbug.com/592889.
@@ -1220,37 +1214,6 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_AvcLevels) {
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42E052\"'"));
}
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mp4Vp9Variants) {
- // Malformed codecs string.
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.00.-1.08\"'"));
-
- // Codecs strings with missing fields.
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.00.01.08\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01..02.01.01.00\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01.08.05.01.01\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.04\"'"));
-
- // Unexpected bit depth.
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01.09.02.01.01.00\"'"));
- // Unexpected chroma subsampling.
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01.08.04.04.00.00\"'"));
- // Unexpected transfer function.
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01.08.04.03.02.00\"'"));
-
- EXPECT_EQ(kMp4Vp9Probably,
- CanPlay("'video/mp4; codecs=\"vp09.00.01.08.02.01.01.00\"'"));
- EXPECT_EQ(kMp4Vp9Probably,
- CanPlay("'video/mp4; codecs=\"vp09.00.01.08.04.03.00.00\"'"));
- EXPECT_EQ(kMP4Vp9Maybe,
- CanPlay("'video/mp4; codecs=\"vp09.01.01.08.02.01.01.00\"'"));
- EXPECT_EQ(kMP4Vp9Maybe,
- CanPlay("'video/mp4; codecs=\"vp09.02.01.08.02.01.01.00\"'"));
- EXPECT_EQ(kMP4Vp9Maybe,
- CanPlay("'video/mp4; codecs=\"vp09.03.01.08.02.01.01.00\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.04.01.08.02.01.01.00\"'"));
-}
-
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_HEVCVariants) {
// Both hev1 and hvc1 should be supported
EXPECT_EQ(kHevcSupported, CanPlay("'video/mp4; codecs=hev1.1.6.L93.B0'"));
@@ -1755,4 +1718,57 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mpeg2TsAudio) {
EXPECT_EQ(kNot, CanPlay("'audio/mp2t; codecs=\"mp4a.40.2\"'"));
}
+class MediaCanPlayTypeTestMp4Vp9Demuxing
+ : public MediaCanPlayTypeTest,
+ public ::testing::WithParamInterface<bool> {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ MediaCanPlayTypeTest::SetUpCommandLine(command_line);
+ const bool enable_mp4_vp9_demuxing = GetParam();
+ if (enable_mp4_vp9_demuxing)
+ command_line->AppendSwitch(switches::kEnableVp9InMp4);
+ }
+};
+
+IN_PROC_BROWSER_TEST_P(MediaCanPlayTypeTestMp4Vp9Demuxing,
+ CodecSupportTest_Mp4Vp9Variants) {
+ // Malformed codecs string.
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.00.-1.08\"'"));
+
+ // Codecs strings with missing fields.
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.00.01.08\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01..02.01.01.00\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01.08.05.01.01\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.04\"'"));
+
+ // Unexpected bit depth.
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01.09.02.01.01.00\"'"));
+ // Unexpected chroma subsampling.
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01.08.04.04.00.00\"'"));
+ // Unexpected transfer function.
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.01.01.08.04.03.02.00\"'"));
+ // Unexpected profile.
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"vp09.04.01.08.02.01.01.00\"'"));
+
+ const bool enable_mp4_vp9_demuxing = GetParam();
+ const char* mp4_vp9_probably = enable_mp4_vp9_demuxing ? kPropProbably : kNot;
+ const char* mp4_vp9_maybe = enable_mp4_vp9_demuxing ? kPropMaybe : kNot;
+
+ EXPECT_EQ(mp4_vp9_probably,
+ CanPlay("'video/mp4; codecs=\"vp09.00.01.08.02.01.01.00\"'"));
+ EXPECT_EQ(mp4_vp9_probably,
+ CanPlay("'video/mp4; codecs=\"vp09.00.01.08.04.03.00.00\"'"));
+ EXPECT_EQ(mp4_vp9_maybe,
+ CanPlay("'video/mp4; codecs=\"vp09.01.01.08.02.01.01.00\"'"));
+ EXPECT_EQ(mp4_vp9_maybe,
+ CanPlay("'video/mp4; codecs=\"vp09.02.01.08.02.01.01.00\"'"));
+ EXPECT_EQ(mp4_vp9_maybe,
+ CanPlay("'video/mp4; codecs=\"vp09.03.01.08.02.01.01.00\"'"));
+}
+
+INSTANTIATE_TEST_CASE_P(EnableDisableMp4Vp9Demuxing,
+ MediaCanPlayTypeTestMp4Vp9Demuxing,
+ ::testing::Bool());
+
} // namespace content
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index 3813858b07f..33df1a834fc 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -5,6 +5,8 @@
#include "content/browser/media/media_internals.h"
#include <stddef.h>
+
+#include <memory>
#include <utility>
#include "base/macros.h"
@@ -13,6 +15,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
@@ -110,6 +113,7 @@ class AudioLogImpl : public media::AudioLog {
void OnSetVolume(int component_id, double volume) override;
void OnSwitchOutputDevice(int component_id,
const std::string& device_id) override;
+ void OnLogMessage(int component_id, const std::string& message) override;
// Called by MediaInternals to update the WebContents title for a stream.
void SendWebContentsTitle(int component_id,
@@ -206,6 +210,10 @@ void AudioLogImpl::OnSwitchOutputDevice(int component_id,
kAudioLogUpdateFunction, &dict);
}
+void AudioLogImpl::OnLogMessage(int component_id, const std::string& message) {
+ MediaStreamManager::SendMessageToNativeLog(message);
+}
+
void AudioLogImpl::SendWebContentsTitle(int component_id,
int render_process_id,
int render_frame_id) {
@@ -605,7 +613,8 @@ void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
for (const auto& format : video_capture_device_info.supported_formats)
format_list->AppendString(media::VideoCaptureFormat::ToString(format));
- base::DictionaryValue* device_dict = new base::DictionaryValue();
+ std::unique_ptr<base::DictionaryValue> device_dict(
+ new base::DictionaryValue());
device_dict->SetString("id", video_capture_device_info.name.id());
device_dict->SetString(
"name", video_capture_device_info.name.GetNameAndModel());
@@ -615,7 +624,7 @@ void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
device_dict->SetString(
"captureApi", video_capture_device_info.name.GetCaptureApiTypeString());
#endif
- video_capture_capabilities_cached_data_.Append(device_dict);
+ video_capture_capabilities_cached_data_.Append(std::move(device_dict));
}
SendVideoCaptureDeviceCapabilities();
diff --git a/chromium/content/browser/media/media_internals_proxy.cc b/chromium/content/browser/media/media_internals_proxy.cc
index 1f8b99f538b..8b492a259d0 100644
--- a/chromium/content/browser/media/media_internals_proxy.cc
+++ b/chromium/content/browser/media/media_internals_proxy.cc
@@ -6,7 +6,10 @@
#include <stddef.h>
+#include <utility>
+
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
@@ -98,7 +101,7 @@ void MediaInternalsProxy::OnAddEntry(const net::NetLog::Entry& entry) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&MediaInternalsProxy::AddNetEventOnUIThread, this,
- entry.ToValue()));
+ base::Passed(entry.ToValue())));
}
MediaInternalsProxy::~MediaInternalsProxy() {}
@@ -153,7 +156,8 @@ void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16& update) {
handler_->OnUpdate(update);
}
-void MediaInternalsProxy::AddNetEventOnUIThread(base::Value* entry) {
+void MediaInternalsProxy::AddNetEventOnUIThread(
+ std::unique_ptr<base::Value> entry) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Send the updates to the page in kMediaInternalsProxyEventDelayMilliseconds
@@ -166,7 +170,7 @@ void MediaInternalsProxy::AddNetEventOnUIThread(base::Value* entry) {
base::TimeDelta::FromMilliseconds(
kMediaInternalsProxyEventDelayMilliseconds));
}
- pending_net_updates_->Append(entry);
+ pending_net_updates_->Append(std::move(entry));
}
void MediaInternalsProxy::SendNetEventsOnUIThread() {
diff --git a/chromium/content/browser/media/media_internals_proxy.h b/chromium/content/browser/media/media_internals_proxy.h
index 84b4a1b1aad..c506fc52a0e 100644
--- a/chromium/content/browser/media/media_internals_proxy.h
+++ b/chromium/content/browser/media/media_internals_proxy.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_MEDIA_MEDIA_INTERNALS_PROXY_H_
#define CONTENT_BROWSER_MEDIA_MEDIA_INTERNALS_PROXY_H_
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner_helpers.h"
@@ -68,7 +70,7 @@ class MediaInternalsProxy
void UpdateUIOnUIThread(const base::string16& update);
// Put |entry| on a list of events to be sent to the page.
- void AddNetEventOnUIThread(base::Value* entry);
+ void AddNetEventOnUIThread(std::unique_ptr<base::Value> entry);
// Send all pending events to the page.
void SendNetEventsOnUIThread();
diff --git a/chromium/content/browser/media/media_redirect_browsertest.cc b/chromium/content/browser/media/media_redirect_browsertest.cc
index 2b7a4390fbe..0d809e69f0e 100644
--- a/chromium/content/browser/media/media_redirect_browsertest.cc
+++ b/chromium/content/browser/media/media_redirect_browsertest.cc
@@ -59,7 +59,8 @@ IN_PROC_BROWSER_TEST_F(MediaRedirectTest, CanPlayHiddenWebm) {
}
#if defined(OS_ANDROID) && defined(USE_PROPRIETARY_CODECS)
-IN_PROC_BROWSER_TEST_F(MediaRedirectTest, CanPlayHiddenHls) {
+// Flaky, see http://crbug.com/624005
+IN_PROC_BROWSER_TEST_F(MediaRedirectTest, DISABLED_CanPlayHiddenHls) {
RunRedirectTest("bear.m3u8");
}
#endif
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index c301e2e345a..066d46fd11f 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -10,11 +10,11 @@
#include "build/build_config.h"
#include "content/browser/media/audible_metrics.h"
#include "content/browser/media/audio_stream_monitor.h"
-#include "content/browser/power_save_blocker_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/media/media_player_delegate_messages.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "device/power_save_blocker/power_save_blocker.h"
#include "ipc/ipc_message_macros.h"
namespace content {
@@ -34,6 +34,9 @@ MediaWebContentsObserver::~MediaWebContentsObserver() {}
void MediaWebContentsObserver::WebContentsDestroyed() {
g_audible_metrics.Get().UpdateAudibleWebContentsState(web_contents(), false);
+#if defined(OS_ANDROID)
+ view_weak_factory_.reset();
+#endif
}
void MediaWebContentsObserver::RenderFrameDeleted(
@@ -180,20 +183,28 @@ void MediaWebContentsObserver::ClearPowerSaveBlockers(
void MediaWebContentsObserver::CreateAudioPowerSaveBlocker() {
DCHECK(!audio_power_save_blocker_);
- audio_power_save_blocker_ = PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
- PowerSaveBlocker::kReasonAudioPlayback, "Playing audio");
+ audio_power_save_blocker_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ device::PowerSaveBlocker::kReasonAudioPlayback, "Playing audio",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
}
void MediaWebContentsObserver::CreateVideoPowerSaveBlocker() {
DCHECK(!video_power_save_blocker_);
DCHECK(!active_video_players_.empty());
- video_power_save_blocker_ = PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
- PowerSaveBlocker::kReasonVideoPlayback, "Playing video");
+ video_power_save_blocker_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ device::PowerSaveBlocker::kReasonVideoPlayback, "Playing video",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
#if defined(OS_ANDROID)
- static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
- ->InitDisplaySleepBlocker(web_contents());
+ if (web_contents()->GetNativeView()) {
+ view_weak_factory_.reset(new base::WeakPtrFactory<ui::ViewAndroid>(
+ web_contents()->GetNativeView()));
+ video_power_save_blocker_.get()->InitDisplaySleepBlocker(
+ view_weak_factory_->GetWeakPtr());
+ }
#endif
}
diff --git a/chromium/content/browser/media/media_web_contents_observer.h b/chromium/content/browser/media/media_web_contents_observer.h
index 072ef4239fe..540a921f28a 100644
--- a/chromium/content/browser/media/media_web_contents_observer.h
+++ b/chromium/content/browser/media/media_web_contents_observer.h
@@ -16,9 +16,15 @@
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
-namespace content {
+#if defined(OS_ANDROID)
+#include "ui/android/view_android.h"
+#endif // OS_ANDROID
+namespace device {
class PowerSaveBlocker;
+} // namespace device
+
+namespace content {
// This class manages all RenderFrame based media related managers at the
// browser side. It receives IPC messages from media RenderFrameObservers and
@@ -94,8 +100,11 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
// Tracking variables and associated power save blockers for media playback.
ActiveMediaPlayerMap active_audio_players_;
ActiveMediaPlayerMap active_video_players_;
- std::unique_ptr<PowerSaveBlocker> audio_power_save_blocker_;
- std::unique_ptr<PowerSaveBlocker> video_power_save_blocker_;
+ std::unique_ptr<device::PowerSaveBlocker> audio_power_save_blocker_;
+ std::unique_ptr<device::PowerSaveBlocker> video_power_save_blocker_;
+#if defined(OS_ANDROID)
+ std::unique_ptr<base::WeakPtrFactory<ui::ViewAndroid>> view_weak_factory_;
+#endif
MediaSessionControllersManager session_controllers_manager_;
diff --git a/chromium/content/browser/media/midi_browsertest.cc b/chromium/content/browser/media/midi_browsertest.cc
index c8d7e2c7c6d..ed69c0e7434 100644
--- a/chromium/content/browser/media/midi_browsertest.cc
+++ b/chromium/content/browser/media/midi_browsertest.cc
@@ -19,7 +19,7 @@ IN_PROC_BROWSER_TEST_F(MidiBrowserTest, RequestMIDIAccess) {
bool result;
NavigateToURL(shell(), GURL("about:blank"));
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"navigator.requestMIDIAccess()"
" .then("
" _ => domAutomationController.send(true),"
@@ -33,7 +33,7 @@ IN_PROC_BROWSER_TEST_F(MidiBrowserTest, SubscribeAll) {
bool result;
NavigateToURL(shell(), GURL("about:blank"));
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"navigator.requestMIDIAccess()"
" .then("
" e => { e.inputs.forEach(i => i.onmidimessage = console.log);"
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 1b04aac3cc9..a2fc8f5e322 100644
--- a/chromium/content/browser/media/session/media_session_controller_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_controller_unittest.cc
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/tuple.h"
+#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"
@@ -69,13 +70,13 @@ class MediaSessionControllerTest : public RenderViewHostImplTestHarness {
if (!msg)
return false;
- base::Tuple<int> result;
+ std::tuple<int> result;
if (!T::Read(msg, &result))
return false;
- EXPECT_EQ(id_.second, base::get<0>(result));
+ EXPECT_EQ(id_.second, std::get<0>(result));
test_sink().ClearMessages();
- return id_.second == base::get<0>(result);
+ return id_.second == std::get<0>(result);
}
template <typename T>
@@ -84,17 +85,17 @@ class MediaSessionControllerTest : public RenderViewHostImplTestHarness {
if (!msg)
return false;
- base::Tuple<int, double> result;
+ std::tuple<int, double> result;
if (!T::Read(msg, &result))
return false;
- EXPECT_EQ(id_.second, base::get<0>(result));
- if (id_.second != base::get<0>(result))
+ EXPECT_EQ(id_.second, std::get<0>(result));
+ if (id_.second != std::get<0>(result))
return false;
- EXPECT_EQ(expected_multiplier, base::get<1>(result));
+ EXPECT_EQ(expected_multiplier, std::get<1>(result));
test_sink().ClearMessages();
- return expected_multiplier == base::get<1>(result);
+ return expected_multiplier == std::get<1>(result);
}
WebContentsObserver::MediaPlayerId id_;
diff --git a/chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc b/chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc
index 440092f4e1d..c5b7f0c6f69 100644
--- a/chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc
@@ -5,7 +5,10 @@
#include <memory>
#include "base/command_line.h"
+#include "base/location.h"
#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/public/test/content_browser_test.h"
@@ -57,7 +60,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionDelegateAndroidBrowserTest,
// to the listeners. If the bug is still present, it will crash.
{
base::RunLoop run_loop;
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(1));
run_loop.Run();
}
diff --git a/chromium/content/browser/media/session/media_session_visibility_browsertest.cc b/chromium/content/browser/media/session/media_session_visibility_browsertest.cc
index f83cd858081..659b3c1a4d8 100644
--- a/chromium/content/browser/media/session/media_session_visibility_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_visibility_browsertest.cc
@@ -3,6 +3,10 @@
// found in the LICENSE file.
#include "base/command_line.h"
+#include "base/location.h"
+#include "base/logging.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/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
@@ -92,7 +96,7 @@ class MediaSessionVisibilityBrowserTest
// MediaRouterIntegrationTests. Move it into a general place.
void Wait(base::TimeDelta timeout) {
base::RunLoop run_loop;
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), timeout);
run_loop.Run();
}
@@ -106,63 +110,89 @@ class MediaSessionVisibilityBrowserTest
void TestSessionInactiveWhenHiddenAfterContentPause() {
LoadTestPage();
+ LOG(INFO) << "Starting player";
ClearMediaSessionStateLoopRunners();
RunScript(kStartPlayerScript);
+ LOG(INFO) << "Waiting for Session to be active";
WaitForMediaSessionState(MediaSession::State::ACTIVE);
+ LOG(INFO) << "Pausing player";
ClearMediaSessionStateLoopRunners();
RunScript(kPausePlayerScript);
+ LOG(INFO) << "Waiting for Session to be suspended";
WaitForMediaSessionState(MediaSession::State::SUSPENDED);
+ LOG(INFO) << "Hiding the tab";
ClearMediaSessionStateLoopRunners();
web_contents_->WasHidden();
+ LOG(INFO) << "Waiting for Session to be inactive";
WaitForMediaSessionState(MediaSession::State::INACTIVE);
+
+ LOG(INFO) << "Test succeeded";
}
void TestSessionInactiveWhenHiddenWhilePlaying() {
LoadTestPage();
+ LOG(INFO) << "Starting player";
ClearMediaSessionStateLoopRunners();
RunScript(kStartPlayerScript);
+ LOG(INFO) << "Waiting for Session to be active";
WaitForMediaSessionState(MediaSession::State::ACTIVE);
+ LOG(INFO) << "Hiding the tab";
ClearMediaSessionStateLoopRunners();
web_contents_->WasHidden();
+ LOG(INFO) << "Waiting for Session to be inactive";
WaitForMediaSessionState(MediaSession::State::INACTIVE);
+
+ LOG(INFO) << "Test succeeded";
}
void TestSessionSuspendedWhenHiddenAfterContentPause() {
LoadTestPage();
+ LOG(INFO) << "Starting player";
ClearMediaSessionStateLoopRunners();
RunScript(kStartPlayerScript);
+ LOG(INFO) << "Waiting for Session to be active";
WaitForMediaSessionState(MediaSession::State::ACTIVE);
+ LOG(INFO) << "Pausing player";
ClearMediaSessionStateLoopRunners();
RunScript(kPausePlayerScript);
+ LOG(INFO) << "Waiting for Session to be suspended";
WaitForMediaSessionState(MediaSession::State::SUSPENDED);
+ LOG(INFO) << "Hiding the tab";
// Wait for 1 second and check the MediaSession state.
// No better solution till now.
web_contents_->WasHidden();
Wait(base::TimeDelta::FromSeconds(1));
ASSERT_EQ(media_session_->audio_focus_state_,
MediaSession::State::SUSPENDED);
+
+ LOG(INFO) << "Test succeeded";
}
void TestSessionActiveWhenHiddenWhilePlaying() {
LoadTestPage();
+ LOG(INFO) << "Starting player";
ClearMediaSessionStateLoopRunners();
RunScript(kStartPlayerScript);
+ LOG(INFO) << "Waiting for Session to be active";
WaitForMediaSessionState(MediaSession::State::ACTIVE);
+ LOG(INFO) << "Hiding the tab";
// Wait for 1 second and check the MediaSession state.
// No better solution till now.
web_contents_->WasHidden();
Wait(base::TimeDelta::FromSeconds(1));
ASSERT_EQ(media_session_->audio_focus_state_,
MediaSession::State::ACTIVE);
+
+ LOG(INFO) << "Test succeeded";
}
WebContents* web_contents_;
@@ -237,6 +267,8 @@ class MediaSessionVisibilityBrowserTest_AndroidPipeline_SuspendOnHide :
}
};
+// The following tests are flaky. Re-enabling with logging to see what's
+// happening on the bots. See crbug.com/619096.
INCLUDE_TEST_FROM_BASE_CLASS(
MediaSessionVisibilityBrowserTest_AndroidPipeline_SuspendOnHide,
TestSessionInactiveWhenHiddenAfterContentPause)
@@ -254,12 +286,14 @@ class MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide :
}
};
+// The following tests are flaky. Re-enabling with logging to see what's
+// happening on the bots. See crbug.com/619096.
INCLUDE_TEST_FROM_BASE_CLASS(
MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide,
TestSessionSuspendedWhenHiddenAfterContentPause)
INCLUDE_TEST_FROM_BASE_CLASS(
- MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide,
- TestSessionActiveWhenHiddenWhilePlaying)
+ MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide,
+ TestSessionActiveWhenHiddenWhilePlaying)
#endif // defined(OS_ANDROID)
diff --git a/chromium/content/browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc
index 5ff2eba4739..f098d77ae4e 100644
--- a/chromium/content/browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc
@@ -233,9 +233,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
std::string result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell2->web_contents(),
- "call({video: true, audio: true});",
- &result));
+ shell2, "call({video: true, audio: true});", &result));
ASSERT_STREQ("OK", result.c_str());
EXPECT_FALSE(base::PathExists(base_file));
diff --git a/chromium/content/browser/media/webrtc/webrtc_canvas_capture_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_canvas_capture_browsertest.cc
deleted file mode 100644
index 107ead30aae..00000000000
--- a/chromium/content/browser/media/webrtc/webrtc_canvas_capture_browsertest.cc
+++ /dev/null
@@ -1,35 +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 "base/command_line.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test_utils.h"
-#include "content/test/webrtc_content_browsertest_base.h"
-
-namespace {
-
-static const char kCanvasTestHtmlPage[] = "/media/canvas_capture_color.html";
-
-} // namespace
-
-namespace content {
-
-// This class tests the rgba color values produced by canvas capture.
-class WebRtcCanvasCaptureTest : public WebRtcContentBrowserTest {
- public:
- WebRtcCanvasCaptureTest() {}
- ~WebRtcCanvasCaptureTest() override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WebRtcCanvasCaptureTest);
-};
-
-IN_PROC_BROWSER_TEST_F(WebRtcCanvasCaptureTest,
- VerifyCanvasCaptureColor) {
- MakeTypicalCall("testCanvasCaptureColors();", kCanvasTestHtmlPage);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/webrtc/webrtc_capture_from_element_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_capture_from_element_browsertest.cc
new file mode 100644
index 00000000000..67cc284a47e
--- /dev/null
+++ b/chromium/content/browser/media/webrtc/webrtc_capture_from_element_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 "base/command_line.h"
+#include "base/strings/stringprintf.h"
+#include "content/public/common/content_switches.h"
+#include "content/test/webrtc_content_browsertest_base.h"
+#include "media/base/test_data_util.h"
+
+namespace {
+
+static const char kCanvasTestHtmlPage[] = "/media/canvas_capture_color.html";
+
+static const char kVideoAudioHtmlFile[] =
+ "/media/video_audio_element_capture_test.html";
+
+static struct FileAndTypeParameters {
+ bool has_video;
+ bool has_audio;
+ bool use_audio_tag;
+ std::string filename;
+} const kFileAndTypeParameters[] = {
+ {true, false, false, "bear-320x240-video-only.webm"},
+ {false, true, false, "bear-320x240-audio-only.webm"},
+ {true, true, false, "bear-320x240.webm"},
+ {false, true, true, "bear-320x240-audio-only.webm"},
+};
+
+} // namespace
+
+namespace content {
+
+// This class is the browser tests for Media Capture from DOM Elements API,
+// which allows for creation of a MediaStream out of a <canvas>, <video> or
+// <audio> element.
+class WebRtcCaptureFromElementBrowserTest
+ : public WebRtcContentBrowserTest,
+ public testing::WithParamInterface<struct FileAndTypeParameters> {
+ public:
+ WebRtcCaptureFromElementBrowserTest() {}
+ ~WebRtcCaptureFromElementBrowserTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ WebRtcContentBrowserTest::SetUpCommandLine(command_line);
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kEnableBlinkFeatures, "MediaCaptureFromVideo");
+
+ // Allow <video>/<audio>.play() when not initiated by user gesture.
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kDisableGestureRequirementForMediaPlayback);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebRtcCaptureFromElementBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
+ VerifyCanvasCaptureColor) {
+ MakeTypicalCall("testCanvasCaptureColors();", kCanvasTestHtmlPage);
+}
+
+IN_PROC_BROWSER_TEST_P(WebRtcCaptureFromElementBrowserTest,
+ CaptureFromMediaElement) {
+ MakeTypicalCall(
+ base::StringPrintf("testCaptureFromMediaElement(\"%s\", %d, %d, %d);",
+ GetParam().filename.c_str(),
+ GetParam().has_video,
+ GetParam().has_audio,
+ GetParam().use_audio_tag),
+ kVideoAudioHtmlFile);
+}
+
+INSTANTIATE_TEST_CASE_P(,
+ WebRtcCaptureFromElementBrowserTest,
+ testing::ValuesIn(kFileAndTypeParameters));
+} // namespace content
diff --git a/chromium/content/browser/media/webrtc/webrtc_datachannel_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_datachannel_browsertest.cc
index e2d358b6462..9f72ab836ac 100644
--- a/chromium/content/browser/media/webrtc/webrtc_datachannel_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_datachannel_browsertest.cc
@@ -16,10 +16,19 @@ const char kDataChannelHtmlFile[] = "/media/datachannel_test.html";
namespace content {
-class WebRtcDataChannelTest : public WebRtcContentBrowserTest {
+#if defined(OS_WIN) || (defined(OS_ANDROID) && defined(ADDRESS_SANITIZER))
+// GC does not work correctly in some cases under Android ASAN.
+// See https://crbug.com/611620.
+// This test has become flaky on Windows. See https://crbug.com/616388
+#define MAYBE_WebRtcDataChannelTest DISABLED_WebRtcDataChannelTest
+#else
+#define MAYBE_WebRtcDataChannelTest WebRtcDataChannelTest
+#endif
+
+class MAYBE_WebRtcDataChannelTest : public WebRtcContentBrowserTest {
public:
- WebRtcDataChannelTest() {}
- ~WebRtcDataChannelTest() override {}
+ MAYBE_WebRtcDataChannelTest() {}
+ ~MAYBE_WebRtcDataChannelTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
WebRtcContentBrowserTest::SetUpCommandLine(command_line);
@@ -29,10 +38,10 @@ class WebRtcDataChannelTest : public WebRtcContentBrowserTest {
}
private:
- DISALLOW_COPY_AND_ASSIGN(WebRtcDataChannelTest);
+ DISALLOW_COPY_AND_ASSIGN(MAYBE_WebRtcDataChannelTest);
};
-IN_PROC_BROWSER_TEST_F(WebRtcDataChannelTest, DataChannelGC) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcDataChannelTest, DataChannelGC) {
MakeTypicalCall("testDataChannelGC();", kDataChannelHtmlFile);
}
diff --git a/chromium/content/browser/media/webrtc/webrtc_internals.cc b/chromium/content/browser/media/webrtc/webrtc_internals.cc
index 09d7a970d26..1a1d57f1a89 100644
--- a/chromium/content/browser/media/webrtc/webrtc_internals.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_internals.cc
@@ -12,9 +12,9 @@
#include "content/browser/web_contents/web_contents_view.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/power_save_blocker.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
+#include "device/power_save_blocker/power_save_blocker.h"
using base::ProcessId;
using std::string;
@@ -263,10 +263,8 @@ void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) {
if (peer_connection_data_.GetSize() > 0)
observer->OnUpdate("updateAllPeerConnections", &peer_connection_data_);
- for (base::ListValue::iterator it = get_user_media_requests_.begin();
- it != get_user_media_requests_.end();
- ++it) {
- observer->OnUpdate("addGetUserMedia", *it);
+ for (const auto& request : get_user_media_requests_) {
+ observer->OnUpdate("addGetUserMedia", request.get());
}
}
@@ -502,9 +500,12 @@ void WebRTCInternals::CreateOrReleasePowerSaveBlocker() {
} else if (!peer_connection_data_.empty() && !power_save_blocker_) {
DVLOG(1) << ("Preventing the application from being suspended while one or "
"more PeerConnections are active.");
- power_save_blocker_ = content::PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
- PowerSaveBlocker::kReasonOther, "WebRTC has active PeerConnections");
+ power_save_blocker_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ device::PowerSaveBlocker::kReasonOther,
+ "WebRTC has active PeerConnections",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
}
}
diff --git a/chromium/content/browser/media/webrtc/webrtc_internals.h b/chromium/content/browser/media/webrtc/webrtc_internals.h
index e319313df2d..ddcb6714291 100644
--- a/chromium/content/browser/media/webrtc/webrtc_internals.h
+++ b/chromium/content/browser/media/webrtc/webrtc_internals.h
@@ -20,9 +20,12 @@
#include "content/public/browser/render_process_host_observer.h"
#include "ui/shell_dialogs/select_file_dialog.h"
+namespace device {
+class PowerSaveBlocker;
+} // namespace device
+
namespace content {
-class PowerSaveBlocker;
class WebContents;
class WebRTCInternalsUIObserver;
@@ -202,7 +205,7 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
// While |peer_connection_data_| is non-empty, hold an instance of
// PowerSaveBlocker. This prevents the application from being suspended while
// remoting.
- std::unique_ptr<PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
// Set of render process hosts that |this| is registered as an observer on.
base::hash_set<int> render_process_id_set_;
diff --git a/chromium/content/browser/media/webrtc/webrtc_internals_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_internals_browsertest.cc
index 854bf09c9fa..046fbf8095f 100644
--- a/chromium/content/browser/media/webrtc/webrtc_internals_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_internals_browsertest.cc
@@ -164,7 +164,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
protected:
bool ExecuteJavascript(const string& javascript) {
- return ExecuteScript(shell()->web_contents(), javascript);
+ return ExecuteScript(shell(), javascript);
}
void ExpectTitle(const std::string& expected_title) const {
@@ -211,7 +211,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
void VerifyElementWithId(const string& id) {
bool result = false;
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send($('" + id + "') != null);",
&result));
EXPECT_TRUE(result);
@@ -221,7 +221,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
void VerifyNoElementWithId(const string& id) {
bool result = false;
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send($('" + id + "') == null);",
&result));
EXPECT_TRUE(result);
@@ -231,11 +231,11 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
void VerifyUserMediaRequest(
const std::vector<UserMediaRequestEntry>& requests) {
string json_requests;
- ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
- "window.domAutomationController.send("
- "JSON.stringify(userMediaRequests));",
- &json_requests));
+ ASSERT_TRUE(
+ ExecuteScriptAndExtractString(shell(),
+ "window.domAutomationController.send("
+ " JSON.stringify(userMediaRequests));",
+ &json_requests));
std::unique_ptr<base::Value> value_requests =
base::JSONReader::Read(json_requests);
@@ -263,19 +263,19 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
}
bool user_media_tab_existed = false;
- ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send("
- "$('user-media-tab-id') != null);",
- &user_media_tab_existed));
+ ASSERT_TRUE(
+ ExecuteScriptAndExtractBool(shell(),
+ "window.domAutomationController.send("
+ " $('user-media-tab-id') != null);",
+ &user_media_tab_existed));
EXPECT_EQ(!requests.empty(), user_media_tab_existed);
if (user_media_tab_existed) {
int user_media_request_count = -1;
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
- "$('user-media-tab-id').childNodes.length);",
+ " $('user-media-tab-id').childNodes.length);",
&user_media_request_count));
ASSERT_EQ(requests.size(), static_cast<size_t>(user_media_request_count));
}
@@ -295,8 +295,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
ss << "var row = $('" << log_id << "').rows[" << (i + 1) << "];"
"var cell = row.lastChild;"
"window.domAutomationController.send(cell.firstChild.textContent);";
- ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(), ss.str(), &result));
+ ASSERT_TRUE(ExecuteScriptAndExtractString(shell(), ss.str(), &result));
EXPECT_EQ(pc.events_[i].type + pc.events_[i].value, result);
}
}
@@ -358,7 +357,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
string result;
ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
+ shell(),
"var row = $('" + table_id + "-" + name + "');"
"var name = row.cells[0].textContent;"
"var value = row.cells[1].textContent;"
@@ -395,7 +394,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
int index, const string& value) {
bool result = false;
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
"graphViews['" + pc_id + "-" + graph_id + "'] != null)",
&result));
@@ -406,8 +405,8 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
".getDataSeries('" << graph_id << "').dataPoints_[" << index << "];"
"window.domAutomationController.send(dp.value.toString())";
string actual_value;
- ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(), ss.str(), &actual_value));
+ ASSERT_TRUE(
+ ExecuteScriptAndExtractString(shell(), ss.str(), &actual_value));
EXPECT_EQ(value, actual_value);
}
@@ -415,7 +414,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
string GetSsrcInfo(const string& ssrc_id) {
string result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(JSON.stringify("
"ssrcInfoManager.streamInfoContainer_['" + ssrc_id + "']))",
&result));
@@ -425,10 +424,10 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
int GetSsrcInfoBlockCount(Shell* shell) {
int count = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- shell->web_contents(),
+ shell,
"window.domAutomationController.send("
- "document.getElementsByClassName("
- "ssrcInfoManager.SSRC_INFO_BLOCK_CLASS).length);",
+ " document.getElementsByClassName("
+ " ssrcInfoManager.SSRC_INFO_BLOCK_CLASS).length);",
&count));
return count;
}
@@ -622,7 +621,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, BweCompoundGraph) {
bool result = false;
// Verify that the bweCompound graph exists.
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
" graphViews['" + graph_id + "'] != null)",
&result));
@@ -631,7 +630,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, BweCompoundGraph) {
// Verify that the bweCompound graph contains multiple dataSeries.
int count = 0;
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
" graphViews['" + graph_id + "'].getDataSeriesCount())",
&count));
@@ -701,31 +700,31 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
// Verifies the number of peerconnections.
int count = 0;
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell2->web_contents(),
+ shell2,
"window.domAutomationController.send("
- "$('peer-connections-list').getElementsByTagName('li').length);",
+ " $('peer-connections-list').getElementsByTagName('li').length);",
&count));
EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
// Verifies the the event tables.
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell2->web_contents(),
+ shell2,
"window.domAutomationController.send($('peer-connections-list')"
- ".getElementsByClassName('update-log-table').length);",
+ " .getElementsByClassName('update-log-table').length);",
&count));
EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell2->web_contents(),
+ shell2,
"window.domAutomationController.send($('peer-connections-list')"
- ".getElementsByClassName('update-log-table')[0].rows.length);",
+ " .getElementsByClassName('update-log-table')[0].rows.length);",
&count));
EXPECT_GT(count, 1);
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell2->web_contents(),
+ shell2,
"window.domAutomationController.send($('peer-connections-list')"
- ".getElementsByClassName('update-log-table')[1].rows.length);",
+ " .getElementsByClassName('update-log-table')[1].rows.length);",
&count));
EXPECT_GT(count, 1);
@@ -733,28 +732,28 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
count = 0;
while (count != NUMBER_OF_PEER_CONNECTIONS) {
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell2->web_contents(),
+ shell2,
"window.domAutomationController.send("
- "$('peer-connections-list').getElementsByClassName("
- "'stats-table-container').length);",
+ " $('peer-connections-list').getElementsByClassName("
+ " 'stats-table-container').length);",
&count));
}
// Verifies each stats table having more than one rows.
bool result = false;
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell2->web_contents(),
+ shell2,
"var tableContainers = $('peer-connections-list')"
- ".getElementsByClassName('stats-table-container');"
+ " .getElementsByClassName('stats-table-container');"
"var result = true;"
"for (var i = 0; i < tableContainers.length && result; ++i) {"
- "var tables = tableContainers[i].getElementsByTagName('table');"
- "for (var j = 0; j < tables.length && result; ++j) {"
- "result = (tables[j].rows.length > 1);"
- "}"
- "if (!result) {"
- "console.log(tableContainers[i].innerHTML);"
- "}"
+ " var tables = tableContainers[i].getElementsByTagName('table');"
+ " for (var j = 0; j < tables.length && result; ++j) {"
+ " result = (tables[j].rows.length > 1);"
+ " }"
+ " if (!result) {"
+ " console.log(tableContainers[i].innerHTML);"
+ " }"
"}"
"window.domAutomationController.send(result);",
&result));
@@ -782,9 +781,9 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, CreatePageDump) {
// Verifies the peer connection data store can be created without stats.
string dump_json;
ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
- "JSON.stringify(peerConnectionDataStore));",
+ " JSON.stringify(peerConnectionDataStore));",
&dump_json));
std::unique_ptr<base::Value> dump = base::JSONReader::Read(dump_json);
VerifyPageDumpStructure(dump.get(),
@@ -801,9 +800,9 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, CreatePageDump) {
ExecuteAndVerifyAddStats(pc_0, type, id, stats);
ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
- "JSON.stringify(peerConnectionDataStore));",
+ " JSON.stringify(peerConnectionDataStore));",
&dump_json));
dump = base::JSONReader::Read(dump_json);
VerifyStatsDump(dump.get(), pc_0, type, id, stats);
@@ -858,7 +857,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
bool result = false;
// Verify that the graph exists.
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
" graphViews['" + graph_id + "'] != null)",
&result));
@@ -867,13 +866,13 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
// Verify that the graph contains multiple data points.
int count = 0;
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
" graphViews['" + graph_id + "'].getDataSeriesCount())",
&count));
EXPECT_EQ(1, count);
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send("
" peerConnectionDataStore['" + pc.getIdString() + "']" +
" .getDataSeries('" + data_series_id + "').getCount())",
diff --git a/chromium/content/browser/media/webrtc/webrtc_media_recorder_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_media_recorder_browsertest.cc
index 0d1fcb66bdd..ce386582bd0 100644
--- a/chromium/content/browser/media/webrtc/webrtc_media_recorder_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_media_recorder_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -15,12 +16,22 @@ namespace {
static const char kMediaRecorderHtmlFile[] = "/media/mediarecorder_test.html";
+static struct EncodingParameters {
+ bool disable_accelerator;
+ std::string video_codec;
+} const kEncodingParameters[] = {
+ {true, "VP8"}, {true, "VP9"}, {true, "H264"},
+ {false, "VP8"}, {false, "VP9"}, {false, "H264"},
+};
+
} // namespace
namespace content {
// This class tests the recording of a media stream.
-class WebRtcMediaRecorderTest : public WebRtcContentBrowserTest {
+class WebRtcMediaRecorderTest
+ : public WebRtcContentBrowserTest,
+ public testing::WithParamInterface<struct EncodingParameters> {
public:
WebRtcMediaRecorderTest() {}
~WebRtcMediaRecorderTest() override {}
@@ -37,6 +48,14 @@ class WebRtcMediaRecorderTest : public WebRtcContentBrowserTest {
switches::kEnableBlinkFeatures, "GetUserMedia");
}
+ void MaybeForceDisableEncodeAccelerator(bool disable) {
+ if (!disable)
+ return;
+ // This flag is also used for encoding, https://crbug.com/616640.
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kDisableAcceleratedVideoDecode);
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(WebRtcMediaRecorderTest);
};
@@ -49,14 +68,20 @@ IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, MediaRecorderStartAndStop) {
MakeTypicalCall("testStartStopAndRecorderState();", kMediaRecorderHtmlFile);
}
-IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest,
+IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest,
MediaRecorderStartAndDataAvailable) {
- MakeTypicalCall("testStartAndDataAvailable();", kMediaRecorderHtmlFile);
+ MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator);
+ MakeTypicalCall(base::StringPrintf("testStartAndDataAvailable(\"%s\");",
+ GetParam().video_codec.c_str()),
+ kMediaRecorderHtmlFile);
}
-IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest,
+IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest,
MediaRecorderStartWithTimeSlice) {
- MakeTypicalCall("testStartWithTimeSlice();", kMediaRecorderHtmlFile);
+ MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator);
+ MakeTypicalCall(base::StringPrintf("testStartWithTimeSlice(\"%s\");",
+ GetParam().video_codec.c_str()),
+ kMediaRecorderHtmlFile);
}
IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, MediaRecorderResume) {
@@ -68,9 +93,12 @@ IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest,
MakeTypicalCall("testIllegalResumeThrowsDOMError();", kMediaRecorderHtmlFile);
}
-IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest,
+IN_PROC_BROWSER_TEST_P(WebRtcMediaRecorderTest,
MediaRecorderResumeAndDataAvailable) {
- MakeTypicalCall("testResumeAndDataAvailable();", kMediaRecorderHtmlFile);
+ MaybeForceDisableEncodeAccelerator(GetParam().disable_accelerator);
+ MakeTypicalCall(base::StringPrintf("testResumeAndDataAvailable(\"%s\");",
+ GetParam().video_codec.c_str()),
+ kMediaRecorderHtmlFile);
}
IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest, MediaRecorderPause) {
@@ -145,4 +173,8 @@ IN_PROC_BROWSER_TEST_F(WebRtcMediaRecorderTest,
kMediaRecorderHtmlFile);
}
+INSTANTIATE_TEST_CASE_P(,
+ WebRtcMediaRecorderTest,
+ testing::ValuesIn(kEncodingParameters));
+
} // namespace content
diff --git a/chromium/content/browser/media/webrtc/webrtc_webcam_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_webcam_browsertest.cc
index 32eeb111532..d1269c972aa 100644
--- a/chromium/content/browser/media/webrtc/webrtc_webcam_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_webcam_browsertest.cc
@@ -78,9 +78,8 @@ IN_PROC_BROWSER_TEST_F(WebRtcWebcamBrowserTest,
NavigateToURL(shell(), url);
std::string result;
- ASSERT_TRUE(ExecuteScriptAndExtractString(shell()->web_contents(),
- "hasVideoInputDeviceOnSystem()",
- &result));
+ ASSERT_TRUE(ExecuteScriptAndExtractString(
+ shell(), "hasVideoInputDeviceOnSystem()", &result));
if (result != "has-video-input-device") {
VLOG(0) << "No video device; skipping test...";
return;
@@ -88,9 +87,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcWebcamBrowserTest,
// GetUserMedia should acquire VGA by default.
ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell()->web_contents(),
- "getUserMediaAndReturnVideoDimensions({video: true})",
- &result));
+ shell(), "getUserMediaAndReturnVideoDimensions({video: true})", &result));
if (result == "640x480" || result == "480x640") {
// Don't care if the device happens to be in landscape or portrait mode
diff --git a/chromium/content/browser/memory/memory_pressure_controller_impl_browsertest.cc b/chromium/content/browser/memory/memory_pressure_controller_impl_browsertest.cc
index 6673abe6467..933891dc16d 100644
--- a/chromium/content/browser/memory/memory_pressure_controller_impl_browsertest.cc
+++ b/chromium/content/browser/memory/memory_pressure_controller_impl_browsertest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <tuple>
+
#include "base/bind.h"
#include "base/memory/memory_pressure_listener.h"
#include "content/browser/memory/memory_message_filter.h"
@@ -24,7 +26,7 @@ MATCHER_P(IsSetSuppressedMessage, suppressed, "") {
if (!MemoryMsg_SetPressureNotificationsSuppressed::Read(message.get(),
&param))
return false;
- return suppressed == base::get<0>(param);
+ return suppressed == std::get<0>(param);
}
MATCHER_P(IsSimulateMessage, level, "") {
@@ -35,7 +37,7 @@ MATCHER_P(IsSimulateMessage, level, "") {
MemoryMsg_SimulatePressureNotification::Param param;
if (!MemoryMsg_SimulatePressureNotification::Read(message.get(), &param))
return false;
- return level == base::get<0>(param);
+ return level == std::get<0>(param);
}
MATCHER_P(IsPressureMessage, level, "") {
@@ -46,7 +48,7 @@ MATCHER_P(IsPressureMessage, level, "") {
MemoryMsg_PressureNotification::Param param;
if (!MemoryMsg_PressureNotification::Read(message.get(), &param))
return false;
- return level == base::get<0>(param);
+ return level == std::get<0>(param);
}
class MemoryMessageFilterForTesting : public MemoryMessageFilter {
diff --git a/chromium/content/browser/message_port_provider_browsertest.cc b/chromium/content/browser/message_port_provider_browsertest.cc
index 0a64396bed1..bac99abaa98 100644
--- a/chromium/content/browser/message_port_provider_browsertest.cc
+++ b/chromium/content/browser/message_port_provider_browsertest.cc
@@ -134,7 +134,8 @@ void VerifyCreateChannelOnIOThread(base::WaitableEvent* event) {
// Verify that a message channel can be created and used for exchanging
// messages.
IN_PROC_BROWSER_TEST_F(MessagePortProviderBrowserTest, CreateChannel) {
- base::WaitableEvent event(true, false);
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&VerifyCreateChannelOnIOThread, &event));
diff --git a/chromium/content/browser/mime_registry_impl.cc b/chromium/content/browser/mime_registry_impl.cc
new file mode 100644
index 00000000000..aa3562535cf
--- /dev/null
+++ b/chromium/content/browser/mime_registry_impl.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/mime_registry_impl.h"
+
+#include "base/files/file_path.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/common/common_type_converters.h"
+#include "net/base/mime_util.h"
+
+namespace content {
+
+// static
+void MimeRegistryImpl::Create(blink::mojom::MimeRegistryRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ new MimeRegistryImpl(std::move(request));
+}
+
+MimeRegistryImpl::MimeRegistryImpl(blink::mojom::MimeRegistryRequest request)
+ : binding_(this, std::move(request)) {}
+
+MimeRegistryImpl::~MimeRegistryImpl() = default;
+
+void MimeRegistryImpl::GetMimeTypeFromExtension(
+ const mojo::String& extension,
+ const GetMimeTypeFromExtensionCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ std::string mime_type;
+ net::GetMimeTypeFromExtension(extension.To<base::FilePath::StringType>(),
+ &mime_type);
+ callback.Run(mime_type);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/mime_registry_impl.h b/chromium/content/browser/mime_registry_impl.h
new file mode 100644
index 00000000000..8adb70feb17
--- /dev/null
+++ b/chromium/content/browser/mime_registry_impl.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.
+
+#ifndef CONTENT_BROWSER_MIME_REGISTRY_IMPL_H_
+#define CONTENT_BROWSER_MIME_REGISTRY_IMPL_H_
+
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "third_party/WebKit/public/platform/mime_registry.mojom.h"
+
+namespace content {
+
+class MimeRegistryImpl : public blink::mojom::MimeRegistry {
+ public:
+ static void Create(blink::mojom::MimeRegistryRequest request);
+
+ private:
+ MimeRegistryImpl(blink::mojom::MimeRegistryRequest request);
+ ~MimeRegistryImpl() override;
+
+ void GetMimeTypeFromExtension(
+ const mojo::String& extension,
+ const GetMimeTypeFromExtensionCallback& callback) override;
+
+ mojo::StrongBinding<blink::mojom::MimeRegistry> binding_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MIME_REGISTRY_IMPL_H_
diff --git a/chromium/content/browser/mime_registry_message_filter.cc b/chromium/content/browser/mime_registry_message_filter.cc
deleted file mode 100644
index 1b6987e7876..00000000000
--- a/chromium/content/browser/mime_registry_message_filter.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All 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/mime_registry_message_filter.h"
-
-#include "content/common/mime_registry_messages.h"
-#include "net/base/mime_util.h"
-
-namespace content {
-
-MimeRegistryMessageFilter::MimeRegistryMessageFilter()
- : BrowserMessageFilter(MimeRegistryMsgStart) {
-}
-
-MimeRegistryMessageFilter::~MimeRegistryMessageFilter() {
-}
-
-void MimeRegistryMessageFilter::OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) {
- if (IPC_MESSAGE_CLASS(message) == MimeRegistryMsgStart)
- *thread = BrowserThread::FILE;
-}
-
-bool MimeRegistryMessageFilter::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(MimeRegistryMessageFilter, message)
- IPC_MESSAGE_HANDLER(MimeRegistryMsg_GetMimeTypeFromExtension,
- OnGetMimeTypeFromExtension)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void MimeRegistryMessageFilter::OnGetMimeTypeFromExtension(
- const base::FilePath::StringType& ext, std::string* mime_type) {
- net::GetMimeTypeFromExtension(ext, mime_type);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/mime_registry_message_filter.h b/chromium/content/browser/mime_registry_message_filter.h
deleted file mode 100644
index c4b110e98a2..00000000000
--- a/chromium/content/browser/mime_registry_message_filter.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2011 The Chromium 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_MIME_REGISTRY_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_MIME_REGISTRY_MESSAGE_FILTER_H_
-
-#include "base/files/file_path.h"
-#include "content/public/browser/browser_message_filter.h"
-
-namespace content {
-
-class MimeRegistryMessageFilter : public BrowserMessageFilter {
- public:
- MimeRegistryMessageFilter();
-
- void OverrideThreadForMessage(const IPC::Message& message,
- BrowserThread::ID* thread) override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- private:
- ~MimeRegistryMessageFilter() override;
-
- void OnGetMimeTypeFromExtension(const base::FilePath::StringType& ext,
- std::string* mime_type);
- void OnGetMimeTypeFromFile(const base::FilePath& file_path,
- std::string* mime_type);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MIME_REGISTRY_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/mojo/browser_shell_connection.cc b/chromium/content/browser/mojo/browser_shell_connection.cc
deleted file mode 100644
index 71e3bf3f368..00000000000
--- a/chromium/content/browser/mojo/browser_shell_connection.cc
+++ /dev/null
@@ -1,79 +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/mojo/browser_shell_connection.h"
-
-#include "base/bind.h"
-#include "content/browser/mojo/constants.h"
-#include "content/public/common/mojo_application_info.h"
-#include "services/shell/public/interfaces/connector.mojom.h"
-
-namespace content {
-
-BrowserShellConnection::BrowserShellConnection() {}
-
-BrowserShellConnection::BrowserShellConnection(
- shell::mojom::ShellClientRequest request)
- : shell_connection_(new shell::ShellConnection(this, std::move(request))) {}
-
-BrowserShellConnection::~BrowserShellConnection() {}
-
-shell::Connector* BrowserShellConnection::GetConnector() {
- DCHECK(shell_connection_);
- return shell_connection_->connector();
-}
-
-void BrowserShellConnection::AddEmbeddedApplication(
- const base::StringPiece& name,
- const MojoApplicationInfo& info) {
- std::unique_ptr<EmbeddedApplicationRunner> app(
- new EmbeddedApplicationRunner(name, info));
- AddShellClientRequestHandler(
- name, base::Bind(&EmbeddedApplicationRunner::BindShellClientRequest,
- base::Unretained(app.get())));
- auto result = embedded_apps_.insert(
- std::make_pair(name.as_string(), std::move(app)));
- DCHECK(result.second);
-}
-
-void BrowserShellConnection::AddShellClientRequestHandler(
- const base::StringPiece& name,
- const ShellClientRequestHandler& handler) {
- auto result = request_handlers_.insert(
- std::make_pair(name.as_string(), handler));
- DCHECK(result.second);
-}
-
-bool BrowserShellConnection::AcceptConnection(shell::Connection* connection) {
- std::string remote_app = connection->GetRemoteIdentity().name();
- if (remote_app == "mojo:shell") {
- // Only expose the SCF interface to the shell.
- connection->AddInterface<shell::mojom::ShellClientFactory>(this);
- return true;
- }
-
- // Allow connections from the root browser application.
- if (remote_app == kBrowserMojoApplicationName &&
- connection->GetRemoteIdentity().user_id() == shell::mojom::kRootUserID)
- return true;
-
- // Reject all other connections to this application.
- return false;
-}
-
-void BrowserShellConnection::Create(
- shell::Connection* connection,
- shell::mojom::ShellClientFactoryRequest request) {
- factory_bindings_.AddBinding(this, std::move(request));
-}
-
-void BrowserShellConnection::CreateShellClient(
- shell::mojom::ShellClientRequest request,
- const mojo::String& name) {
- auto it = request_handlers_.find(name);
- if (it != request_handlers_.end())
- it->second.Run(std::move(request));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/mojo/browser_shell_connection.h b/chromium/content/browser/mojo/browser_shell_connection.h
deleted file mode 100644
index 62968320a83..00000000000
--- a/chromium/content/browser/mojo/browser_shell_connection.h
+++ /dev/null
@@ -1,90 +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_MOJO_BROWSER_SHELL_CONNECTION_H_
-#define CONTENT_BROWSER_MOJO_BROWSER_SHELL_CONNECTION_H_
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_piece.h"
-#include "content/common/mojo/embedded_application_runner.h"
-#include "content/public/common/mojo_application_info.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/shell/public/cpp/connector.h"
-#include "services/shell/public/cpp/interface_factory.h"
-#include "services/shell/public/cpp/shell_client.h"
-#include "services/shell/public/cpp/shell_connection.h"
-#include "services/shell/public/interfaces/shell_client.mojom.h"
-#include "services/shell/public/interfaces/shell_client_factory.mojom.h"
-
-namespace content {
-
-// A connection from the browser process to the Mojo shell. There may be
-// multiple connections in a single browser process. Each connection may have
-// its own identity, e.g., a connection with unique user ID per BrowserContext.
-class BrowserShellConnection
- : public shell::ShellClient,
- public shell::InterfaceFactory<shell::mojom::ShellClientFactory>,
- public shell::mojom::ShellClientFactory {
- public:
- using ShellClientRequestHandler =
- base::Callback<void(shell::mojom::ShellClientRequest)>;
-
- // Constructs a connection which does not own a ShellClient pipe. This
- // connection must be manually fed new incoming connections via its
- // shell::ShellClient interface.
- BrowserShellConnection();
-
- // Constructs a connection associated with its own ShellClient pipe.
- explicit BrowserShellConnection(shell::mojom::ShellClientRequest request);
-
- ~BrowserShellConnection() override;
-
- shell::Connector* GetConnector();
-
- // Adds an embedded application to this connection's ShellClientFactory.
- // |info| provides details on how to construct new instances of the
- // application when an incoming connection is made to |name|.
- void AddEmbeddedApplication(const base::StringPiece& name,
- const MojoApplicationInfo& info);
-
- // Adds a generic ShellClientRequestHandler for a given application name. This
- // will be used to satisfy any incoming calls to CreateShellClient() which
- // reference the given name.
- //
- // For in-process applications, it is preferrable to use
- // |AddEmbeddedApplication()| as defined above.
- void AddShellClientRequestHandler(const base::StringPiece& name,
- const ShellClientRequestHandler& handler);
-
- private:
- // shell::ShellClient:
- bool AcceptConnection(shell::Connection* connection) override;
-
- // shell::InterfaceFactory<shell::mojom::ShellClientFactory>:
- void Create(shell::Connection* connection,
- shell::mojom::ShellClientFactoryRequest request) override;
-
- // shell::mojom::ShellClientFactory:
- void CreateShellClient(shell::mojom::ShellClientRequest request,
- const mojo::String& name) override;
-
- std::unique_ptr<shell::ShellConnection> shell_connection_;
- mojo::BindingSet<shell::mojom::ShellClientFactory> factory_bindings_;
- std::unordered_map<std::string, std::unique_ptr<EmbeddedApplicationRunner>>
- embedded_apps_;
- std::unordered_map<std::string, ShellClientRequestHandler> request_handlers_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserShellConnection);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MOJO_BROWSER_SHELL_CONNECTION_H_
diff --git a/chromium/content/browser/mojo/constants.cc b/chromium/content/browser/mojo/constants.cc
index cbb79379eeb..4fe5f2ab705 100644
--- a/chromium/content/browser/mojo/constants.cc
+++ b/chromium/content/browser/mojo/constants.cc
@@ -11,9 +11,19 @@ namespace content {
// src/content/public/app/mojo/content_browser_manifest.json.
const char kBrowserMojoApplicationName[] = "exe:content_browser";
+// The default application name used to identify the gpu process when
+// connecting it to the shell. This must match the name in
+// src/content/public/app/mojo/content_gpu_manifest.json.
+const char kGpuMojoApplicationName[] = "exe:content_gpu";
+
// The default application name used to identify render processes when
// connecting them to the shell. This must match the name in
// src/content/public/app/mojo/content_renderer_manifest.json.
const char kRendererMojoApplicationName[] = "exe:content_renderer";
+// The default application name used to identify utility processes when
+// connecting them to the shell. This must match the name in
+// src/content/public/app/mojo/content_utility_manifest.json.
+const char kUtilityMojoApplicationName[] = "exe:content_utility";
+
} // namespace content
diff --git a/chromium/content/browser/mojo/constants.h b/chromium/content/browser/mojo/constants.h
index ed6120a5c33..2fd761a17c7 100644
--- a/chromium/content/browser/mojo/constants.h
+++ b/chromium/content/browser/mojo/constants.h
@@ -8,7 +8,9 @@
namespace content {
extern const char kBrowserMojoApplicationName[];
+extern const char kGpuMojoApplicationName[];
extern const char kRendererMojoApplicationName[];
+extern const char kUtilityMojoApplicationName[];
} // namespace content
diff --git a/chromium/content/browser/mojo/mojo_app_connection_impl.cc b/chromium/content/browser/mojo/mojo_app_connection_impl.cc
deleted file mode 100644
index 582da64dc5d..00000000000
--- a/chromium/content/browser/mojo/mojo_app_connection_impl.cc
+++ /dev/null
@@ -1,50 +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/mojo/mojo_app_connection_impl.h"
-
-#include <stdint.h>
-#include <utility>
-
-#include "base/bind.h"
-#include "content/browser/mojo/mojo_shell_context.h"
-
-namespace content {
-
-const char kBrowserMojoAppUrl[] = "system:content_browser";
-
-namespace {
-void OnGotInstanceID(shell::mojom::ConnectResult result,
- const std::string& user_id,
- uint32_t remote_id) {}
-} // namespace
-
-// static
-std::unique_ptr<MojoAppConnection> MojoAppConnection::Create(
- const std::string& user_id,
- const std::string& name,
- const std::string& requestor_name) {
- return std::unique_ptr<MojoAppConnection>(
- new MojoAppConnectionImpl(user_id, name, requestor_name));
-}
-
-MojoAppConnectionImpl::MojoAppConnectionImpl(
- const std::string& user_id,
- const std::string& name,
- const std::string& requestor_name) {
- MojoShellContext::ConnectToApplication(
- user_id, name, requestor_name, mojo::GetProxy(&interfaces_),
- shell::mojom::InterfaceProviderPtr(), base::Bind(&OnGotInstanceID));
-}
-
-MojoAppConnectionImpl::~MojoAppConnectionImpl() {
-}
-
-void MojoAppConnectionImpl::GetInterface(
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle handle) {
- interfaces_->GetInterface(interface_name, std::move(handle));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/mojo/mojo_app_connection_impl.h b/chromium/content/browser/mojo/mojo_app_connection_impl.h
deleted file mode 100644
index e2ed0bd3dfb..00000000000
--- a/chromium/content/browser/mojo/mojo_app_connection_impl.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_MOJO_MOJO_APP_CONNECTION_IMPL_H_
-#define CONTENT_BROWSER_MOJO_MOJO_APP_CONNECTION_IMPL_H_
-
-#include "base/macros.h"
-#include "content/public/browser/mojo_app_connection.h"
-#include "services/shell/public/interfaces/interface_provider.mojom.h"
-
-namespace content {
-
-// Implementation of the app connection mechanism provided to browser code.
-class MojoAppConnectionImpl : public MojoAppConnection {
- public:
- // Takes a BrowserContext and derives a mojo userid from it for this
- // connection.
- MojoAppConnectionImpl(const std::string& user_id,
- const std::string& name,
- const std::string& requestor_name);
- ~MojoAppConnectionImpl() override;
-
- private:
- // MojoAppConnection:
- void GetInterface(const std::string& interface_name,
- mojo::ScopedMessagePipeHandle handle) override;
-
- shell::mojom::InterfaceProviderPtr interfaces_;
-
- DISALLOW_COPY_AND_ASSIGN(MojoAppConnectionImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MOJO_MOJO_APP_CONNECTION_IMPL_H_
diff --git a/chromium/content/browser/mojo/mojo_application_host.cc b/chromium/content/browser/mojo/mojo_application_host.cc
deleted file mode 100644
index f2b110e71b1..00000000000
--- a/chromium/content/browser/mojo/mojo_application_host.cc
+++ /dev/null
@@ -1,59 +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/mojo/mojo_application_host.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/embedder.h"
-
-namespace content {
-namespace {
-
-class ApplicationSetupImpl : public mojom::ApplicationSetup {
- public:
- ApplicationSetupImpl(ServiceRegistryImpl* service_registry,
- mojo::InterfaceRequest<mojom::ApplicationSetup> request)
- : binding_(this, std::move(request)),
- service_registry_(service_registry) {}
-
- ~ApplicationSetupImpl() override {
- }
-
- private:
- // mojom::ApplicationSetup implementation.
- void ExchangeInterfaceProviders(
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services) override {
- service_registry_->Bind(std::move(services));
- service_registry_->BindRemoteServiceProvider(std::move(exposed_services));
- }
-
- mojo::Binding<mojom::ApplicationSetup> binding_;
- ServiceRegistryImpl* service_registry_;
-};
-
-} // namespace
-
-MojoApplicationHost::MojoApplicationHost()
- : token_(mojo::edk::GenerateRandomToken()) {
-#if defined(OS_ANDROID)
- service_registry_android_ =
- ServiceRegistryAndroid::Create(&service_registry_);
-#endif
-
- mojo::ScopedMessagePipeHandle pipe =
- mojo::edk::CreateParentMessagePipe(token_);
- DCHECK(pipe.is_valid());
- application_setup_.reset(new ApplicationSetupImpl(
- &service_registry_,
- mojo::MakeRequest<mojom::ApplicationSetup>(std::move(pipe))));
-}
-
-MojoApplicationHost::~MojoApplicationHost() {
-}
-
-} // namespace content
diff --git a/chromium/content/browser/mojo/mojo_application_host.h b/chromium/content/browser/mojo/mojo_application_host.h
deleted file mode 100644
index b1bc026cfdc..00000000000
--- a/chromium/content/browser/mojo/mojo_application_host.h
+++ /dev/null
@@ -1,63 +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_MOJO_MOJO_APPLICATION_HOST_H_
-#define CONTENT_BROWSER_MOJO_MOJO_APPLICATION_HOST_H_
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "content/common/application_setup.mojom.h"
-#include "content/common/mojo/service_registry_impl.h"
-
-#if defined(OS_ANDROID)
-#include "content/public/browser/android/service_registry_android.h"
-#endif
-
-namespace IPC {
-class Sender;
-}
-
-namespace content {
-
-// MojoApplicationHost represents the code needed on the browser side to setup
-// a child process as a Mojo application. The child process should use the token
-// from GetToken() to initialize its MojoApplication. MojoApplicationHost makes
-// the ServiceRegistry interface available so that child-provided services can
-// be invoked.
-class CONTENT_EXPORT MojoApplicationHost {
- public:
- MojoApplicationHost();
- ~MojoApplicationHost();
-
- // Returns a token to pass to the child process to initialize its
- // MojoApplication.
- const std::string& GetToken() { return token_; }
-
- ServiceRegistry* service_registry() { return &service_registry_; }
-
-#if defined(OS_ANDROID)
- ServiceRegistryAndroid* service_registry_android() {
- return service_registry_android_.get();
- }
-#endif
-
- private:
- const std::string token_;
-
- std::unique_ptr<mojom::ApplicationSetup> application_setup_;
- ServiceRegistryImpl service_registry_;
-
-#if defined(OS_ANDROID)
- std::unique_ptr<ServiceRegistryAndroid> service_registry_android_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(MojoApplicationHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MOJO_MOJO_APPLICATION_HOST_H_
diff --git a/chromium/content/browser/mojo/mojo_child_connection.cc b/chromium/content/browser/mojo/mojo_child_connection.cc
index 333271a651e..896d8f5aafc 100644
--- a/chromium/content/browser/mojo/mojo_child_connection.cc
+++ b/chromium/content/browser/mojo/mojo_child_connection.cc
@@ -17,16 +17,12 @@
namespace content {
MojoChildConnection::MojoChildConnection(const std::string& application_name,
- const std::string& instance_id)
+ const std::string& instance_id,
+ const std::string& child_token,
+ shell::Connector* connector)
: shell_client_token_(mojo::edk::GenerateRandomToken()) {
mojo::ScopedMessagePipeHandle shell_client_pipe =
- mojo::edk::CreateParentMessagePipe(shell_client_token_);
-
- // Some process types get created before the main message loop. In this case
- // the shell request pipe will simply be closed, and the child can detect
- // this.
- if (!MojoShellConnection::Get())
- return;
+ mojo::edk::CreateParentMessagePipe(shell_client_token_, child_token);
shell::mojom::ShellClientPtr client;
client.Bind(mojo::InterfacePtrInfo<shell::mojom::ShellClient>(
@@ -39,7 +35,16 @@ MojoChildConnection::MojoChildConnection(const std::string& application_name,
shell::Connector::ConnectParams params(target);
params.set_client_process_connection(std::move(client),
std::move(pid_receiver_request));
- connection_ = MojoShellConnection::Get()->GetConnector()->Connect(&params);
+
+ // In some unit testing scenarios a null connector is passed.
+ if (!connector)
+ return;
+
+ connection_ = connector->Connect(&params);
+#if defined(OS_ANDROID)
+ service_registry_android_ = ServiceRegistryAndroid::Create(
+ connection_->GetInterfaceRegistry(), connection_->GetRemoteInterfaces());
+#endif
}
MojoChildConnection::~MojoChildConnection() {}
diff --git a/chromium/content/browser/mojo/mojo_child_connection.h b/chromium/content/browser/mojo/mojo_child_connection.h
index 369442725b0..7227284cc16 100644
--- a/chromium/content/browser/mojo/mojo_child_connection.h
+++ b/chromium/content/browser/mojo/mojo_child_connection.h
@@ -12,8 +12,13 @@
#include "base/process/process_handle.h"
#include "services/shell/public/interfaces/connector.mojom.h"
+#if defined(OS_ANDROID)
+#include "content/public/browser/android/service_registry_android.h"
+#endif
+
namespace shell {
class Connection;
+class Connector;
}
namespace content {
@@ -26,8 +31,11 @@ class MojoChildConnection {
// Prepares a new child connection for a child process which will be
// identified to the shell as |application_name|. |instance_id| must be
// unique among all child connections using the same |application_name|.
+ // |connector| is the connector to use to establish the connection.
MojoChildConnection(const std::string& application_name,
- const std::string& instance_id);
+ const std::string& instance_id,
+ const std::string& child_token,
+ shell::Connector* connector);
~MojoChildConnection();
shell::Connection* connection() const {
@@ -44,10 +52,19 @@ class MojoChildConnection {
// functional until this is called.
void SetProcessHandle(base::ProcessHandle handle);
+#if defined(OS_ANDROID)
+ ServiceRegistryAndroid* service_registry_android() {
+ return service_registry_android_.get();
+ }
+#endif
+
private:
const std::string shell_client_token_;
std::unique_ptr<shell::Connection> connection_;
shell::mojom::PIDReceiverPtr pid_receiver_;
+#if defined(OS_ANDROID)
+ std::unique_ptr<ServiceRegistryAndroid> service_registry_android_;
+#endif
DISALLOW_COPY_AND_ASSIGN(MojoChildConnection);
};
diff --git a/chromium/content/browser/mojo/mojo_shell_context.cc b/chromium/content/browser/mojo/mojo_shell_context.cc
index 9ed0b916dca..e454437fb83 100644
--- a/chromium/content/browser/mojo/mojo_shell_context.cc
+++ b/chromium/content/browser/mojo/mojo_shell_context.cc
@@ -16,7 +16,6 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/mojo/browser_shell_connection.h"
#include "content/browser/mojo/constants.h"
#include "content/common/gpu_process_launch_causes.h"
#include "content/common/mojo/mojo_shell_connection_impl.h"
@@ -28,7 +27,7 @@
#include "content/public/browser/utility_process_host_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/service_registry.h"
+#include "mojo/edk/embedder/embedder.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/string.h"
#include "services/catalog/catalog.h"
@@ -36,11 +35,13 @@
#include "services/catalog/store.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/identity.h"
#include "services/shell/public/cpp/shell_client.h"
#include "services/shell/public/interfaces/connector.mojom.h"
#include "services/shell/public/interfaces/shell_client.mojom.h"
#include "services/shell/public/interfaces/shell_client_factory.mojom.h"
+#include "services/shell/runner/common/client_util.h"
#include "services/shell/runner/host/in_process_native_runner.h"
#include "services/user/public/cpp/constants.h"
@@ -48,6 +49,21 @@ namespace content {
namespace {
+using ConnectorPtr = base::ThreadLocalPointer<shell::Connector>;
+
+base::LazyInstance<ConnectorPtr>::Leaky io_connector_tls_ptr =
+ LAZY_INSTANCE_INITIALIZER;
+
+void SetConnectorOnIOThread(std::unique_ptr<shell::Connector> connector) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ io_connector_tls_ptr.Pointer()->Set(connector.release());
+}
+
+void DestroyConnectorOnIOThread() {
+ delete MojoShellContext::GetConnectorForIOThread();
+ io_connector_tls_ptr.Pointer()->Set(nullptr);
+}
+
void StartUtilityProcessOnIOThread(
mojo::InterfaceRequest<mojom::ProcessControl> request,
const base::string16& process_name,
@@ -59,8 +75,7 @@ void StartUtilityProcessOnIOThread(
process_host->DisableSandbox();
process_host->Start();
- ServiceRegistry* services = process_host->GetServiceRegistry();
- services->ConnectToRemoteService(std::move(request));
+ process_host->GetRemoteInterfaces()->GetInterface(std::move(request));
}
void OnApplicationLoaded(const std::string& name, bool success) {
@@ -102,8 +117,7 @@ void RequestGpuProcessControl(
// load requests through mojom::ProcessControl will also fail. Make sure we
// handle
// these cases correctly.
- process_host->GetServiceRegistry()->ConnectToRemoteService(
- std::move(request));
+ process_host->GetRemoteInterfaces()->GetInterface(std::move(request));
}
void LaunchAppInGpuProcess(const std::string& app_name,
@@ -210,26 +224,6 @@ class MojoShellContext::Proxy {
DISALLOW_COPY_AND_ASSIGN(Proxy);
};
-// Used to attach an existing ShellClient instance as a listener on the global
-// MojoShellConnection.
-// TODO(rockot): Find a way to get rid of this.
-class ShellConnectionListener : public MojoShellConnection::Listener {
- public:
- ShellConnectionListener(std::unique_ptr<shell::ShellClient> client)
- : client_(std::move(client)) {}
- ~ShellConnectionListener() override {}
-
- private:
- // MojoShellConnection::Listener:
- bool AcceptConnection(shell::Connection* connection) override {
- return client_->AcceptConnection(connection);
- }
-
- std::unique_ptr<shell::ShellClient> client_;
-
- DISALLOW_COPY_AND_ASSIGN(ShellConnectionListener);
-};
-
// static
base::LazyInstance<std::unique_ptr<MojoShellContext::Proxy>>
MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER;
@@ -254,8 +248,12 @@ MojoShellContext::MojoShellContext() {
manifest_provider_->AddManifests(std::move(manifests));
manifest_provider_->AddManifestResource(kBrowserMojoApplicationName,
IDR_MOJO_CONTENT_BROWSER_MANIFEST);
+ manifest_provider_->AddManifestResource(kGpuMojoApplicationName,
+ IDR_MOJO_CONTENT_GPU_MANIFEST);
manifest_provider_->AddManifestResource(kRendererMojoApplicationName,
IDR_MOJO_CONTENT_RENDERER_MANIFEST);
+ manifest_provider_->AddManifestResource(kUtilityMojoApplicationName,
+ IDR_MOJO_CONTENT_UTILITY_MANIFEST);
manifest_provider_->AddManifestResource("mojo:catalog",
IDR_MOJO_CATALOG_MANIFEST);
manifest_provider_->AddManifestResource(user_service::kUserServiceName,
@@ -264,29 +262,37 @@ MojoShellContext::MojoShellContext() {
catalog_.reset(new catalog::Catalog(file_task_runner.get(), nullptr,
manifest_provider_.get()));
- if (!IsRunningInMojoShell()) {
+ shell::mojom::ShellClientRequest request;
+ if (shell::ShellIsRemote()) {
+ mojo::edk::SetParentPipeHandleFromCommandLine();
+ request = shell::GetShellClientRequestFromCommandLine();
+ } else {
shell_.reset(new shell::Shell(std::move(native_runner_factory),
catalog_->TakeShellClient()));
- MojoShellConnection::Create(
- shell_->InitInstanceForEmbedder(kBrowserMojoApplicationName),
- false /* is_external */);
+ request = shell_->InitInstanceForEmbedder(kBrowserMojoApplicationName);
}
- GetContentClient()->browser()->AddMojoShellConnectionListeners();
+ MojoShellConnection::SetForProcess(
+ MojoShellConnection::Create(std::move(request)));
- std::unique_ptr<BrowserShellConnection> browser_shell_connection(
- new BrowserShellConnection);
+ std::unique_ptr<shell::Connector> io_connector =
+ MojoShellConnection::GetForProcess()->GetConnector()->Clone();
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&SetConnectorOnIOThread, base::Passed(&io_connector)));
ContentBrowserClient::StaticMojoApplicationMap apps;
GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps);
- for (const auto& entry : apps)
- browser_shell_connection->AddEmbeddedApplication(entry.first, entry.second);
+ for (const auto& entry : apps) {
+ MojoShellConnection::GetForProcess()->AddEmbeddedService(entry.first,
+ entry.second);
+ }
ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps;
GetContentClient()
->browser()
->RegisterOutOfProcessMojoApplications(&sandboxed_apps);
for (const auto& app : sandboxed_apps) {
- browser_shell_connection->AddShellClientRequestHandler(
+ MojoShellConnection::GetForProcess()->AddShellClientRequestHandler(
app.first,
base::Bind(&LaunchAppInUtilityProcess, app.first, app.second,
true /* use_sandbox */));
@@ -297,27 +303,23 @@ MojoShellContext::MojoShellContext() {
->browser()
->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps);
for (const auto& app : unsandboxed_apps) {
- browser_shell_connection->AddShellClientRequestHandler(
+ MojoShellConnection::GetForProcess()->AddShellClientRequestHandler(
app.first,
base::Bind(&LaunchAppInUtilityProcess, app.first, app.second,
false /* use_sandbox */));
}
#if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
- browser_shell_connection->AddShellClientRequestHandler(
+ MojoShellConnection::GetForProcess()->AddShellClientRequestHandler(
"mojo:media", base::Bind(&LaunchAppInGpuProcess, "mojo:media"));
#endif
-
- // Attach our ShellClientFactory implementation to the global connection.
- MojoShellConnection* shell_connection = MojoShellConnection::Get();
- CHECK(shell_connection);
- shell_connection->AddListener(base::WrapUnique(
- new ShellConnectionListener(std::move(browser_shell_connection))));
}
MojoShellContext::~MojoShellContext() {
- if (!IsRunningInMojoShell())
- MojoShellConnectionImpl::Destroy();
+ if (MojoShellConnection::GetForProcess())
+ MojoShellConnection::DestroyForProcess();
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&DestroyConnectorOnIOThread));
catalog_.reset();
}
@@ -334,6 +336,12 @@ void MojoShellContext::ConnectToApplication(
std::move(exposed_services), callback);
}
+// static
+shell::Connector* MojoShellContext::GetConnectorForIOThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return io_connector_tls_ptr.Pointer()->Get();
+}
+
void MojoShellContext::ConnectToApplicationOnOwnThread(
const std::string& user_id,
const std::string& name,
diff --git a/chromium/content/browser/mojo/mojo_shell_context.h b/chromium/content/browser/mojo/mojo_shell_context.h
index dc738a45abb..6ef9f895680 100644
--- a/chromium/content/browser/mojo/mojo_shell_context.h
+++ b/chromium/content/browser/mojo/mojo_shell_context.h
@@ -45,6 +45,9 @@ class CONTENT_EXPORT MojoShellContext {
shell::mojom::InterfaceProviderPtr exposed_services,
const shell::mojom::Connector::ConnectCallback& callback);
+ // Returns a shell::Connector that can be used on the IO thread.
+ static shell::Connector* GetConnectorForIOThread();
+
private:
class BuiltinManifestProvider;
class Proxy;
diff --git a/chromium/content/browser/net/network_errors_listing_ui.cc b/chromium/content/browser/net/network_errors_listing_ui.cc
index 9f29c2869f0..86ed0bb068b 100644
--- a/chromium/content/browser/net/network_errors_listing_ui.cc
+++ b/chromium/content/browser/net/network_errors_listing_ui.cc
@@ -4,8 +4,12 @@
#include "content/browser/net/network_errors_listing_ui.h"
+#include <memory>
+#include <utility>
+
#include "base/bind.h"
#include "base/json/json_writer.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/values.h"
#include "content/grit/content_resources.h"
#include "content/public/browser/web_contents.h"
@@ -44,10 +48,10 @@ std::unique_ptr<base::ListValue> GetNetworkErrorData() {
// Exclude the aborted and pending codes as these don't return a page.
if (error_code != net::Error::ERR_IO_PENDING &&
error_code != net::Error::ERR_ABORTED) {
- base::DictionaryValue* error = new base::DictionaryValue();
+ std::unique_ptr<base::DictionaryValue> error(new base::DictionaryValue());
error->SetInteger(kErrorIdField, error_code);
error->SetString(kErrorCodeField, itr.key());
- error_list->Append(error);
+ error_list->Append(std::move(error));
}
}
return error_list;
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 3fb8a5b7e84..59d97fe89a0 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
@@ -15,12 +15,13 @@
#include "content/browser/net/quota_policy_cookie_store.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/base/test_data_directory.h"
#include "net/cookies/cookie_util.h"
#include "net/ssl/ssl_client_cert_type.h"
#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
namespace {
const base::FilePath::CharType kTestCookiesFilename[] =
@@ -36,9 +37,10 @@ class QuotaPolicyCookieStoreTest : public testing::Test {
public:
QuotaPolicyCookieStoreTest()
: pool_owner_(new base::SequencedWorkerPoolOwner(3, "Background Pool")),
- loaded_event_(false, false),
- destroy_event_(false, false) {
- }
+ loaded_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ destroy_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED) {}
void OnLoaded(const CanonicalCookieVector& cookies) {
cookies_ = cookies;
@@ -91,14 +93,15 @@ class QuotaPolicyCookieStoreTest : public testing::Test {
}
// Adds a persistent cookie to store_.
- void AddCookie(const std::string& name,
+ void AddCookie(const GURL& url,
+ const std::string& name,
const std::string& value,
const std::string& domain,
const std::string& path,
const base::Time& creation) {
- store_->AddCookie(net::CanonicalCookie(
- GURL(), name, value, domain, path, creation, creation, creation, false,
- false, net::CookieSameSite::DEFAULT_MODE,
+ store_->AddCookie(*net::CanonicalCookie::Create(
+ url, name, value, domain, path, creation, creation, false, false,
+ net::CookieSameSite::DEFAULT_MODE, false,
net::COOKIE_PRIORITY_DEFAULT));
}
@@ -136,9 +139,9 @@ TEST_F(QuotaPolicyCookieStoreTest, TestPersistence) {
ASSERT_EQ(0U, cookies.size());
base::Time t = base::Time::Now();
- AddCookie("A", "B", "foo.com", "/", t);
+ AddCookie(GURL("http://foo.com"), "A", "B", std::string(), "/", t);
t += base::TimeDelta::FromInternalValue(10);
- AddCookie("A", "B", "persistent.com", "/", t);
+ AddCookie(GURL("http://persistent.com"), "A", "B", std::string(), "/", t);
// Replace the store, which forces the current store to flush data to
// disk. Then, after reloading the store, confirm that the data was flushed by
@@ -180,11 +183,11 @@ TEST_F(QuotaPolicyCookieStoreTest, TestPolicy) {
ASSERT_EQ(0U, cookies.size());
base::Time t = base::Time::Now();
- AddCookie("A", "B", "foo.com", "/", t);
+ AddCookie(GURL("http://foo.com"), "A", "B", std::string(), "/", t);
t += base::TimeDelta::FromInternalValue(10);
- AddCookie("A", "B", "persistent.com", "/", t);
+ AddCookie(GURL("http://persistent.com"), "A", "B", std::string(), "/", t);
t += base::TimeDelta::FromInternalValue(10);
- AddCookie("A", "B", "nonpersistent.com", "/", t);
+ AddCookie(GURL("http://nonpersistent.com"), "A", "B", std::string(), "/", t);
// Replace the store, which forces the current store to flush data to
// disk. Then, after reloading the store, confirm that the data was flushed by
@@ -203,7 +206,8 @@ TEST_F(QuotaPolicyCookieStoreTest, TestPolicy) {
EXPECT_EQ(3U, cookies.size());
t += base::TimeDelta::FromInternalValue(10);
- AddCookie("A", "B", "nonpersistent.com", "/second", t);
+ AddCookie(GURL("http://nonpersistent.com"), "A", "B", std::string(),
+ "/second", t);
// Now close the store, and "nonpersistent.com" should be deleted according to
// policy.
@@ -224,7 +228,7 @@ TEST_F(QuotaPolicyCookieStoreTest, ForceKeepSessionState) {
ASSERT_EQ(0U, cookies.size());
base::Time t = base::Time::Now();
- AddCookie("A", "B", "foo.com", "/", t);
+ AddCookie(GURL("http://foo.com"), "A", "B", std::string(), "/", t);
// Recreate |store_| with a storage policy that makes "nonpersistent.com"
// session only, but then instruct the store to forcibly keep all cookies.
@@ -240,9 +244,9 @@ TEST_F(QuotaPolicyCookieStoreTest, ForceKeepSessionState) {
EXPECT_EQ(1U, cookies.size());
t += base::TimeDelta::FromInternalValue(10);
- AddCookie("A", "B", "persistent.com", "/", t);
+ AddCookie(GURL("http://persistent.com"), "A", "B", std::string(), "/", t);
t += base::TimeDelta::FromInternalValue(10);
- AddCookie("A", "B", "nonpersistent.com", "/", t);
+ AddCookie(GURL("http://nonpersistent.com"), "A", "B", std::string(), "/", t);
// Now close the store, but the "nonpersistent.com" cookie should not be
// deleted.
@@ -269,7 +273,7 @@ TEST_F(QuotaPolicyCookieStoreTest, TestDestroyOnBackgroundThread) {
ASSERT_EQ(0U, cookies.size());
base::Time t = base::Time::Now();
- AddCookie("A", "B", "nonpersistent.com", "/", t);
+ AddCookie(GURL("http://nonpersistent.com"), "A", "B", std::string(), "/", t);
// Replace the store, which forces the current store to flush data to
// disk. Then, after reloading the store, confirm that the data was flushed by
diff --git a/chromium/content/browser/net_info_browsertest.cc b/chromium/content/browser/net_info_browsertest.cc
index 5a845561db2..ba66337c6d9 100644
--- a/chromium/content/browser/net_info_browsertest.cc
+++ b/chromium/content/browser/net_info_browsertest.cc
@@ -58,15 +58,13 @@ class NetInfoBrowserTest : public content::ContentBrowserTest {
std::string RunScriptExtractString(const std::string& script) {
std::string data;
- EXPECT_TRUE(
- ExecuteScriptAndExtractString(shell()->web_contents(), script, &data));
+ EXPECT_TRUE(ExecuteScriptAndExtractString(shell(), script, &data));
return data;
}
bool RunScriptExtractBool(const std::string& script) {
bool data;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(shell()->web_contents(), script, &data));
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(shell(), script, &data));
return data;
}
@@ -136,8 +134,7 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, TwoRenderViewsInOneProcess) {
EXPECT_FALSE(RunScriptExtractBool("getOnLine()"));
// Open the same page in a new window on the same process.
- EXPECT_TRUE(
- ExecuteScript(shell()->web_contents(), "window.open(\"net_info.html\")"));
+ EXPECT_TRUE(ExecuteScript(shell(), "window.open(\"net_info.html\")"));
// The network state should not have reinitialized to what it was when opening
// the first window (online).
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl.cc b/chromium/content/browser/notifications/blink_notification_service_impl.cc
new file mode 100644
index 00000000000..8db1cdd25b4
--- /dev/null
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.cc
@@ -0,0 +1,71 @@
+// 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/notifications/blink_notification_service_impl.h"
+
+#include "base/logging.h"
+#include "content/browser/notifications/platform_notification_context_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/platform_notification_service.h"
+#include "content/public/common/content_client.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+// Returns the implementation of the PlatformNotificationService. May be NULL.
+PlatformNotificationService* Service() {
+ return GetContentClient()->browser()->GetPlatformNotificationService();
+}
+
+} // namespace
+
+BlinkNotificationServiceImpl::BlinkNotificationServiceImpl(
+ PlatformNotificationContextImpl* notification_context,
+ ResourceContext* resource_context,
+ int render_process_id,
+ mojo::InterfaceRequest<blink::mojom::NotificationService> request)
+ : notification_context_(notification_context),
+ resource_context_(resource_context),
+ render_process_id_(render_process_id),
+ binding_(this, std::move(request)) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(notification_context_);
+ DCHECK(resource_context_);
+
+ binding_.set_connection_error_handler(
+ base::Bind(&BlinkNotificationServiceImpl::OnConnectionError,
+ base::Unretained(this) /* the channel is owned by this */));
+}
+
+BlinkNotificationServiceImpl::~BlinkNotificationServiceImpl() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+void BlinkNotificationServiceImpl::GetPermissionStatus(
+ const mojo::String& origin,
+ const GetPermissionStatusCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!Service()) {
+ callback.Run(blink::mojom::PermissionStatus::DENIED);
+ return;
+ }
+
+ blink::mojom::PermissionStatus permission_status =
+ Service()->CheckPermissionOnIOThread(
+ resource_context_, GURL(origin.get()), render_process_id_);
+
+ callback.Run(permission_status);
+}
+
+void BlinkNotificationServiceImpl::OnConnectionError() {
+ notification_context_->RemoveService(this);
+ // |this| has now been deleted.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl.h b/chromium/content/browser/notifications/blink_notification_service_impl.h
new file mode 100644
index 00000000000..30826de1661
--- /dev/null
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_NOTIFICATIONS_BLINK_NOTIFICATION_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_NOTIFICATIONS_BLINK_NOTIFICATION_SERVICE_IMPL_H_
+
+#include "base/macros.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "third_party/WebKit/public/platform/modules/notifications/notification_service.mojom.h"
+
+namespace content {
+
+class PlatformNotificationContextImpl;
+class ResourceContext;
+
+// Implementation of the NotificationService used for Web Notifications. Is
+// responsible for displaying, updating and reading of both non-persistent
+// and persistent notifications. Lives on the IO thread.
+class BlinkNotificationServiceImpl : public blink::mojom::NotificationService {
+ public:
+ BlinkNotificationServiceImpl(
+ PlatformNotificationContextImpl* notification_context,
+ ResourceContext* resource_context,
+ int render_process_id,
+ mojo::InterfaceRequest<blink::mojom::NotificationService> request);
+ ~BlinkNotificationServiceImpl() override;
+
+ // blink::mojom::NotificationService implementation.
+ void GetPermissionStatus(
+ const mojo::String& origin,
+ const GetPermissionStatusCallback& callback) override;
+
+ private:
+ // Called when an error is detected on binding_.
+ void OnConnectionError();
+
+ // The notification context that owns this service instance.
+ PlatformNotificationContextImpl* notification_context_;
+
+ ResourceContext* resource_context_;
+
+ int render_process_id_;
+
+ mojo::Binding<blink::mojom::NotificationService> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlinkNotificationServiceImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NOTIFICATIONS_BLINK_NOTIFICATION_SERVICE_IMPL_H_
diff --git a/chromium/content/browser/notifications/notification_database.cc b/chromium/content/browser/notifications/notification_database.cc
index 3b4ba9fc5e3..31aa8f2a77e 100644
--- a/chromium/content/browser/notifications/notification_database.cc
+++ b/chromium/content/browser/notifications/notification_database.cc
@@ -58,8 +58,9 @@ NotificationDatabase::Status LevelDBStatusToStatus(
return NotificationDatabase::STATUS_IO_ERROR;
else if (status.IsNotSupportedError())
return NotificationDatabase::STATUS_NOT_SUPPORTED;
+ else if (status.IsInvalidArgument())
+ return NotificationDatabase::STATUS_INVALID_ARGUMENT;
- // TODO(cmumford): Once leveldb 1.19 is released add IsInvalidArgument().
return NotificationDatabase::STATUS_ERROR_FAILED;
}
diff --git a/chromium/content/browser/notifications/notification_database.h b/chromium/content/browser/notifications/notification_database.h
index 00fae877dae..5cc9ea93a27 100644
--- a/chromium/content/browser/notifications/notification_database.h
+++ b/chromium/content/browser/notifications/notification_database.h
@@ -61,9 +61,12 @@ class CONTENT_EXPORT NotificationDatabase {
// leveldb operation not supported
STATUS_NOT_SUPPORTED = 5,
+ // Invalid database ID or snapshot ID provided.
+ STATUS_INVALID_ARGUMENT = 6,
+
// Number of entries in the status enumeration. Used by UMA. Must always be
// one higher than the otherwise highest value in this enumeration.
- STATUS_COUNT = 6
+ STATUS_COUNT = 7
};
explicit NotificationDatabase(const base::FilePath& path);
diff --git a/chromium/content/browser/notifications/notification_message_filter.cc b/chromium/content/browser/notifications/notification_message_filter.cc
index 876a89c11e1..d522e75f7d5 100644
--- a/chromium/content/browser/notifications/notification_message_filter.cc
+++ b/chromium/content/browser/notifications/notification_message_filter.cc
@@ -95,8 +95,6 @@ void NotificationMessageFilter::OnDestruct() const {
bool NotificationMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(NotificationMessageFilter, message)
- IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_CheckPermission,
- OnCheckNotificationPermission)
IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_Show,
OnShowPlatformNotification)
IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_ShowPersistent,
@@ -121,14 +119,6 @@ void NotificationMessageFilter::OverrideThreadForMessage(
*thread = BrowserThread::UI;
}
-void NotificationMessageFilter::OnCheckNotificationPermission(
- const GURL& origin,
- blink::mojom::PermissionStatus* permission_status) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- *permission_status = GetPermissionForOriginOnIO(origin);
-}
-
void NotificationMessageFilter::OnShowPlatformNotification(
int notification_id,
const GURL& origin,
diff --git a/chromium/content/browser/notifications/notification_message_filter.h b/chromium/content/browser/notifications/notification_message_filter.h
index c8987b7983f..919499b47dc 100644
--- a/chromium/content/browser/notifications/notification_message_filter.h
+++ b/chromium/content/browser/notifications/notification_message_filter.h
@@ -53,9 +53,6 @@ class NotificationMessageFilter : public BrowserMessageFilter {
friend class base::DeleteHelper<NotificationMessageFilter>;
friend class BrowserThread;
- void OnCheckNotificationPermission(
- const GURL& origin,
- blink::mojom::PermissionStatus* permission_status);
void OnShowPlatformNotification(
int notification_id,
const GURL& origin,
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.cc b/chromium/content/browser/notifications/platform_notification_context_impl.cc
index 99c9591c1fb..9028997002c 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.cc
@@ -6,10 +6,13 @@
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "content/browser/notifications/blink_notification_service_impl.h"
#include "content/browser/notifications/notification_database.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_database_data.h"
@@ -94,11 +97,45 @@ void PlatformNotificationContextImpl::Shutdown() {
void PlatformNotificationContextImpl::ShutdownOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ services_.clear();
+
// |service_worker_context_| may be NULL in tests.
if (service_worker_context_)
service_worker_context_->RemoveObserver(this);
}
+void PlatformNotificationContextImpl::CreateService(
+ int render_process_id,
+ mojo::InterfaceRequest<blink::mojom::NotificationService> request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PlatformNotificationContextImpl::CreateServiceOnIO, this,
+ render_process_id, browser_context_->GetResourceContext(),
+ base::Passed(&request)));
+}
+
+void PlatformNotificationContextImpl::CreateServiceOnIO(
+ int render_process_id,
+ ResourceContext* resource_context,
+ mojo::InterfaceRequest<blink::mojom::NotificationService> request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ services_.push_back(base::WrapUnique(new BlinkNotificationServiceImpl(
+ this, resource_context, render_process_id, std::move(request))));
+}
+
+void PlatformNotificationContextImpl::RemoveService(
+ BlinkNotificationServiceImpl* service) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto services_to_remove = std::remove_if(
+ services_.begin(), services_.end(),
+ [service](const std::unique_ptr<BlinkNotificationServiceImpl>& ptr) {
+ return ptr.get() == service;
+ });
+
+ services_.erase(services_to_remove, services_.end());
+}
+
void PlatformNotificationContextImpl::ReadNotificationData(
int64_t notification_id,
const GURL& origin,
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.h b/chromium/content/browser/notifications/platform_notification_context_impl.h
index f2eb599f4db..7d05ad11d09 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.h
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.h
@@ -6,8 +6,8 @@
#define CONTENT_BROWSER_NOTIFICATIONS_PLATFORM_NOTIFICATION_CONTEXT_IMPL_H_
#include <stdint.h>
-#include <set>
#include <string>
+#include <vector>
#include "base/callback.h"
#include "base/compiler_specific.h"
@@ -18,6 +18,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/platform_notification_context.h"
+#include "third_party/WebKit/public/platform/modules/notifications/notification_service.mojom.h"
class GURL;
@@ -27,9 +28,11 @@ class SequencedTaskRunner;
namespace content {
+class BlinkNotificationServiceImpl;
class BrowserContext;
class NotificationDatabase;
struct NotificationDatabaseData;
+class ResourceContext;
class ServiceWorkerContextWrapper;
// Implementation of the Web Notification storage context. The public methods
@@ -54,6 +57,17 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
// To be called on the UI thread when the context is being shut down.
void Shutdown();
+ // Creates a BlinkNotificationServiceImpl that is owned by this context. Must
+ // be called on the UI thread, although the service will be created on and
+ // bound to the IO thread.
+ void CreateService(
+ int render_process_id,
+ mojo::InterfaceRequest<blink::mojom::NotificationService> request);
+
+ // Removes |service| from the list of owned services, for example because the
+ // Mojo pipe disconnected. Must be called on the IO thread.
+ void RemoveService(BlinkNotificationServiceImpl* service);
+
// PlatformNotificationContext implementation.
void ReadNotificationData(int64_t notification_id,
const GURL& origin,
@@ -81,6 +95,10 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
void InitializeOnIO();
void ShutdownOnIO();
+ void CreateServiceOnIO(
+ int render_process_id,
+ ResourceContext* resource_context,
+ mojo::InterfaceRequest<blink::mojom::NotificationService> request);
// Initializes the database if neccesary. Must be called on the IO thread.
// |success_closure| will be invoked on a the |task_runner_| thread when
@@ -153,6 +171,10 @@ class CONTENT_EXPORT PlatformNotificationContextImpl
// Indicates whether the database should be pruned when it's opened.
bool prune_database_on_open_ = false;
+ // The notification services are owned by the platform context, and will be
+ // removed when either this class is destroyed or the Mojo pipe disconnects.
+ std::vector<std::unique_ptr<BlinkNotificationServiceImpl>> services_;
+
DISALLOW_COPY_AND_ASSIGN(PlatformNotificationContextImpl);
};
diff --git a/chromium/content/browser/permissions/permission_service_impl.cc b/chromium/content/browser/permissions/permission_service_impl.cc
index 5591797df1d..39daa643474 100644
--- a/chromium/content/browser/permissions/permission_service_impl.cc
+++ b/chromium/content/browser/permissions/permission_service_impl.cc
@@ -50,8 +50,8 @@ PermissionType PermissionNameToPermissionType(PermissionName name) {
// This function allows the usage of the the multiple request map
// with single requests.
void PermissionRequestResponseCallbackWrapper(
- const mojo::Callback<void(PermissionStatus)>& callback,
- const mojo::Array<PermissionStatus>& vector) {
+ const base::Callback<void(PermissionStatus)>& callback,
+ mojo::Array<PermissionStatus> vector) {
DCHECK_EQ(vector.size(), 1ul);
callback.Run(vector[0]);
}
@@ -59,7 +59,7 @@ void PermissionRequestResponseCallbackWrapper(
} // anonymous namespace
PermissionServiceImpl::PendingRequest::PendingRequest(
- const PermissionsStatusCallback& callback,
+ const RequestPermissionsCallback& callback,
int request_count)
: callback(callback),
request_count(request_count) {
@@ -115,6 +115,7 @@ void PermissionServiceImpl::OnConnectionError() {
void PermissionServiceImpl::RequestPermission(
PermissionName permission,
const mojo::String& origin,
+ bool user_gesture,
const PermissionStatusCallback& callback) {
// This condition is valid if the call is coming from a ChildThread instead of
// a RenderFrame. Some consumers of the service run in Workers and some in
@@ -160,7 +161,8 @@ void PermissionServiceImpl::OnRequestPermissionResponse(
void PermissionServiceImpl::RequestPermissions(
mojo::Array<PermissionName> permissions,
const mojo::String& origin,
- const PermissionsStatusCallback& callback) {
+ bool user_gesture,
+ const RequestPermissionsCallback& callback) {
if (permissions.is_null()) {
callback.Run(mojo::Array<PermissionStatus>());
return;
@@ -213,8 +215,8 @@ void PermissionServiceImpl::OnRequestPermissionsResponse(
int pending_request_id,
const std::vector<PermissionStatus>& result) {
PendingRequest* request = pending_requests_.Lookup(pending_request_id);
- PermissionsStatusCallback callback(request->callback);
- request->callback.reset();
+ RequestPermissionsCallback callback(request->callback);
+ request->callback.Reset();
pending_requests_.Remove(pending_request_id);
callback.Run(mojo::Array<PermissionStatus>::From(result));
}
@@ -240,7 +242,7 @@ void PermissionServiceImpl::CancelPendingOperations() {
it(&pending_subscriptions_); !it.IsAtEnd(); it.Advance()) {
it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType(
it.GetCurrentValue()->permission, it.GetCurrentValue()->origin));
- it.GetCurrentValue()->callback.reset();
+ it.GetCurrentValue()->callback.Reset();
permission_manager->UnsubscribePermissionStatusChange(
it.GetCurrentValue()->id);
}
@@ -365,7 +367,7 @@ void PermissionServiceImpl::OnPermissionStatusChanged(
PermissionStatusCallback callback = subscription->callback;
- subscription->callback.reset();
+ subscription->callback.Reset();
pending_subscriptions_.Remove(pending_subscription_id);
callback.Run(status);
diff --git a/chromium/content/browser/permissions/permission_service_impl.h b/chromium/content/browser/permissions/permission_service_impl.h
index dfda77549f1..208c05804ee 100644
--- a/chromium/content/browser/permissions/permission_service_impl.h
+++ b/chromium/content/browser/permissions/permission_service_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_PERMISSIONS_PERMISSION_SERVICE_IMPL_H_
#define CONTENT_BROWSER_PERMISSIONS_PERMISSION_SERVICE_IMPL_H_
+#include "base/callback.h"
#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -41,18 +42,16 @@ class PermissionServiceImpl : public blink::mojom::PermissionService {
private:
using PermissionStatusCallback =
- mojo::Callback<void(blink::mojom::PermissionStatus)>;
- using PermissionsStatusCallback =
- mojo::Callback<void(mojo::Array<blink::mojom::PermissionStatus>)>;
+ base::Callback<void(blink::mojom::PermissionStatus)>;
struct PendingRequest {
- PendingRequest(const PermissionsStatusCallback& callback,
+ PendingRequest(const RequestPermissionsCallback& callback,
int request_count);
~PendingRequest();
// Request ID received from the PermissionManager.
int id;
- PermissionsStatusCallback callback;
+ RequestPermissionsCallback callback;
int request_count;
};
using RequestsMap = IDMap<PendingRequest, IDMapOwnPointer>;
@@ -76,10 +75,12 @@ class PermissionServiceImpl : public blink::mojom::PermissionService {
const PermissionStatusCallback& callback) override;
void RequestPermission(blink::mojom::PermissionName permission,
const mojo::String& origin,
+ bool user_gesture,
const PermissionStatusCallback& callback) override;
void RequestPermissions(mojo::Array<blink::mojom::PermissionName> permissions,
const mojo::String& origin,
- const PermissionsStatusCallback& callback) override;
+ bool user_gesture,
+ const RequestPermissionsCallback& callback) override;
void RevokePermission(blink::mojom::PermissionName permission,
const mojo::String& origin,
const PermissionStatusCallback& callback) override;
diff --git a/chromium/content/browser/plugin_data_remover_impl.cc b/chromium/content/browser/plugin_data_remover_impl.cc
index e9273995d52..a489822467e 100644
--- a/chromium/content/browser/plugin_data_remover_impl.cc
+++ b/chromium/content/browser/plugin_data_remover_impl.cc
@@ -65,7 +65,9 @@ class PluginDataRemoverImpl::Context
BrowserThread::DeleteOnIOThread> {
public:
Context(base::Time begin_time, BrowserContext* browser_context)
- : event_(new base::WaitableEvent(true, false)),
+ : event_(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED)),
begin_time_(begin_time),
is_removing_(false),
browser_context_path_(browser_context->GetPath()) {
diff --git a/chromium/content/browser/plugin_private_storage_helper.cc b/chromium/content/browser/plugin_private_storage_helper.cc
new file mode 100644
index 00000000000..023693290d6
--- /dev/null
+++ b/chromium/content/browser/plugin_private_storage_helper.cc
@@ -0,0 +1,415 @@
+// 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/plugin_private_storage_helper.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <set>
+#include <string>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/files/file.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/browser/browser_thread.h"
+#include "ppapi/shared_impl/ppapi_constants.h"
+#include "storage/browser/fileapi/async_file_util.h"
+#include "storage/browser/fileapi/async_file_util_adapter.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/browser/fileapi/obfuscated_file_util.h"
+#include "storage/common/fileapi/file_system_util.h"
+
+namespace content {
+
+namespace {
+
+std::string StringTypeToString(const base::FilePath::StringType& value) {
+#if defined(OS_POSIX)
+ return value;
+#elif defined(OS_WIN)
+ return base::WideToUTF8(value);
+#endif
+}
+
+// Helper for checking the plugin private data for a specified origin and
+// plugin for the existance of any file that matches the time range specified.
+// All of the operations in this class are done on the IO thread.
+//
+// This class keeps track of outstanding async requests it generates, and does
+// not call |callback_| until they all respond (and thus don't need to worry
+// about lifetime of |this| in the async requests). If the data for the origin
+// needs to be deleted, it needs to be done on the file task runner, so we
+// want to ensure that there are no pending requests that may prevent the
+// date from being deleted.
+class PluginPrivateDataByOriginChecker {
+ public:
+ PluginPrivateDataByOriginChecker(
+ storage::FileSystemContext* filesystem_context,
+ const GURL& origin,
+ const std::string& plugin_name,
+ const base::Time begin,
+ const base::Time end,
+ const base::Callback<void(bool, const GURL&)>& callback)
+ : filesystem_context_(filesystem_context),
+ origin_(origin),
+ plugin_name_(plugin_name),
+ begin_(begin),
+ end_(end),
+ callback_(callback) {
+ // Create the filesystem ID.
+ fsid_ = storage::IsolatedContext::GetInstance()
+ ->RegisterFileSystemForVirtualPath(
+ storage::kFileSystemTypePluginPrivate,
+ ppapi::kPluginPrivateRootName, base::FilePath());
+ }
+ ~PluginPrivateDataByOriginChecker() {}
+
+ // Checks the files contained in the plugin private filesystem for |origin_|
+ // and |plugin_name_| for any file whose last modified time is between
+ // |begin_| and |end_|. |callback_| is called when all actions are complete
+ // with true and the origin if any such file is found, false and empty GURL
+ // otherwise.
+ void CheckFilesOnIOThread();
+
+ private:
+ void OnFileSystemOpened(base::File::Error result);
+ void OnDirectoryRead(const std::string& root,
+ base::File::Error result,
+ const storage::AsyncFileUtil::EntryList& file_list,
+ bool has_more);
+ void OnFileInfo(const std::string& file_name,
+ base::File::Error result,
+ const base::File::Info& file_info);
+
+ // Keeps track of the pending work. When |task_count_| goes to 0 then
+ // |callback_| is called and this helper object is destroyed.
+ void IncrementTaskCount();
+ void DecrementTaskCount();
+
+ // Not owned by this object. Caller is responsible for keeping the
+ // FileSystemContext alive until |callback_| is called.
+ storage::FileSystemContext* filesystem_context_;
+
+ const GURL origin_;
+ const std::string plugin_name_;
+ const base::Time begin_;
+ const base::Time end_;
+ const base::Callback<void(bool, const GURL&)> callback_;
+ std::string fsid_;
+ int task_count_ = 0;
+
+ // Keep track if the data for this origin needs to be deleted due to
+ // any file found that has last modified time between |begin_| and |end_|.
+ bool delete_this_origin_data_ = false;
+};
+
+void PluginPrivateDataByOriginChecker::CheckFilesOnIOThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(storage::ValidateIsolatedFileSystemId(fsid_));
+
+ IncrementTaskCount();
+ filesystem_context_->OpenPluginPrivateFileSystem(
+ origin_, storage::kFileSystemTypePluginPrivate, fsid_, plugin_name_,
+ storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ base::Bind(&PluginPrivateDataByOriginChecker::OnFileSystemOpened,
+ base::Unretained(this)));
+}
+
+void PluginPrivateDataByOriginChecker::OnFileSystemOpened(
+ base::File::Error result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DVLOG(3) << "Opened filesystem for " << origin_ << ":" << plugin_name_
+ << ", result: " << result;
+
+ // If we can't open the directory, we can't delete files so simply return.
+ if (result != base::File::FILE_OK) {
+ DecrementTaskCount();
+ return;
+ }
+
+ storage::AsyncFileUtil* file_util = filesystem_context_->GetAsyncFileUtil(
+ storage::kFileSystemTypePluginPrivate);
+ std::string root = storage::GetIsolatedFileSystemRootURIString(
+ origin_, fsid_, ppapi::kPluginPrivateRootName);
+ std::unique_ptr<storage::FileSystemOperationContext> operation_context =
+ base::WrapUnique(
+ new storage::FileSystemOperationContext(filesystem_context_));
+ file_util->ReadDirectory(
+ std::move(operation_context), filesystem_context_->CrackURL(GURL(root)),
+ base::Bind(&PluginPrivateDataByOriginChecker::OnDirectoryRead,
+ base::Unretained(this), root));
+}
+
+void PluginPrivateDataByOriginChecker::OnDirectoryRead(
+ const std::string& root,
+ base::File::Error result,
+ const storage::AsyncFileUtil::EntryList& file_list,
+ bool has_more) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DVLOG(3) << __FUNCTION__ << " result: " << result
+ << ", #files: " << file_list.size();
+
+ // Quit if there is an error.
+ if (result != base::File::FILE_OK) {
+ DLOG(ERROR) << "Unable to read directory for " << origin_ << ":"
+ << plugin_name_;
+ DecrementTaskCount();
+ return;
+ }
+
+ // No error, process the files returned. No need to do this if we have
+ // already decided to delete all the data for this origin.
+ if (!delete_this_origin_data_) {
+ storage::AsyncFileUtil* file_util = filesystem_context_->GetAsyncFileUtil(
+ storage::kFileSystemTypePluginPrivate);
+ for (const auto& file : file_list) {
+ DVLOG(3) << __FUNCTION__ << " file: " << file.name;
+ DCHECK(!file.is_directory); // Nested directories not implemented.
+
+ std::unique_ptr<storage::FileSystemOperationContext> operation_context =
+ base::WrapUnique(
+ new storage::FileSystemOperationContext(filesystem_context_));
+ storage::FileSystemURL file_url = filesystem_context_->CrackURL(
+ GURL(root + StringTypeToString(file.name)));
+ IncrementTaskCount();
+ file_util->GetFileInfo(
+ std::move(operation_context), file_url,
+ storage::FileSystemOperation::GET_METADATA_FIELD_SIZE |
+ storage::FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
+ base::Bind(&PluginPrivateDataByOriginChecker::OnFileInfo,
+ base::Unretained(this), StringTypeToString(file.name)));
+ }
+ }
+
+ // If there are more files in this directory, wait for the next call.
+ if (has_more)
+ return;
+
+ DecrementTaskCount();
+}
+
+void PluginPrivateDataByOriginChecker::OnFileInfo(
+ const std::string& file_name,
+ base::File::Error result,
+ const base::File::Info& file_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (result == base::File::FILE_OK) {
+ DVLOG(3) << __FUNCTION__ << " name: " << file_name
+ << ", size: " << file_info.size
+ << ", modified: " << file_info.last_modified;
+ if (file_info.last_modified >= begin_ && file_info.last_modified <= end_)
+ delete_this_origin_data_ = true;
+ }
+
+ DecrementTaskCount();
+}
+
+void PluginPrivateDataByOriginChecker::IncrementTaskCount() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ++task_count_;
+}
+
+void PluginPrivateDataByOriginChecker::DecrementTaskCount() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_GT(task_count_, 0);
+ --task_count_;
+ if (task_count_)
+ return;
+
+ // If there are no more tasks in progress, then run |callback_| on the
+ // proper thread.
+ filesystem_context_->default_file_task_runner()->PostTask(
+ FROM_HERE, base::Bind(callback_, delete_this_origin_data_, origin_));
+ delete this;
+}
+
+// Helper for deleting the plugin private data.
+// All of the operations in this class are done on the file task runner.
+class PluginPrivateDataDeletionHelper {
+ public:
+ PluginPrivateDataDeletionHelper(
+ scoped_refptr<storage::FileSystemContext> filesystem_context,
+ const base::Time begin,
+ const base::Time end,
+ const base::Closure& callback)
+ : filesystem_context_(std::move(filesystem_context)),
+ begin_(begin),
+ end_(end),
+ callback_(callback) {}
+ ~PluginPrivateDataDeletionHelper() {}
+
+ void CheckOriginsOnFileTaskRunner(const std::set<GURL>& origins);
+
+ private:
+ // Keeps track of the pending work. When |task_count_| goes to 0 then
+ // |callback_| is called and this helper object is destroyed.
+ void IncrementTaskCount();
+ void DecrementTaskCount(bool delete_data_for_origin, const GURL& origin);
+
+ // Keep a reference to FileSystemContext until we are done with it.
+ scoped_refptr<storage::FileSystemContext> filesystem_context_;
+
+ const base::Time begin_;
+ const base::Time end_;
+ const base::Closure callback_;
+ int task_count_ = 0;
+};
+
+void PluginPrivateDataDeletionHelper::CheckOriginsOnFileTaskRunner(
+ const std::set<GURL>& origins) {
+ DCHECK(filesystem_context_->default_file_task_runner()
+ ->RunsTasksOnCurrentThread());
+ IncrementTaskCount();
+
+ base::Callback<void(bool, const GURL&)> decrement_callback =
+ base::Bind(&PluginPrivateDataDeletionHelper::DecrementTaskCount,
+ base::Unretained(this));
+ storage::AsyncFileUtil* async_file_util =
+ filesystem_context_->GetAsyncFileUtil(
+ storage::kFileSystemTypePluginPrivate);
+ storage::ObfuscatedFileUtil* obfuscated_file_util =
+ static_cast<storage::ObfuscatedFileUtil*>(
+ static_cast<storage::AsyncFileUtilAdapter*>(async_file_util)
+ ->sync_file_util());
+ for (const auto& origin : origins) {
+ // Determine the available plugin private filesystem directories
+ // for this origin.
+ base::File::Error error;
+ base::FilePath path = obfuscated_file_util->GetDirectoryForOriginAndType(
+ origin, "", false, &error);
+ if (error != base::File::FILE_OK) {
+ DLOG(ERROR) << "Unable to read directory for " << origin;
+ continue;
+ }
+
+ // Currently the plugin private filesystem is only used by Encrypted
+ // Media Content Decryption Modules, which are treated as pepper plugins.
+ // Each CDM gets a directory based on the mimetype (e.g. plugin
+ // application/x-ppapi-widevine-cdm uses directory
+ // application_x-ppapi-widevine-cdm). Enumerate through the set of
+ // directories so that data from any CDM used by this origin is deleted.
+ base::FileEnumerator file_enumerator(path, false,
+ base::FileEnumerator::DIRECTORIES);
+ for (base::FilePath plugin_path = file_enumerator.Next();
+ !plugin_path.empty(); plugin_path = file_enumerator.Next()) {
+ IncrementTaskCount();
+ PluginPrivateDataByOriginChecker* helper =
+ new PluginPrivateDataByOriginChecker(
+ filesystem_context_.get(), origin.GetOrigin(),
+ plugin_path.BaseName().MaybeAsASCII(), begin_, end_,
+ decrement_callback);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PluginPrivateDataByOriginChecker::CheckFilesOnIOThread,
+ base::Unretained(helper)));
+
+ // |helper| will delete itself when it is done.
+ }
+ }
+
+ // Cancels out the call to IncrementTaskCount() at the start of this method.
+ // If there are no origins specified then this will cause this helper to
+ // be destroyed.
+ DecrementTaskCount(false, GURL());
+}
+
+void PluginPrivateDataDeletionHelper::IncrementTaskCount() {
+ DCHECK(filesystem_context_->default_file_task_runner()
+ ->RunsTasksOnCurrentThread());
+ ++task_count_;
+}
+
+void PluginPrivateDataDeletionHelper::DecrementTaskCount(
+ bool delete_data_for_origin,
+ const GURL& origin) {
+ DCHECK(filesystem_context_->default_file_task_runner()
+ ->RunsTasksOnCurrentThread());
+
+ // Since the PluginPrivateDataByOriginChecker runs on the IO thread,
+ // delete all the data for |origin| if needed.
+ if (delete_data_for_origin) {
+ DCHECK(!origin.is_empty());
+ DVLOG(3) << "Deleting plugin data for " << origin;
+ storage::FileSystemBackend* backend =
+ filesystem_context_->GetFileSystemBackend(
+ storage::kFileSystemTypePluginPrivate);
+ storage::FileSystemQuotaUtil* quota_util = backend->GetQuotaUtil();
+ base::File::Error result = quota_util->DeleteOriginDataOnFileTaskRunner(
+ filesystem_context_.get(), nullptr, origin,
+ storage::kFileSystemTypePluginPrivate);
+ ALLOW_UNUSED_LOCAL(result);
+ DLOG_IF(ERROR, result != base::File::FILE_OK)
+ << "Unable to delete the plugin data for " << origin;
+ }
+
+ DCHECK_GT(task_count_, 0);
+ --task_count_;
+ if (task_count_)
+ return;
+
+ // If there are no more tasks in progress, run |callback_| and then
+ // this helper can be deleted.
+ callback_.Run();
+ delete this;
+}
+
+} // namespace
+
+void ClearPluginPrivateDataOnFileTaskRunner(
+ scoped_refptr<storage::FileSystemContext> filesystem_context,
+ const GURL& storage_origin,
+ const base::Time begin,
+ const base::Time end,
+ const base::Closure& callback) {
+ DCHECK(filesystem_context->default_file_task_runner()
+ ->RunsTasksOnCurrentThread());
+ DVLOG(3) << "Clearing plugin data for origin: " << storage_origin;
+
+ storage::FileSystemBackend* backend =
+ filesystem_context->GetFileSystemBackend(
+ storage::kFileSystemTypePluginPrivate);
+ storage::FileSystemQuotaUtil* quota_util = backend->GetQuotaUtil();
+
+ // Determine the set of origins used.
+ std::set<GURL> origins;
+ quota_util->GetOriginsForTypeOnFileTaskRunner(
+ storage::kFileSystemTypePluginPrivate, &origins);
+
+ if (origins.empty()) {
+ // No origins, so nothing to do.
+ callback.Run();
+ return;
+ }
+
+ // If a specific origin is provided, then check that it is in the list
+ // returned and remove all the other origins.
+ if (!storage_origin.is_empty()) {
+ if (!ContainsKey(origins, storage_origin)) {
+ // Nothing matches, so nothing to do.
+ callback.Run();
+ return;
+ }
+
+ // List should only contain the one value that matches.
+ origins.clear();
+ origins.insert(storage_origin);
+ }
+
+ PluginPrivateDataDeletionHelper* helper = new PluginPrivateDataDeletionHelper(
+ std::move(filesystem_context), begin, end, callback);
+ helper->CheckOriginsOnFileTaskRunner(origins);
+ // |helper| will delete itself when all origins have been checked.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/plugin_private_storage_helper.h b/chromium/content/browser/plugin_private_storage_helper.h
new file mode 100644
index 00000000000..d23dba3763d
--- /dev/null
+++ b/chromium/content/browser/plugin_private_storage_helper.h
@@ -0,0 +1,37 @@
+// 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_PLUGIN_PRIVATE_STORAGE_HELPER_H_
+#define CONTENT_BROWSER_PLUGIN_PRIVATE_STORAGE_HELPER_H_
+
+#if !defined(ENABLE_PLUGINS)
+#error This file should only be included when plugins are enabled.
+#endif
+
+#include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
+#include "url/gurl.h"
+
+namespace storage {
+class FileSystemContext;
+}
+
+namespace content {
+
+// Clear the plugin private filesystem data in |filesystem_context| for
+// |storage_origin| if any file has a last modified time between |begin|
+// and |end|. If |storage_origin| is not specified, then all available
+// origins are checked. |callback| is called when the operation is complete.
+// This must be called on the file task runner.
+void ClearPluginPrivateDataOnFileTaskRunner(
+ scoped_refptr<storage::FileSystemContext> filesystem_context,
+ const GURL& storage_origin,
+ const base::Time begin,
+ const base::Time end,
+ const base::Closure& callback);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PLUGIN_PRIVATE_STORAGE_HELPER_H_
diff --git a/chromium/content/browser/power_save_blocker_android.cc b/chromium/content/browser/power_save_blocker_android.cc
deleted file mode 100644
index 0adcd290d5e..00000000000
--- a/chromium/content/browser/power_save_blocker_android.cc
+++ /dev/null
@@ -1,117 +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 "base/android/jni_android.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "content/browser/android/content_view_core_impl.h"
-#include "content/browser/power_save_blocker_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/android/content_view_core.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "jni/PowerSaveBlocker_jni.h"
-#include "ui/android/view_android.h"
-
-namespace content {
-
-using base::android::AttachCurrentThread;
-
-class PowerSaveBlockerImpl::Delegate
- : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate>,
- public WebContentsObserver {
- public:
- explicit Delegate(WebContents* web_contents);
-
- // Does the actual work to apply or remove the desired power save block.
- void ApplyBlock();
- void RemoveBlock();
-
- private:
- friend class base::RefCountedThreadSafe<Delegate>;
- ~Delegate() override;
-
- base::android::ScopedJavaLocalRef<jobject> GetContentViewCore();
-
- base::android::ScopedJavaGlobalRef<jobject> java_power_save_blocker_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
-};
-
-PowerSaveBlockerImpl::Delegate::Delegate(WebContents* web_contents)
- : WebContentsObserver(web_contents) {
- JNIEnv* env = AttachCurrentThread();
- java_power_save_blocker_.Reset(Java_PowerSaveBlocker_create(env));
-}
-
-PowerSaveBlockerImpl::Delegate::~Delegate() {
-}
-
-void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::android::ScopedJavaLocalRef<jobject> java_content_view_core =
- GetContentViewCore();
- if (java_content_view_core.is_null())
- return;
-
- ScopedJavaLocalRef<jobject> obj(java_power_save_blocker_);
- JNIEnv* env = AttachCurrentThread();
- Java_PowerSaveBlocker_applyBlock(env, obj.obj(),
- java_content_view_core.obj());
-}
-
-void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::android::ScopedJavaLocalRef<jobject> java_content_view_core =
- GetContentViewCore();
- if (java_content_view_core.is_null())
- return;
-
- ScopedJavaLocalRef<jobject> obj(java_power_save_blocker_);
- JNIEnv* env = AttachCurrentThread();
- Java_PowerSaveBlocker_removeBlock(env, obj.obj(),
- java_content_view_core.obj());
-}
-
-base::android::ScopedJavaLocalRef<jobject>
-PowerSaveBlockerImpl::Delegate::GetContentViewCore() {
- if (!web_contents())
- return base::android::ScopedJavaLocalRef<jobject>();
-
- ContentViewCoreImpl* content_view_core_impl =
- ContentViewCoreImpl::FromWebContents(web_contents());
- if (!content_view_core_impl)
- return base::android::ScopedJavaLocalRef<jobject>();
-
- return content_view_core_impl->GetJavaObject();
-}
-
-PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
- Reason reason,
- const std::string& description) {
- // Don't support kPowerSaveBlockPreventAppSuspension
-}
-
-PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
- if (delegate_.get()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, delegate_));
- }
-}
-
-void PowerSaveBlockerImpl::InitDisplaySleepBlocker(WebContents* web_contents) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!web_contents)
- return;
-
- delegate_ = new Delegate(web_contents);
- delegate_->ApplyBlock();
-}
-
-bool RegisterPowerSaveBlocker(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/power_save_blocker_android.h b/chromium/content/browser/power_save_blocker_android.h
deleted file mode 100644
index 1df7d697b53..00000000000
--- a/chromium/content/browser/power_save_blocker_android.h
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <jni.h>
-
-namespace content {
-
-bool RegisterPowerSaveBlocker(JNIEnv* env);
-
-} // namespace content
diff --git a/chromium/content/browser/power_save_blocker_chromeos.cc b/chromium/content/browser/power_save_blocker_chromeos.cc
deleted file mode 100644
index bf50c898451..00000000000
--- a/chromium/content/browser/power_save_blocker_chromeos.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/power_save_blocker_impl.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "chromeos/dbus/power_policy_controller.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-namespace {
-
-// Converts a PowerSaveBlocker::Reason to a
-// chromeos::PowerPolicyController::WakeLockReason.
-chromeos::PowerPolicyController::WakeLockReason GetWakeLockReason(
- PowerSaveBlocker::Reason reason) {
- switch (reason) {
- case PowerSaveBlocker::kReasonAudioPlayback:
- return chromeos::PowerPolicyController::REASON_AUDIO_PLAYBACK;
- case PowerSaveBlocker::kReasonVideoPlayback:
- return chromeos::PowerPolicyController::REASON_VIDEO_PLAYBACK;
- case PowerSaveBlocker::kReasonOther:
- return chromeos::PowerPolicyController::REASON_OTHER;
- }
- return chromeos::PowerPolicyController::REASON_OTHER;
-}
-
-} // namespace
-
-class PowerSaveBlockerImpl::Delegate
- : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
- public:
- Delegate(PowerSaveBlockerType type,
- Reason reason,
- const std::string& description)
- : type_(type), reason_(reason), description_(description), block_id_(0) {}
-
- void ApplyBlock() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!chromeos::PowerPolicyController::IsInitialized())
- return;
-
- auto* controller = chromeos::PowerPolicyController::Get();
- switch (type_) {
- case kPowerSaveBlockPreventAppSuspension:
- block_id_ = controller->AddSystemWakeLock(GetWakeLockReason(reason_),
- description_);
- break;
- case kPowerSaveBlockPreventDisplaySleep:
- block_id_ = controller->AddScreenWakeLock(GetWakeLockReason(reason_),
- description_);
- break;
- default:
- NOTREACHED() << "Unhandled block type " << type_;
- }
- }
-
- void RemoveBlock() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!chromeos::PowerPolicyController::IsInitialized())
- return;
-
- chromeos::PowerPolicyController::Get()->RemoveWakeLock(block_id_);
- }
-
- private:
- friend class base::RefCountedThreadSafe<Delegate>;
- virtual ~Delegate() {}
-
- PowerSaveBlockerType type_;
- Reason reason_;
- std::string description_;
-
- // ID corresponding to the block request in PowerPolicyController.
- int block_id_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
-};
-
-PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
- Reason reason,
- const std::string& description)
- : delegate_(new Delegate(type, reason, description)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&Delegate::ApplyBlock, delegate_));
-}
-
-PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, delegate_));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/power_save_blocker_impl.cc b/chromium/content/browser/power_save_blocker_impl.cc
deleted file mode 100644
index 52cb6a1dde1..00000000000
--- a/chromium/content/browser/power_save_blocker_impl.cc
+++ /dev/null
@@ -1,21 +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 "build/build_config.h"
-#include "content/browser/power_save_blocker_impl.h"
-
-namespace content {
-
-PowerSaveBlocker::~PowerSaveBlocker() {}
-
-// static
-std::unique_ptr<PowerSaveBlocker> PowerSaveBlocker::Create(
- PowerSaveBlockerType type,
- Reason reason,
- const std::string& description) {
- return std::unique_ptr<PowerSaveBlocker>(
- new PowerSaveBlockerImpl(type, reason, description));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/power_save_blocker_impl.h b/chromium/content/browser/power_save_blocker_impl.h
deleted file mode 100644
index a01fc60928a..00000000000
--- a/chromium/content/browser/power_save_blocker_impl.h
+++ /dev/null
@@ -1,60 +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_POWER_SAVE_BLOCKER_IMPL_H_
-#define CONTENT_BROWSER_POWER_SAVE_BLOCKER_IMPL_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "build/build_config.h"
-#include "content/public/browser/power_save_blocker.h"
-
-namespace content {
-
-class WebContents;
-
-class PowerSaveBlockerImpl : public PowerSaveBlocker {
- public:
- PowerSaveBlockerImpl(PowerSaveBlockerType type,
- Reason reason,
- const std::string& description);
- ~PowerSaveBlockerImpl() override;
-
-#if defined(OS_ANDROID)
- // In Android platform, the kPowerSaveBlockPreventDisplaySleep type of
- // PowerSaveBlocker should associated with a WebContents, so the blocker
- // could be removed by platform if the WebContents is hidden.
- void InitDisplaySleepBlocker(WebContents* web_contents);
-#endif
-
- private:
- class Delegate;
-
- // Implementations of this class may need a second object with different
- // lifetime than the RAII container, or additional storage. This member is
- // here for that purpose. If not used, just define the class as an empty
- // RefCounted (or RefCountedThreadSafe) like so to make it compile:
- // class PowerSaveBlocker::Delegate
- // : public base::RefCounted<PowerSaveBlocker::Delegate> {
- // private:
- // friend class base::RefCounted<Delegate>;
- // ~Delegate() {}
- // };
- scoped_refptr<Delegate> delegate_;
-
-#if defined(USE_X11)
- // Since display sleep prevention also implies system suspend prevention, for
- // the Linux FreeDesktop API case, there needs to be a second delegate to
- // block system suspend when screen saver / display sleep is blocked.
- scoped_refptr<Delegate> freedesktop_suspend_delegate_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_POWER_SAVE_BLOCKER_IMPL_H_
diff --git a/chromium/content/browser/power_save_blocker_mac.cc b/chromium/content/browser/power_save_blocker_mac.cc
deleted file mode 100644
index 0ce80f6a210..00000000000
--- a/chromium/content/browser/power_save_blocker_mac.cc
+++ /dev/null
@@ -1,115 +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/power_save_blocker_impl.h"
-
-#include <IOKit/pwr_mgt/IOPMLib.h>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-
-namespace content {
-namespace {
-
-// Power management cannot be done on the UI thread. IOPMAssertionCreate does a
-// synchronous MIG call to configd, so if it is called on the main thread the UI
-// is at the mercy of another process. See http://crbug.com/79559 and
-// http://www.opensource.apple.com/source/IOKitUser/IOKitUser-514.16.31/pwr_mgt.subproj/IOPMLibPrivate.c .
-struct PowerSaveBlockerLazyInstanceTraits {
- static const bool kRegisterOnExit = false;
-#ifndef NDEBUG
- static const bool kAllowedToAccessOnNonjoinableThread = true;
-#endif
-
- static base::Thread* New(void* instance) {
- base::Thread* thread = new (instance) base::Thread("PowerSaveBlocker");
- thread->Start();
- return thread;
- }
- static void Delete(base::Thread* instance) { }
-};
-base::LazyInstance<base::Thread, PowerSaveBlockerLazyInstanceTraits>
- g_power_thread = LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-class PowerSaveBlockerImpl::Delegate
- : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
- public:
- Delegate(PowerSaveBlockerType type, const std::string& description)
- : type_(type),
- description_(description),
- assertion_(kIOPMNullAssertionID) {}
-
- // Does the actual work to apply or remove the desired power save block.
- void ApplyBlock();
- void RemoveBlock();
-
- private:
- friend class base::RefCountedThreadSafe<Delegate>;
- ~Delegate() {}
- PowerSaveBlockerType type_;
- std::string description_;
- IOPMAssertionID assertion_;
-};
-
-void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
- DCHECK_EQ(base::PlatformThread::CurrentId(),
- g_power_thread.Pointer()->GetThreadId());
-
- CFStringRef level = NULL;
- // See QA1340 <http://developer.apple.com/library/mac/#qa/qa1340/> for more
- // details.
- switch (type_) {
- case PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension:
- level = kIOPMAssertionTypeNoIdleSleep;
- break;
- case PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep:
- level = kIOPMAssertionTypeNoDisplaySleep;
- break;
- default:
- NOTREACHED();
- break;
- }
- if (level) {
- base::ScopedCFTypeRef<CFStringRef> cf_description(
- base::SysUTF8ToCFStringRef(description_));
- IOReturn result = IOPMAssertionCreateWithName(level, kIOPMAssertionLevelOn,
- cf_description, &assertion_);
- LOG_IF(ERROR, result != kIOReturnSuccess)
- << "IOPMAssertionCreate: " << result;
- }
-}
-
-void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
- DCHECK_EQ(base::PlatformThread::CurrentId(),
- g_power_thread.Pointer()->GetThreadId());
-
- if (assertion_ != kIOPMNullAssertionID) {
- IOReturn result = IOPMAssertionRelease(assertion_);
- LOG_IF(ERROR, result != kIOReturnSuccess)
- << "IOPMAssertionRelease: " << result;
- }
-}
-
-PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
- Reason reason,
- const std::string& description)
- : delegate_(new Delegate(type, description)) {
- g_power_thread.Pointer()->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&Delegate::ApplyBlock, delegate_));
-}
-
-PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
- g_power_thread.Pointer()->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, delegate_));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/power_save_blocker_ozone.cc b/chromium/content/browser/power_save_blocker_ozone.cc
deleted file mode 100644
index c3102351774..00000000000
--- a/chromium/content/browser/power_save_blocker_ozone.cc
+++ /dev/null
@@ -1,36 +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_save_blocker_impl.h"
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-
-namespace content {
-
-// TODO(derat): Consider renaming this file; '_ozone' is a misnomer as power
-// save is OS-specific, not display-system-specific. This implementation
-// ends up being used for non-ChromeOS Ozone platforms such as Chromecast.
-// See crbug.com/495661 for more detail.
-class PowerSaveBlockerImpl::Delegate
- : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
- public:
- Delegate() {}
-
- private:
- friend class base::RefCountedThreadSafe<Delegate>;
- virtual ~Delegate() {}
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
-};
-
-PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
- Reason reason,
- const std::string& description)
- : delegate_(new Delegate()) {
-}
-
-PowerSaveBlockerImpl::~PowerSaveBlockerImpl() { }
-
-} // namespace content
diff --git a/chromium/content/browser/power_save_blocker_win.cc b/chromium/content/browser/power_save_blocker_win.cc
deleted file mode 100644
index ff78f1184f7..00000000000
--- a/chromium/content/browser/power_save_blocker_win.cc
+++ /dev/null
@@ -1,153 +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/power_save_blocker_impl.h"
-
-#include <windows.h>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/windows_version.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-namespace {
-
-int g_blocker_count[2];
-
-HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type,
- const std::string& description) {
- if (type == PowerRequestExecutionRequired &&
- base::win::GetVersion() < base::win::VERSION_WIN8) {
- return INVALID_HANDLE_VALUE;
- }
-
- base::string16 wide_description = base::ASCIIToUTF16(description);
- REASON_CONTEXT context = {0};
- context.Version = POWER_REQUEST_CONTEXT_VERSION;
- context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
- context.Reason.SimpleReasonString =
- const_cast<wchar_t*>(wide_description.c_str());
-
- base::win::ScopedHandle handle(::PowerCreateRequest(&context));
- if (!handle.IsValid())
- return INVALID_HANDLE_VALUE;
-
- if (::PowerSetRequest(handle.Get(), type))
- return handle.Take();
-
- // Something went wrong.
- return INVALID_HANDLE_VALUE;
-}
-
-// Takes ownership of the |handle|.
-void DeletePowerRequest(POWER_REQUEST_TYPE type, HANDLE handle) {
- base::win::ScopedHandle request_handle(handle);
- if (!request_handle.IsValid())
- return;
-
- if (type == PowerRequestExecutionRequired &&
- base::win::GetVersion() < base::win::VERSION_WIN8) {
- return;
- }
-
- BOOL success = ::PowerClearRequest(request_handle.Get(), type);
- DCHECK(success);
-}
-
-void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type,
- int delta) {
- g_blocker_count[type] += delta;
- DCHECK_GE(g_blocker_count[type], 0);
-
- if (g_blocker_count[type] > 1)
- return;
-
- DWORD this_flag = 0;
- if (type == PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension)
- this_flag |= ES_SYSTEM_REQUIRED;
- else
- this_flag |= ES_DISPLAY_REQUIRED;
-
- DCHECK(this_flag);
-
- static DWORD flags = ES_CONTINUOUS;
- if (!g_blocker_count[type])
- flags &= ~this_flag;
- else
- flags |= this_flag;
-
- SetThreadExecutionState(flags);
-}
-
-} // namespace
-
-class PowerSaveBlockerImpl::Delegate
- : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
- public:
- Delegate(PowerSaveBlockerType type, const std::string& description)
- : type_(type), description_(description) {}
-
- // Does the actual work to apply or remove the desired power save block.
- void ApplyBlock();
- void RemoveBlock();
-
- // Returns the equivalent POWER_REQUEST_TYPE for this request.
- POWER_REQUEST_TYPE RequestType();
-
- private:
- friend class base::RefCountedThreadSafe<Delegate>;
- ~Delegate() {}
-
- PowerSaveBlockerType type_;
- const std::string description_;
- base::win::ScopedHandle handle_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
-};
-
-void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (base::win::GetVersion() < base::win::VERSION_WIN7)
- return ApplySimpleBlock(type_, 1);
-
- handle_.Set(CreatePowerRequest(RequestType(), description_));
-}
-
-void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (base::win::GetVersion() < base::win::VERSION_WIN7)
- return ApplySimpleBlock(type_, -1);
-
- DeletePowerRequest(RequestType(), handle_.Take());
-}
-
-POWER_REQUEST_TYPE PowerSaveBlockerImpl::Delegate::RequestType() {
- if (type_ == kPowerSaveBlockPreventDisplaySleep)
- return PowerRequestDisplayRequired;
-
- if (base::win::GetVersion() < base::win::VERSION_WIN8)
- return PowerRequestSystemRequired;
-
- return PowerRequestExecutionRequired;
-}
-
-PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
- Reason reason,
- const std::string& description)
- : delegate_(new Delegate(type, description)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&Delegate::ApplyBlock, delegate_));
-}
-
-PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, delegate_));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/power_save_blocker_x11.cc b/chromium/content/browser/power_save_blocker_x11.cc
deleted file mode 100644
index e80265c5a77..00000000000
--- a/chromium/content/browser/power_save_blocker_x11.cc
+++ /dev/null
@@ -1,493 +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 <X11/Xlib.h>
-#include <X11/extensions/dpms.h>
-#include <X11/extensions/scrnsaver.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "content/browser/power_save_blocker_impl.h"
-// Xlib #defines Status, but we can't have that for some of our headers.
-#ifdef Status
-#undef Status
-#endif
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/singleton.h"
-#include "base/nix/xdg_util.h"
-#include "base/synchronization/lock.h"
-#include "content/public/browser/browser_thread.h"
-#include "dbus/bus.h"
-#include "dbus/message.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "ui/gfx/x/x11_types.h"
-
-namespace {
-
-enum DBusAPI {
- NO_API, // Disable. No supported API available.
- GNOME_API, // Use the GNOME API. (Supports more features.)
- FREEDESKTOP_API, // Use the FreeDesktop API, for KDE4, KDE5, and XFCE.
-};
-
-// Inhibit flags defined in the org.gnome.SessionManager interface.
-// Can be OR'd together and passed as argument to the Inhibit() method
-// to specify which power management features we want to suspend.
-enum GnomeAPIInhibitFlags {
- INHIBIT_LOGOUT = 1,
- INHIBIT_SWITCH_USER = 2,
- INHIBIT_SUSPEND_SESSION = 4,
- INHIBIT_MARK_SESSION_IDLE = 8
-};
-
-const char kGnomeAPIServiceName[] = "org.gnome.SessionManager";
-const char kGnomeAPIInterfaceName[] = "org.gnome.SessionManager";
-const char kGnomeAPIObjectPath[] = "/org/gnome/SessionManager";
-
-const char kFreeDesktopAPIPowerServiceName[] =
- "org.freedesktop.PowerManagement";
-const char kFreeDesktopAPIPowerInterfaceName[] =
- "org.freedesktop.PowerManagement.Inhibit";
-const char kFreeDesktopAPIPowerObjectPath[] =
- "/org/freedesktop/PowerManagement/Inhibit";
-
-const char kFreeDesktopAPIScreenServiceName[] = "org.freedesktop.ScreenSaver";
-const char kFreeDesktopAPIScreenInterfaceName[] = "org.freedesktop.ScreenSaver";
-const char kFreeDesktopAPIScreenObjectPath[] = "/org/freedesktop/ScreenSaver";
-
-} // namespace
-
-namespace content {
-
-class PowerSaveBlockerImpl::Delegate
- : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
- public:
- // Picks an appropriate D-Bus API to use based on the desktop environment.
- Delegate(PowerSaveBlockerType type,
- const std::string& description,
- bool freedesktop_only);
-
- // Post a task to initialize the delegate on the UI thread, which will itself
- // then post a task to apply the power save block on the FILE thread.
- void Init();
-
- // Post a task to remove the power save block on the FILE thread, unless it
- // hasn't yet been applied, in which case we just prevent it from applying.
- void CleanUp();
-
- private:
- friend class base::RefCountedThreadSafe<Delegate>;
- ~Delegate() {}
-
- // Selects an appropriate D-Bus API to use for this object. Must be called on
- // the UI thread. Checks enqueue_apply_ once an API has been selected, and
- // enqueues a call back to ApplyBlock() if it is true. See the comments for
- // enqueue_apply_ below.
- void InitOnUIThread();
-
- // Returns true if ApplyBlock() / RemoveBlock() should be called.
- bool ShouldBlock() const;
-
- // Apply or remove the power save block, respectively. These methods should be
- // called once each, on the same thread, per instance. They block waiting for
- // the action to complete (with a timeout); the thread must thus allow I/O.
- void ApplyBlock();
- void RemoveBlock();
-
- // Asynchronous callback functions for ApplyBlock and RemoveBlock.
- // Functions do not receive ownership of |response|.
- void ApplyBlockFinished(dbus::Response* response);
- void RemoveBlockFinished(dbus::Response* response);
-
- // Wrapper for XScreenSaverSuspend. Checks whether the X11 Screen Saver
- // Extension is available first. If it isn't, this is a no-op.
- // Must be called on the UI thread.
- static void XSSSuspendSet(bool suspend);
-
- // If DPMS (the power saving system in X11) is not enabled, then we don't want
- // to try to disable power saving, since on some desktop environments that may
- // enable DPMS with very poor default settings (e.g. turning off the display
- // after only 1 second). Must be called on the UI thread.
- static bool DPMSEnabled();
-
- // If no other method is available (i.e. not running under a Desktop
- // Environment) check whether the X11 Screen Saver Extension can be used
- // to disable the screen saver. Must be called on the UI thread.
- static bool XSSAvailable();
-
- // Returns an appropriate D-Bus API to use based on the desktop environment.
- // Must be called on the UI thread, as it may call DPMSEnabled() above.
- static DBusAPI SelectAPI();
-
- const PowerSaveBlockerType type_;
- const std::string description_;
- const bool freedesktop_only_;
-
- // Initially, we post a message to the UI thread to select an API. When it
- // finishes, it will post a message to the FILE thread to perform the actual
- // application of the block, unless enqueue_apply_ is false. We set it to
- // false when we post that message, or when RemoveBlock() is called before
- // ApplyBlock() has run. Both api_ and enqueue_apply_ are guarded by lock_.
- DBusAPI api_;
- bool enqueue_apply_;
- base::Lock lock_;
-
- // Indicates that a D-Bus power save blocking request is in flight.
- bool block_inflight_;
- // Used to detect erronous redundant calls to RemoveBlock().
- bool unblock_inflight_;
- // Indicates that RemoveBlock() is called before ApplyBlock() has finished.
- // If it's true, then the RemoveBlock() call will be processed immediately
- // after ApplyBlock() has finished.
- bool enqueue_unblock_;
-
- scoped_refptr<dbus::Bus> bus_;
-
- // The cookie that identifies our inhibit request,
- // or 0 if there is no active inhibit request.
- uint32_t inhibit_cookie_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
-};
-
-PowerSaveBlockerImpl::Delegate::Delegate(PowerSaveBlockerType type,
- const std::string& description,
- bool freedesktop_only)
- : type_(type),
- description_(description),
- freedesktop_only_(freedesktop_only),
- api_(NO_API),
- enqueue_apply_(false),
- inhibit_cookie_(0) {
- // We're on the client's thread here, so we don't allocate the dbus::Bus
- // object yet. We'll do it later in ApplyBlock(), on the FILE thread.
-}
-
-void PowerSaveBlockerImpl::Delegate::Init() {
- base::AutoLock lock(lock_);
- DCHECK(!enqueue_apply_);
- enqueue_apply_ = true;
- block_inflight_ = false;
- unblock_inflight_ = false;
- enqueue_unblock_ = false;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&Delegate::InitOnUIThread, this));
-}
-
-void PowerSaveBlockerImpl::Delegate::CleanUp() {
- base::AutoLock lock(lock_);
- if (enqueue_apply_) {
- // If a call to ApplyBlock() has not yet been enqueued because we are still
- // initializing on the UI thread, then just cancel it. We don't need to
- // remove the block because we haven't even applied it yet.
- enqueue_apply_ = false;
- } else {
- if (ShouldBlock()) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, this));
- }
-
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&Delegate::XSSSuspendSet, false));
- }
-}
-
-void PowerSaveBlockerImpl::Delegate::InitOnUIThread() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::AutoLock lock(lock_);
- api_ = SelectAPI();
-
- if (enqueue_apply_) {
- if (ShouldBlock()) {
- // The thread we use here becomes the origin and D-Bus thread for the
- // D-Bus library, so we need to use the same thread above for
- // RemoveBlock(). It must be a thread that allows I/O operations, so we
- // use the FILE thread.
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&Delegate::ApplyBlock, this));
- }
- XSSSuspendSet(true);
- }
- enqueue_apply_ = false;
-}
-
-bool PowerSaveBlockerImpl::Delegate::ShouldBlock() const {
- return freedesktop_only_ ? api_ == FREEDESKTOP_API : api_ != NO_API;
-}
-
-void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- DCHECK(!bus_); // ApplyBlock() should only be called once.
- DCHECK(!block_inflight_);
-
- dbus::Bus::Options options;
- options.bus_type = dbus::Bus::SESSION;
- options.connection_type = dbus::Bus::PRIVATE;
- bus_ = new dbus::Bus(options);
-
- scoped_refptr<dbus::ObjectProxy> object_proxy;
- std::unique_ptr<dbus::MethodCall> method_call;
- std::unique_ptr<dbus::MessageWriter> message_writer;
-
- switch (api_) {
- case NO_API:
- NOTREACHED(); // We should never call this method with this value.
- return;
- case GNOME_API:
- object_proxy = bus_->GetObjectProxy(
- kGnomeAPIServiceName,
- dbus::ObjectPath(kGnomeAPIObjectPath));
- method_call.reset(
- new dbus::MethodCall(kGnomeAPIInterfaceName, "Inhibit"));
- message_writer.reset(new dbus::MessageWriter(method_call.get()));
- // The arguments of the method are:
- // app_id: The application identifier
- // toplevel_xid: The toplevel X window identifier
- // reason: The reason for the inhibit
- // flags: Flags that spefify what should be inhibited
- message_writer->AppendString(
- base::CommandLine::ForCurrentProcess()->GetProgram().value());
- message_writer->AppendUint32(0); // should be toplevel_xid
- message_writer->AppendString(description_);
- {
- uint32_t flags = 0;
- switch (type_) {
- case kPowerSaveBlockPreventDisplaySleep:
- flags |= INHIBIT_MARK_SESSION_IDLE;
- flags |= INHIBIT_SUSPEND_SESSION;
- break;
- case kPowerSaveBlockPreventAppSuspension:
- flags |= INHIBIT_SUSPEND_SESSION;
- break;
- }
- message_writer->AppendUint32(flags);
- }
- break;
- case FREEDESKTOP_API:
- switch (type_) {
- case kPowerSaveBlockPreventDisplaySleep:
- object_proxy = bus_->GetObjectProxy(
- kFreeDesktopAPIScreenServiceName,
- dbus::ObjectPath(kFreeDesktopAPIScreenObjectPath));
- method_call.reset(new dbus::MethodCall(
- kFreeDesktopAPIScreenInterfaceName, "Inhibit"));
- break;
- case kPowerSaveBlockPreventAppSuspension:
- object_proxy = bus_->GetObjectProxy(
- kFreeDesktopAPIPowerServiceName,
- dbus::ObjectPath(kFreeDesktopAPIPowerObjectPath));
- method_call.reset(new dbus::MethodCall(
- kFreeDesktopAPIPowerInterfaceName, "Inhibit"));
- break;
- }
- message_writer.reset(new dbus::MessageWriter(method_call.get()));
- // The arguments of the method are:
- // app_id: The application identifier
- // reason: The reason for the inhibit
- message_writer->AppendString(
- base::CommandLine::ForCurrentProcess()->GetProgram().value());
- message_writer->AppendString(description_);
- break;
- }
-
- block_inflight_ = true;
- object_proxy->CallMethod(
- method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::Bind(&PowerSaveBlockerImpl::Delegate::ApplyBlockFinished, this));
-}
-
-void PowerSaveBlockerImpl::Delegate::ApplyBlockFinished(
- dbus::Response* response) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- DCHECK(bus_);
- DCHECK(block_inflight_);
- block_inflight_ = false;
-
- if (response) {
- // The method returns an inhibit_cookie, used to uniquely identify
- // this request. It should be used as an argument to Uninhibit()
- // in order to remove the request.
- dbus::MessageReader message_reader(response);
- if (!message_reader.PopUint32(&inhibit_cookie_))
- LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString();
- } else {
- LOG(ERROR) << "No response to Inhibit() request!";
- }
-
- if (enqueue_unblock_) {
- enqueue_unblock_ = false;
- // RemoveBlock() was called while the Inhibit operation was in flight,
- // so go ahead and remove the block now.
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, this));
- }
-}
-
-void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- DCHECK(bus_); // RemoveBlock() should only be called once.
- DCHECK(!unblock_inflight_);
-
- if (block_inflight_) {
- DCHECK(!enqueue_unblock_);
- // Can't call RemoveBlock until ApplyBlock's async operation has
- // finished. Enqueue it for execution once ApplyBlock is done.
- enqueue_unblock_ = true;
- return;
- }
-
- scoped_refptr<dbus::ObjectProxy> object_proxy;
- std::unique_ptr<dbus::MethodCall> method_call;
-
- switch (api_) {
- case NO_API:
- NOTREACHED(); // We should never call this method with this value.
- return;
- case GNOME_API:
- object_proxy = bus_->GetObjectProxy(
- kGnomeAPIServiceName,
- dbus::ObjectPath(kGnomeAPIObjectPath));
- method_call.reset(
- new dbus::MethodCall(kGnomeAPIInterfaceName, "Uninhibit"));
- break;
- case FREEDESKTOP_API:
- switch (type_) {
- case kPowerSaveBlockPreventDisplaySleep:
- object_proxy = bus_->GetObjectProxy(
- kFreeDesktopAPIScreenServiceName,
- dbus::ObjectPath(kFreeDesktopAPIScreenObjectPath));
- method_call.reset(new dbus::MethodCall(
- kFreeDesktopAPIScreenInterfaceName, "UnInhibit"));
- break;
- case kPowerSaveBlockPreventAppSuspension:
- object_proxy = bus_->GetObjectProxy(
- kFreeDesktopAPIPowerServiceName,
- dbus::ObjectPath(kFreeDesktopAPIPowerObjectPath));
- method_call.reset(new dbus::MethodCall(
- kFreeDesktopAPIPowerInterfaceName, "UnInhibit"));
- break;
- }
- break;
- }
-
- dbus::MessageWriter message_writer(method_call.get());
- message_writer.AppendUint32(inhibit_cookie_);
- unblock_inflight_ = true;
- object_proxy->CallMethod(
- method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::Bind(&PowerSaveBlockerImpl::Delegate::RemoveBlockFinished, this));
-}
-
-void PowerSaveBlockerImpl::Delegate::RemoveBlockFinished(
- dbus::Response* response) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- DCHECK(bus_);
- unblock_inflight_ = false;
-
- if (!response)
- LOG(ERROR) << "No response to Uninhibit() request!";
- // We don't care about checking the result. We assume it works; we can't
- // really do anything about it anyway if it fails.
- inhibit_cookie_ = 0;
-
- bus_->ShutdownAndBlock();
- bus_ = nullptr;
-}
-
-// static
-void PowerSaveBlockerImpl::Delegate::XSSSuspendSet(bool suspend) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- if (!XSSAvailable())
- return;
-
- XDisplay* display = gfx::GetXDisplay();
- XScreenSaverSuspend(display, suspend);
-}
-
-// static
-bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- XDisplay* display = gfx::GetXDisplay();
- BOOL enabled = false;
- int dummy;
- if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) {
- CARD16 state;
- DPMSInfo(display, &state, &enabled);
- }
- return enabled;
-}
-
-// static
-bool PowerSaveBlockerImpl::Delegate::XSSAvailable() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- XDisplay* display = gfx::GetXDisplay();
- int dummy;
- int major;
- int minor;
-
- if (!XScreenSaverQueryExtension(display, &dummy, &dummy))
- return false;
-
- if (!XScreenSaverQueryVersion(display, &major, &minor))
- return false;
-
- return major > 1 || (major == 1 && minor >= 1);
-}
-
-// static
-DBusAPI PowerSaveBlockerImpl::Delegate::SelectAPI() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- std::unique_ptr<base::Environment> env(base::Environment::Create());
- switch (base::nix::GetDesktopEnvironment(env.get())) {
- case base::nix::DESKTOP_ENVIRONMENT_GNOME:
- case base::nix::DESKTOP_ENVIRONMENT_UNITY:
- if (DPMSEnabled())
- return GNOME_API;
- break;
- case base::nix::DESKTOP_ENVIRONMENT_XFCE:
- case base::nix::DESKTOP_ENVIRONMENT_KDE4:
- case base::nix::DESKTOP_ENVIRONMENT_KDE5:
- if (DPMSEnabled())
- return FREEDESKTOP_API;
- break;
- case base::nix::DESKTOP_ENVIRONMENT_KDE3:
- case base::nix::DESKTOP_ENVIRONMENT_OTHER:
- // Not supported.
- break;
- }
- return NO_API;
-}
-
-PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
- Reason reason,
- const std::string& description)
- : delegate_(new Delegate(type, description, false /* freedesktop_only */)) {
- delegate_->Init();
-
- if (type == kPowerSaveBlockPreventDisplaySleep) {
- freedesktop_suspend_delegate_ =
- new Delegate(kPowerSaveBlockPreventAppSuspension, description,
- true /* freedesktop_only */);
- freedesktop_suspend_delegate_->Init();
- }
-}
-
-PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
- delegate_->CleanUp();
- if (freedesktop_suspend_delegate_)
- freedesktop_suspend_delegate_->CleanUp();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index e177330fd10..19d434485e9 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -26,11 +26,13 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/mojo_channel_switches.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/process_type.h"
#include "content/public/common/sandbox_type.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "ipc/ipc_switches.h"
+#include "mojo/edk/embedder/embedder.h"
#include "net/base/network_change_notifier.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ui/base/ui_base_switches.h"
@@ -60,14 +62,16 @@ class PpapiPluginSandboxedProcessLauncherDelegate
PpapiPluginSandboxedProcessLauncherDelegate(bool is_broker,
const PepperPluginInfo& info,
ChildProcessHost* host)
- :
#if defined(OS_WIN)
- info_(info),
-#endif // OS_WIN
-#if defined(OS_POSIX)
- ipc_fd_(host->TakeClientFileDescriptor()),
-#endif // OS_POSIX
- is_broker_(is_broker) {}
+ : 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
+ {
+#endif
+ }
~PpapiPluginSandboxedProcessLauncherDelegate() override {}
@@ -140,7 +144,10 @@ class PpapiPluginSandboxedProcessLauncherDelegate
#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_;
+#endif
DISALLOW_COPY_AND_ASSIGN(PpapiPluginSandboxedProcessLauncherDelegate);
};
@@ -311,7 +318,8 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
const PepperPluginInfo& info,
const base::FilePath& profile_data_directory)
: profile_data_directory_(profile_data_directory),
- is_broker_(false) {
+ is_broker_(false),
+ mojo_child_token_(mojo::edk::GenerateRandomToken()) {
uint32_t base_permissions = info.permissions;
// We don't have to do any whitelisting for APIs in this process host, so
@@ -322,7 +330,7 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
permissions_ = ppapi::PpapiPermissions::GetForCommandLine(base_permissions);
process_.reset(new BrowserChildProcessHostImpl(
- PROCESS_TYPE_PPAPI_PLUGIN, this));
+ PROCESS_TYPE_PPAPI_PLUGIN, this, mojo_child_token_));
host_impl_.reset(new BrowserPpapiHostImpl(this, permissions_, info.name,
info.path, profile_data_directory,
@@ -344,9 +352,10 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
}
PpapiPluginProcessHost::PpapiPluginProcessHost()
- : is_broker_(true) {
+ : is_broker_(true),
+ mojo_child_token_(mojo::edk::GenerateRandomToken()) {
process_.reset(new BrowserChildProcessHostImpl(
- PROCESS_TYPE_PPAPI_BROKER, this));
+ PROCESS_TYPE_PPAPI_BROKER, this, mojo_child_token_));
ppapi::PpapiPermissions permissions; // No permissions.
// The plugin name, path and profile data directory shouldn't be needed for
@@ -366,8 +375,9 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
process_->SetName(base::UTF8ToUTF16(info.name));
}
- std::string channel_id = process_->GetHost()->CreateChannel();
- if (channel_id.empty()) {
+ std::string mojo_channel_token =
+ process_->GetHost()->CreateChannelMojo(mojo_child_token_);
+ if (mojo_channel_token.empty()) {
VLOG(1) << "Could not create pepper host channel.";
return false;
}
@@ -393,13 +403,11 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
cmd_line->AppendSwitchASCII(switches::kProcessType,
is_broker_ ? switches::kPpapiBrokerProcess
: switches::kPpapiPluginProcess);
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
+ cmd_line->AppendSwitchASCII(switches::kMojoChannelToken, mojo_channel_token);
#if defined(OS_WIN)
- if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument()) {
- cmd_line->AppendArg(is_broker_ ? switches::kPrefetchArgumentPpapiBroker
- : switches::kPrefetchArgumentPpapi);
- }
+ cmd_line->AppendArg(is_broker_ ? switches::kPrefetchArgumentPpapiBroker
+ : switches::kPrefetchArgumentPpapi);
#endif // defined(OS_WIN)
// These switches are forwarded to both plugin and broker pocesses.
diff --git a/chromium/content/browser/ppapi_plugin_process_host.h b/chromium/content/browser/ppapi_plugin_process_host.h
index 46401e8817f..90c9b09bfd6 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.h
+++ b/chromium/content/browser/ppapi_plugin_process_host.h
@@ -177,6 +177,9 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate,
const bool is_broker_;
+ // A random token used to identify the child process to Mojo.
+ const std::string mojo_child_token_;
+
std::unique_ptr<BrowserChildProcessHostImpl> process_;
DISALLOW_COPY_AND_ASSIGN(PpapiPluginProcessHost);
diff --git a/chromium/content/browser/presentation/presentation_service_impl.cc b/chromium/content/browser/presentation/presentation_service_impl.cc
index a9a73dd0304..17ec835b5f3 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl.cc
@@ -112,8 +112,8 @@ std::unique_ptr<PresentationSessionMessage> GetPresentationSessionMessage(
return output;
}
-void InvokeNewSessionMojoCallbackWithError(
- const NewSessionMojoCallback& callback) {
+void InvokeNewSessionCallbackWithError(
+ const PresentationServiceImpl::NewSessionCallback& callback) {
callback.Run(blink::mojom::PresentationSessionInfoPtr(),
blink::mojom::PresentationError::From(PresentationError(
PRESENTATION_ERROR_UNKNOWN, "Internal error")));
@@ -218,9 +218,8 @@ void PresentationServiceImpl::StopListeningForScreenAvailability(
screen_availability_listeners_.erase(listener_it);
}
-void PresentationServiceImpl::StartSession(
- const mojo::String& presentation_url,
- const NewSessionMojoCallback& callback) {
+void PresentationServiceImpl::StartSession(const mojo::String& presentation_url,
+ const NewSessionCallback& callback) {
DVLOG(2) << "StartSession";
if (!delegate_) {
callback.Run(
@@ -233,12 +232,12 @@ void PresentationServiceImpl::StartSession(
// There is a StartSession request in progress. To avoid queueing up
// requests, the incoming request is rejected.
if (start_session_request_id_ != kInvalidRequestSessionId) {
- InvokeNewSessionMojoCallbackWithError(callback);
+ InvokeNewSessionCallbackWithError(callback);
return;
}
start_session_request_id_ = GetNextRequestSessionId();
- pending_start_session_cb_.reset(new NewSessionMojoCallbackWrapper(callback));
+ pending_start_session_cb_.reset(new NewSessionCallbackWrapper(callback));
delegate_->StartSession(
render_process_id_, render_frame_id_, presentation_url,
base::Bind(&PresentationServiceImpl::OnStartSessionSucceeded,
@@ -250,7 +249,7 @@ void PresentationServiceImpl::StartSession(
void PresentationServiceImpl::JoinSession(
const mojo::String& presentation_url,
const mojo::String& presentation_id,
- const NewSessionMojoCallback& callback) {
+ const NewSessionCallback& callback) {
DVLOG(2) << "JoinSession";
if (!delegate_) {
callback.Run(blink::mojom::PresentationSessionInfoPtr(),
@@ -262,7 +261,7 @@ void PresentationServiceImpl::JoinSession(
int request_session_id = RegisterJoinSessionCallback(callback);
if (request_session_id == kInvalidRequestSessionId) {
- InvokeNewSessionMojoCallbackWithError(callback);
+ InvokeNewSessionCallbackWithError(callback);
return;
}
delegate_->JoinSession(
@@ -277,13 +276,13 @@ void PresentationServiceImpl::JoinSession(
}
int PresentationServiceImpl::RegisterJoinSessionCallback(
- const NewSessionMojoCallback& callback) {
+ const NewSessionCallback& callback) {
if (pending_join_session_cbs_.size() >= kMaxNumQueuedSessionRequests)
return kInvalidRequestSessionId;
int request_id = GetNextRequestSessionId();
pending_join_session_cbs_[request_id].reset(
- new NewSessionMojoCallbackWrapper(callback));
+ new NewSessionCallbackWrapper(callback));
return request_id;
}
@@ -378,7 +377,7 @@ void PresentationServiceImpl::SetDefaultPresentationURL(
void PresentationServiceImpl::SendSessionMessage(
blink::mojom::PresentationSessionInfoPtr session,
blink::mojom::SessionMessagePtr session_message,
- const SendMessageMojoCallback& callback) {
+ const SendSessionMessageCallback& callback) {
DVLOG(2) << "SendSessionMessage";
DCHECK(!session_message.is_null());
// send_message_callback_ should be null by now, otherwise resetting of
@@ -388,7 +387,7 @@ void PresentationServiceImpl::SendSessionMessage(
return;
}
- send_message_callback_.reset(new SendMessageMojoCallback(callback));
+ send_message_callback_.reset(new SendSessionMessageCallback(callback));
delegate_->SendMessage(
render_process_id_, render_frame_id_,
session.To<PresentationSessionInfo>(),
@@ -590,23 +589,23 @@ void PresentationServiceImpl::ScreenAvailabilityListenerImpl
service_->client_->OnScreenAvailabilityNotSupported(availability_url_);
}
-PresentationServiceImpl::NewSessionMojoCallbackWrapper
-::NewSessionMojoCallbackWrapper(const NewSessionMojoCallback& callback)
+PresentationServiceImpl::NewSessionCallbackWrapper
+::NewSessionCallbackWrapper(const NewSessionCallback& callback)
: callback_(callback) {
}
-PresentationServiceImpl::NewSessionMojoCallbackWrapper
-::~NewSessionMojoCallbackWrapper() {
+PresentationServiceImpl::NewSessionCallbackWrapper
+::~NewSessionCallbackWrapper() {
if (!callback_.is_null())
- InvokeNewSessionMojoCallbackWithError(callback_);
+ InvokeNewSessionCallbackWithError(callback_);
}
-void PresentationServiceImpl::NewSessionMojoCallbackWrapper::Run(
+void PresentationServiceImpl::NewSessionCallbackWrapper::Run(
blink::mojom::PresentationSessionInfoPtr session,
blink::mojom::PresentationErrorPtr error) {
DCHECK(!callback_.is_null());
callback_.Run(std::move(session), std::move(error));
- callback_.reset();
+ callback_.Reset();
}
} // namespace content
diff --git a/chromium/content/browser/presentation/presentation_service_impl.h b/chromium/content/browser/presentation/presentation_service_impl.h
index 44fb0e10fa3..2bdc3e9029b 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.h
+++ b/chromium/content/browser/presentation/presentation_service_impl.h
@@ -10,6 +10,7 @@
#include <memory>
#include <string>
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/gtest_prod_util.h"
@@ -33,10 +34,6 @@ struct LoadCommittedDetails;
struct PresentationSessionMessage;
class RenderFrameHost;
-using NewSessionMojoCallback =
- mojo::Callback<void(blink::mojom::PresentationSessionInfoPtr,
- blink::mojom::PresentationErrorPtr)>;
-
// Implementation of Mojo PresentationService.
// It handles Presentation API requests coming from Blink / renderer process
// and delegates the requests to the embedder's media router via
@@ -50,6 +47,10 @@ class CONTENT_EXPORT PresentationServiceImpl
public WebContentsObserver,
public PresentationServiceDelegate::Observer {
public:
+ using NewSessionCallback =
+ base::Callback<void(blink::mojom::PresentationSessionInfoPtr,
+ blink::mojom::PresentationErrorPtr)>;
+
~PresentationServiceImpl() override;
// Static factory method to create an instance of PresentationServiceImpl.
@@ -95,11 +96,9 @@ class CONTENT_EXPORT PresentationServiceImpl
// Maximum number of pending JoinSession requests at any given time.
static const int kMaxNumQueuedSessionRequests = 10;
- using PresentationSessionMojoCallback =
- mojo::Callback<void(blink::mojom::PresentationSessionInfoPtr)>;
using SessionMessagesCallback =
- mojo::Callback<void(mojo::Array<blink::mojom::SessionMessagePtr>)>;
- using SendMessageMojoCallback = mojo::Callback<void(bool)>;
+ base::Callback<void(mojo::Array<blink::mojom::SessionMessagePtr>)>;
+ using SendSessionMessageCallback = base::Callback<void(bool)>;
// Listener implementation owned by PresentationServiceImpl. An instance of
// this is created when PresentationRequest.getAvailability() is resolved.
@@ -123,21 +122,21 @@ class CONTENT_EXPORT PresentationServiceImpl
PresentationServiceImpl* const service_;
};
- // Ensures the provided NewSessionMojoCallback is invoked exactly once
+ // Ensures the provided NewSessionCallback is invoked exactly once
// before it goes out of scope.
- class NewSessionMojoCallbackWrapper {
+ class NewSessionCallbackWrapper {
public:
- explicit NewSessionMojoCallbackWrapper(
- const NewSessionMojoCallback& callback);
- ~NewSessionMojoCallbackWrapper();
+ explicit NewSessionCallbackWrapper(
+ const NewSessionCallback& callback);
+ ~NewSessionCallbackWrapper();
void Run(blink::mojom::PresentationSessionInfoPtr session,
blink::mojom::PresentationErrorPtr error);
private:
- NewSessionMojoCallback callback_;
+ NewSessionCallback callback_;
- DISALLOW_COPY_AND_ASSIGN(NewSessionMojoCallbackWrapper);
+ DISALLOW_COPY_AND_ASSIGN(NewSessionCallbackWrapper);
};
// |render_frame_host|: The RFH this instance is associated with.
@@ -156,14 +155,14 @@ class CONTENT_EXPORT PresentationServiceImpl
void StopListeningForScreenAvailability(const mojo::String& url) override;
void StartSession(
const mojo::String& presentation_url,
- const NewSessionMojoCallback& callback) override;
+ const NewSessionCallback& callback) override;
void JoinSession(
const mojo::String& presentation_url,
const mojo::String& presentation_id,
- const NewSessionMojoCallback& callback) override;
+ const NewSessionCallback& callback) override;
void SendSessionMessage(blink::mojom::PresentationSessionInfoPtr session_info,
blink::mojom::SessionMessagePtr session_message,
- const SendMessageMojoCallback& callback) override;
+ const SendSessionMessageCallback& callback) override;
void CloseConnection(const mojo::String& presentation_url,
const mojo::String& presentation_id) override;
void Terminate(const mojo::String& presentation_url,
@@ -236,7 +235,7 @@ class CONTENT_EXPORT PresentationServiceImpl
// Associates a JoinSession |callback| with a unique request ID and
// stores it in a map.
// Returns a positive value on success.
- int RegisterJoinSessionCallback(const NewSessionMojoCallback& callback);
+ int RegisterJoinSessionCallback(const NewSessionCallback& callback);
// Invoked by the embedder's PresentationServiceDelegate when a
// PresentationConnection's state has changed.
@@ -264,10 +263,10 @@ class CONTENT_EXPORT PresentationServiceImpl
// For StartSession requests.
// Set to a positive value when a StartSession request is being processed.
int start_session_request_id_;
- std::unique_ptr<NewSessionMojoCallbackWrapper> pending_start_session_cb_;
+ std::unique_ptr<NewSessionCallbackWrapper> pending_start_session_cb_;
// For JoinSession requests.
- base::hash_map<int, linked_ptr<NewSessionMojoCallbackWrapper>>
+ base::hash_map<int, linked_ptr<NewSessionCallbackWrapper>>
pending_join_session_cbs_;
// RAII binding of |this| to an Presentation interface request.
@@ -275,7 +274,7 @@ class CONTENT_EXPORT PresentationServiceImpl
std::unique_ptr<mojo::Binding<blink::mojom::PresentationService>> binding_;
// There can be only one send message request at a time.
- std::unique_ptr<SendMessageMojoCallback> send_message_callback_;
+ std::unique_ptr<SendSessionMessageCallback> send_message_callback_;
std::unique_ptr<SessionMessagesCallback> on_session_messages_callback_;
diff --git a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
index 31e3d6456cd..f6dbd5d0e92 100644
--- a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -280,7 +280,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
EXPECT_FALSE(service_impl_->on_session_messages_callback_.get());
}
- void ExpectNewSessionMojoCallbackSuccess(
+ void ExpectNewSessionCallbackSuccess(
blink::mojom::PresentationSessionInfoPtr info,
blink::mojom::PresentationErrorPtr error) {
EXPECT_FALSE(info.is_null());
@@ -289,7 +289,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
run_loop_quit_closure_.Run();
}
- void ExpectNewSessionMojoCallbackError(
+ void ExpectNewSessionCallbackError(
blink::mojom::PresentationSessionInfoPtr info,
blink::mojom::PresentationErrorPtr error) {
EXPECT_TRUE(info.is_null());
@@ -308,7 +308,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
}
}
- void ExpectSendMessageMojoCallback(bool success) {
+ void ExpectSendSessionMessageCallback(bool success) {
EXPECT_TRUE(success);
EXPECT_FALSE(service_impl_->send_message_callback_);
if (!run_loop_quit_closure_.is_null())
@@ -545,7 +545,7 @@ TEST_F(PresentationServiceImplTest, StartSessionSuccess) {
service_ptr_->StartSession(
kPresentationUrl,
base::Bind(
- &PresentationServiceImplTest::ExpectNewSessionMojoCallbackSuccess,
+ &PresentationServiceImplTest::ExpectNewSessionCallbackSuccess,
base::Unretained(this)));
base::RunLoop run_loop;
base::Callback<void(const PresentationSessionInfo&)> success_cb;
@@ -565,7 +565,7 @@ TEST_F(PresentationServiceImplTest, StartSessionError) {
service_ptr_->StartSession(
kPresentationUrl,
base::Bind(
- &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError,
+ &PresentationServiceImplTest::ExpectNewSessionCallbackError,
base::Unretained(this)));
base::RunLoop run_loop;
base::Callback<void(const PresentationError&)> error_cb;
@@ -583,7 +583,7 @@ TEST_F(PresentationServiceImplTest, JoinSessionSuccess) {
kPresentationUrl,
kPresentationId,
base::Bind(
- &PresentationServiceImplTest::ExpectNewSessionMojoCallbackSuccess,
+ &PresentationServiceImplTest::ExpectNewSessionCallbackSuccess,
base::Unretained(this)));
base::RunLoop run_loop;
base::Callback<void(const PresentationSessionInfo&)> success_cb;
@@ -605,7 +605,7 @@ TEST_F(PresentationServiceImplTest, JoinSessionError) {
kPresentationUrl,
kPresentationId,
base::Bind(
- &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError,
+ &PresentationServiceImplTest::ExpectNewSessionCallbackError,
base::Unretained(this)));
base::RunLoop run_loop;
base::Callback<void(const PresentationError&)> error_cb;
@@ -666,7 +666,7 @@ TEST_F(PresentationServiceImplTest, StartSessionInProgress) {
service_ptr_->StartSession(
presentation_url2,
base::Bind(
- &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError,
+ &PresentationServiceImplTest::ExpectNewSessionCallbackError,
base::Unretained(this)));
SaveQuitClosureAndRunLoop();
}
@@ -684,7 +684,7 @@ TEST_F(PresentationServiceImplTest, SendStringMessage) {
message_request->message = message;
service_ptr_->SendSessionMessage(
std::move(session), std::move(message_request),
- base::Bind(&PresentationServiceImplTest::ExpectSendMessageMojoCallback,
+ base::Bind(&PresentationServiceImplTest::ExpectSendSessionMessageCallback,
base::Unretained(this)));
base::RunLoop run_loop;
@@ -722,7 +722,7 @@ TEST_F(PresentationServiceImplTest, SendArrayBuffer) {
message_request->data = mojo::Array<uint8_t>::From(data);
service_ptr_->SendSessionMessage(
std::move(session), std::move(message_request),
- base::Bind(&PresentationServiceImplTest::ExpectSendMessageMojoCallback,
+ base::Bind(&PresentationServiceImplTest::ExpectSendSessionMessageCallback,
base::Unretained(this)));
base::RunLoop run_loop;
@@ -766,7 +766,7 @@ TEST_F(PresentationServiceImplTest, SendArrayBufferWithExceedingLimit) {
message_request->data = mojo::Array<uint8_t>::From(data);
service_ptr_->SendSessionMessage(
std::move(session), std::move(message_request),
- base::Bind(&PresentationServiceImplTest::ExpectSendMessageMojoCallback,
+ base::Bind(&PresentationServiceImplTest::ExpectSendSessionMessageCallback,
base::Unretained(this)));
base::RunLoop run_loop;
@@ -797,7 +797,7 @@ TEST_F(PresentationServiceImplTest, SendBlobData) {
message_request->data = mojo::Array<uint8_t>::From(data);
service_ptr_->SendSessionMessage(
std::move(session), std::move(message_request),
- base::Bind(&PresentationServiceImplTest::ExpectSendMessageMojoCallback,
+ base::Bind(&PresentationServiceImplTest::ExpectSendSessionMessageCallback,
base::Unretained(this)));
base::RunLoop run_loop;
@@ -841,7 +841,7 @@ TEST_F(PresentationServiceImplTest, MaxPendingJoinSessionRequests) {
base::StringPrintf(presentation_url, i),
base::StringPrintf(presentation_id, i),
base::Bind(
- &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError,
+ &PresentationServiceImplTest::ExpectNewSessionCallbackError,
base::Unretained(this)));
SaveQuitClosureAndRunLoop();
}
diff --git a/chromium/content/browser/quota/quota_database_unittest.cc b/chromium/content/browser/quota/quota_database_unittest.cc
index 0ec69dda73d..a0c7b0e09b9 100644
--- a/chromium/content/browser/quota/quota_database_unittest.cc
+++ b/chromium/content/browser/quota/quota_database_unittest.cc
@@ -19,7 +19,7 @@
#include "sql/connection.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
-#include "sql/test/scoped_error_ignorer.h"
+#include "sql/test/scoped_error_expecter.h"
#include "sql/test/test_helpers.h"
#include "storage/browser/quota/quota_database.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -687,10 +687,12 @@ TEST_F(QuotaDatabaseTest, OpenCorruptedDatabase) {
const base::FilePath kDbFile = data_dir.path().AppendASCII(kDBFileName);
LazyOpen(kDbFile);
ASSERT_TRUE(sql::test::CorruptSizeInHeader(kDbFile));
- sql::ScopedErrorIgnorer ignore_errors;
- ignore_errors.IgnoreError(SQLITE_CORRUPT);
- Reopen(kDbFile);
- EXPECT_TRUE(ignore_errors.CheckIgnoredErrors());
+ {
+ sql::test::ScopedErrorExpecter expecter;
+ expecter.ExpectError(SQLITE_CORRUPT);
+ Reopen(kDbFile);
+ EXPECT_TRUE(expecter.SawExpectedErrors());
+ }
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index fd111519666..0df03fb8bc8 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -22,6 +22,7 @@ specific_include_rules = {
"+content/public/browser/web_contents_view.h",
],
"render_process_host_impl\.cc": [
+ "+components/mus/common/switches.h",
"+content/browser/frame_host/render_frame_message_filter.h",
],
"render_widget_host_view_mac\.mm": [
diff --git a/chromium/content/browser/renderer_host/OWNERS b/chromium/content/browser/renderer_host/OWNERS
index b3ee6fca8b9..b0f3c3f5d4e 100644
--- a/chromium/content/browser/renderer_host/OWNERS
+++ b/chromium/content/browser/renderer_host/OWNERS
@@ -30,3 +30,11 @@ per-file render_sandbox_host_linux.*=jln@chromium.org
per-file render_sandbox_host_linux.*=jorgelo@chromium.org
per-file sandbox_ipc_linux.*=jln@chromium.org
per-file sandbox_ipc_linux.*=jorgelo@chromium.org
+
+# WebSQL
+per-file database_*=jsbell@chromium.org
+per-file database_*=michaeln@chromium.org
+
+# Offscreen Canvas
+per-file offscreen_canvas_surface_impl.*=junov@chromium.org
+per-file offscreen_canvas_surface_impl.*=xlai@chromium.org
diff --git a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
index 5a232f94b13..358adffbf86 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -8,71 +8,191 @@
#include <memory>
#include "base/macros.h"
-#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
+#include "cc/scheduler/begin_frame_source.h"
+#include "content/browser/renderer_host/delegated_frame_host.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
+namespace ui {
+class AcceleratedWidgetMac;
+class AcceleratedWidgetMacNSView;
+}
+
namespace content {
-// A ui::Compositor and a gfx::AcceleratedWidget (and helper) that it draws
-// into. This structure is used to efficiently recycle these structures across
-// tabs (because creating a new ui::Compositor for each tab would be expensive
-// in terms of time and resources).
-class BrowserCompositorMac : public ui::CompositorObserver {
- public:
- virtual ~BrowserCompositorMac();
+class RecyclableCompositorMac;
- // Create a compositor, or recycle a preexisting one.
- static std::unique_ptr<BrowserCompositorMac> Create();
+class BrowserCompositorMacClient {
+ public:
+ virtual NSView* BrowserCompositorMacGetNSView() const = 0;
+ virtual SkColor BrowserCompositorMacGetGutterColor(SkColor color) const = 0;
+ virtual void BrowserCompositorMacSendCompositorSwapAck(
+ int output_surface_id,
+ const cc::CompositorFrameAck& ack) = 0;
+ virtual void BrowserCompositorMacSendReclaimCompositorResources(
+ int output_surface_id,
+ const cc::CompositorFrameAck& ack) = 0;
+ virtual void BrowserCompositorMacOnLostCompositorResources() = 0;
+ virtual void BrowserCompositorMacUpdateVSyncParameters(
+ const base::TimeTicks& timebase,
+ const base::TimeDelta& interval) = 0;
+ virtual void BrowserCompositorMacSendBeginFrame(
+ const cc::BeginFrameArgs& args) = 0;
+};
- // Delete a compositor, or allow it to be recycled.
- static void Recycle(std::unique_ptr<BrowserCompositorMac> compositor);
+// This class owns a DelegatedFrameHost, and will dynamically attach and
+// detach it from a ui::Compositor as needed. The ui::Compositor will be
+// detached from the DelegatedFrameHost when the following conditions are
+// all met:
+// - There are no outstanding copy requests
+// - The RenderWidgetHostImpl providing frames to the DelegatedFrameHost
+// is visible.
+// - The RenderWidgetHostViewMac that is used to display these frames is
+// attached to the NSView hierarchy of an NSWindow.
+class BrowserCompositorMac : public cc::BeginFrameObserver,
+ public DelegatedFrameHostClient {
+ public:
+ BrowserCompositorMac(
+ ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view,
+ BrowserCompositorMacClient* client,
+ bool render_widget_host_is_hidden,
+ bool ns_view_attached_to_window);
+ ~BrowserCompositorMac() override;
+
+ // These will not return nullptr until Destroy is called.
+ DelegatedFrameHost* GetDelegatedFrameHost();
+
+ // This may return nullptr, if this has detached itself from its
+ // ui::Compositor.
+ ui::AcceleratedWidgetMac* GetAcceleratedWidgetMac();
+
+ void SwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame);
+ void SetHasTransparentBackground(bool transparent);
+ void UpdateVSyncParameters(const base::TimeTicks& timebase,
+ const base::TimeDelta& interval);
+ void SetNeedsBeginFrames(bool needs_begin_frames);
+
+ // This is used to ensure that the ui::Compositor be attached to the
+ // DelegatedFrameHost while the RWHImpl is visible.
+ // Note: This should be called before the RWHImpl is made visible and after
+ // it has been hidden, in order to ensure that thumbnailer notifications to
+ // initiate copies occur before the ui::Compositor be detached.
+ void SetRenderWidgetHostIsHidden(bool hidden);
+
+ // This is used to ensure that the ui::Compositor be attached to this
+ // NSView while its contents may be visible on-screen, even if the RWHImpl is
+ // hidden (e.g, because it is occluded by another window).
+ void SetNSViewAttachedToWindow(bool attached);
+
+ // These functions will track the number of outstanding copy requests, and
+ // will not allow the ui::Compositor to be detached until all outstanding
+ // copies have returned.
+ void CopyFromCompositingSurface(const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ const ReadbackRequestCallback& callback,
+ SkColorType preferred_color_type);
+ void CopyFromCompositingSurfaceToVideoFrame(
+ const gfx::Rect& src_subrect,
+ const scoped_refptr<media::VideoFrame>& target,
+ const base::Callback<void(const gfx::Rect&, bool)>& callback);
// Indicate that the recyclable compositor should be destroyed, and no future
// compositors should be recycled.
static void DisableRecyclingForShutdown();
- ui::Compositor* compositor() { return &compositor_; }
- ui::AcceleratedWidgetMac* accelerated_widget_mac() {
- return accelerated_widget_mac_.get();
- }
-
- // Suspend will prevent the compositor from producing new frames. This should
- // be called to avoid creating spurious frames while changing state.
- // Compositors are created as suspended.
- void Suspend();
- void Unsuspend();
-
- private:
- BrowserCompositorMac();
-
- // ui::CompositorObserver implementation:
- void OnCompositingDidCommit(ui::Compositor* compositor) override;
- 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 {}
-
- std::unique_ptr<ui::AcceleratedWidgetMac> accelerated_widget_mac_;
- ui::Compositor compositor_;
- scoped_refptr<ui::CompositorLock> compositor_suspended_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserCompositorMac);
-};
-
-// A class to keep around whenever a BrowserCompositorMac may be created.
-// While at least one instance of this class exists, a spare
-// BrowserCompositorViewCocoa will be kept around to be recycled so that the
-// next BrowserCompositorMac to be created will be be created quickly.
-class BrowserCompositorMacPlaceholder {
- public:
- BrowserCompositorMacPlaceholder();
- ~BrowserCompositorMacPlaceholder();
+ // DelegatedFrameHostClient implementation.
+ ui::Layer* DelegatedFrameHostGetLayer() const override;
+ bool DelegatedFrameHostIsVisible() const override;
+ SkColor DelegatedFrameHostGetGutterColor(SkColor color) const override;
+ gfx::Size DelegatedFrameHostDesiredSizeInDIP() const override;
+ bool DelegatedFrameCanCreateResizeLock() const override;
+ std::unique_ptr<ResizeLock> DelegatedFrameHostCreateResizeLock(
+ bool defer_compositor_lock) override;
+ void DelegatedFrameHostResizeLockWasReleased() override;
+ void DelegatedFrameHostSendCompositorSwapAck(
+ int output_surface_id,
+ const cc::CompositorFrameAck& ack) override;
+ void DelegatedFrameHostSendReclaimCompositorResources(
+ int output_surface_id,
+ const cc::CompositorFrameAck& ack) override;
+ void DelegatedFrameHostOnLostCompositorResources() override;
+ void DelegatedFrameHostUpdateVSyncParameters(
+ const base::TimeTicks& timebase,
+ const base::TimeDelta& interval) override;
+ void SetBeginFrameSource(cc::BeginFrameSource* source) override;
+ bool IsAutoResizeEnabled() const override;
+
+ // cc::BeginFrameObserver implementation.
+ void OnBeginFrame(const cc::BeginFrameArgs& args) override;
+ const cc::BeginFrameArgs& LastUsedBeginFrameArgs() const override;
+ void OnBeginFrameSourcePausedChanged(bool paused) override;
private:
- DISALLOW_COPY_AND_ASSIGN(BrowserCompositorMacPlaceholder);
+ // The state of |delegated_frame_host_| and |recyclable_compositor_| to
+ // manage being visible, hidden, or occluded.
+ enum State {
+ // Effects:
+ // - |recyclable_compositor_| exists and is attached to
+ // |delegated_frame_host_|.
+ // Happens when:
+ // - |render_widet_host_| is in the visible state, or there are
+ // outstanding copy requests.
+ HasAttachedCompositor,
+ // Effects:
+ // - |recyclable_compositor_| exists, but |delegated_frame_host_| is
+ // hidden and detached from it.
+ // Happens when:
+ // - The |render_widget_host_| is hidden, but |cocoa_view_| is still in the
+ // NSWindow hierarchy (e.g, when the window is occluded or offscreen).
+ // - Note: In this state, |recyclable_compositor_| and its CALayers are kept
+ // around so that we will have content to show when we are un-occluded. If
+ // we had a way to keep the CALayers attached to the NSView while
+ // detaching the ui::Compositor, then there would be no need for this
+ HasDetachedCompositor,
+ // Effects:
+ // - |recyclable_compositor_| has been recycled and |delegated_frame_host_|
+ // is hidden and detached from it.
+ // Happens when:
+ // - The |render_widget_host_| hidden or gone, and |cocoa_view_| is not
+ // attached to an NSWindow.
+ // - This happens for backgrounded tabs.
+ HasNoCompositor,
+ };
+ State state_ = HasNoCompositor;
+ void UpdateState();
+ void TransitionToState(State new_state);
+
+ static void CopyCompleted(
+ base::WeakPtr<BrowserCompositorMac> browser_compositor,
+ const ReadbackRequestCallback& callback,
+ const SkBitmap& bitmap,
+ ReadbackResponse response);
+ static void CopyToVideoFrameCompleted(
+ base::WeakPtr<BrowserCompositorMac> browser_compositor,
+ const base::Callback<void(const gfx::Rect&, bool)>& callback,
+ const gfx::Rect& rect,
+ bool result);
+ uint64_t outstanding_copy_count_ = 0;
+
+ bool render_widget_host_is_hidden_ = true;
+ bool ns_view_attached_to_window_ = false;
+
+ BrowserCompositorMacClient* client_ = nullptr;
+ ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view_ = nullptr;
+ std::unique_ptr<RecyclableCompositorMac> recyclable_compositor_;
+
+ std::unique_ptr<DelegatedFrameHost> delegated_frame_host_;
+ std::unique_ptr<ui::Layer> root_layer_;
+
+ bool has_transparent_background_ = false;
+
+ // The begin frame source being observed. Null if none.
+ cc::BeginFrameSource* begin_frame_source_ = nullptr;
+ cc::BeginFrameArgs last_begin_frame_args_;
+ bool needs_begin_frames_ = false;
+
+ base::WeakPtrFactory<BrowserCompositorMac> weak_factory_;
};
} // namespace content
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 6002eca17dc..1a641047dbb 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -11,12 +11,12 @@
#include "base/lazy_instance.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/compositor/image_transport_factory.h"
+#include "content/browser/renderer_host/resize_lock.h"
#include "content/public/browser/context_factory.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
-
-////////////////////////////////////////////////////////////////////////////////
-// BrowserCompositorMac
+#include "ui/base/layout.h"
+#include "ui/gfx/geometry/dip_util.h"
namespace content {
@@ -26,17 +26,68 @@ namespace {
bool g_has_shut_down = false;
// The number of placeholder objects allocated. If this reaches zero, then
-// the BrowserCompositorMac being held on to for recycling,
-// |g_recyclable_browser_compositor|, will be freed.
-uint32_t g_placeholder_count = 0;
+// the RecyclableCompositorMac being held on to for recycling,
+// |g_spare_recyclable_compositor|, will be freed.
+uint32_t g_browser_compositor_count = 0;
-// A spare BrowserCompositorMac kept around for recycling.
-base::LazyInstance<std::unique_ptr<BrowserCompositorMac>>
- g_recyclable_browser_compositor;
+// A spare RecyclableCompositorMac kept around for recycling.
+base::LazyInstance<std::unique_ptr<RecyclableCompositorMac>>
+ g_spare_recyclable_compositor;
} // namespace
-BrowserCompositorMac::BrowserCompositorMac()
+////////////////////////////////////////////////////////////////////////////////
+// RecyclableCompositorMac
+
+// A ui::Compositor and a gfx::AcceleratedWidget (and helper) that it draws
+// into. This structure is used to efficiently recycle these structures across
+// tabs (because creating a new ui::Compositor for each tab would be expensive
+// in terms of time and resources).
+class RecyclableCompositorMac : public ui::CompositorObserver {
+ public:
+ virtual ~RecyclableCompositorMac();
+
+ // Create a compositor, or recycle a preexisting one.
+ static std::unique_ptr<RecyclableCompositorMac> Create();
+
+ // Delete a compositor, or allow it to be recycled.
+ static void Recycle(std::unique_ptr<RecyclableCompositorMac> compositor);
+
+ // Indicate that the recyclable compositor should be destroyed, and no future
+ // compositors should be recycled.
+ static void DisableRecyclingForShutdown();
+
+ ui::Compositor* compositor() { return &compositor_; }
+ ui::AcceleratedWidgetMac* accelerated_widget_mac() {
+ return accelerated_widget_mac_.get();
+ }
+
+ // Suspend will prevent the compositor from producing new frames. This should
+ // be called to avoid creating spurious frames while changing state.
+ // Compositors are created as suspended.
+ void Suspend();
+ void Unsuspend();
+
+ private:
+ RecyclableCompositorMac();
+
+ // ui::CompositorObserver implementation:
+ void OnCompositingDidCommit(ui::Compositor* compositor) override;
+ 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 {}
+
+ std::unique_ptr<ui::AcceleratedWidgetMac> accelerated_widget_mac_;
+ ui::Compositor compositor_;
+ scoped_refptr<ui::CompositorLock> compositor_suspended_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(RecyclableCompositorMac);
+};
+
+RecyclableCompositorMac::RecyclableCompositorMac()
: accelerated_widget_mac_(new ui::AcceleratedWidgetMac()),
compositor_(content::GetContextFactory(),
ui::WindowResizeHelperMac::Get()->task_runner()) {
@@ -47,19 +98,19 @@ BrowserCompositorMac::BrowserCompositorMac()
compositor_.AddObserver(this);
}
-BrowserCompositorMac::~BrowserCompositorMac() {
+RecyclableCompositorMac::~RecyclableCompositorMac() {
compositor_.RemoveObserver(this);
}
-void BrowserCompositorMac::Suspend() {
+void RecyclableCompositorMac::Suspend() {
compositor_suspended_lock_ = compositor_.GetCompositorLock();
}
-void BrowserCompositorMac::Unsuspend() {
+void RecyclableCompositorMac::Unsuspend() {
compositor_suspended_lock_ = nullptr;
}
-void BrowserCompositorMac::OnCompositingDidCommit(
+void RecyclableCompositorMac::OnCompositingDidCommit(
ui::Compositor* compositor_that_did_commit) {
DCHECK_EQ(compositor_that_did_commit, compositor());
content::ImageTransportFactory::GetInstance()
@@ -67,16 +118,16 @@ void BrowserCompositorMac::OnCompositingDidCommit(
}
// static
-std::unique_ptr<BrowserCompositorMac> BrowserCompositorMac::Create() {
+std::unique_ptr<RecyclableCompositorMac> RecyclableCompositorMac::Create() {
DCHECK(ui::WindowResizeHelperMac::Get()->task_runner());
- if (g_recyclable_browser_compositor.Get())
- return std::move(g_recyclable_browser_compositor.Get());
- return std::unique_ptr<BrowserCompositorMac>(new BrowserCompositorMac);
+ if (g_spare_recyclable_compositor.Get())
+ return std::move(g_spare_recyclable_compositor.Get());
+ return std::unique_ptr<RecyclableCompositorMac>(new RecyclableCompositorMac);
}
// static
-void BrowserCompositorMac::Recycle(
- std::unique_ptr<BrowserCompositorMac> compositor) {
+void RecyclableCompositorMac::Recycle(
+ std::unique_ptr<RecyclableCompositorMac> compositor) {
DCHECK(compositor);
content::ImageTransportFactory::GetInstance()
->SetCompositorSuspendedForRecycle(compositor->compositor(), true);
@@ -85,36 +136,335 @@ void BrowserCompositorMac::Recycle(
// shutdown.
CHECK(!g_has_shut_down);
- // Make this BrowserCompositorMac recyclable for future instances.
- g_recyclable_browser_compositor.Get().swap(compositor);
+ // Make this RecyclableCompositorMac recyclable for future instances.
+ g_spare_recyclable_compositor.Get().swap(compositor);
// If there are no placeholders allocated, destroy the recyclable
- // BrowserCompositorMac that we just populated.
- if (!g_placeholder_count)
- g_recyclable_browser_compositor.Get().reset();
+ // RecyclableCompositorMac that we just populated.
+ if (!g_browser_compositor_count)
+ g_spare_recyclable_compositor.Get().reset();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BrowserCompositorMac
+
+BrowserCompositorMac::BrowserCompositorMac(
+ ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view,
+ BrowserCompositorMacClient* client,
+ bool render_widget_host_is_hidden,
+ bool ns_view_attached_to_window)
+ : client_(client),
+ accelerated_widget_mac_ns_view_(accelerated_widget_mac_ns_view),
+ weak_factory_(this) {
+ g_browser_compositor_count += 1;
+
+ root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
+ delegated_frame_host_.reset(new DelegatedFrameHost(this));
+
+ SetRenderWidgetHostIsHidden(render_widget_host_is_hidden);
+ SetNSViewAttachedToWindow(ns_view_attached_to_window);
+}
+
+BrowserCompositorMac::~BrowserCompositorMac() {
+ // Ensure that copy callbacks completed or cancelled during further tear-down
+ // do not call back into this.
+ weak_factory_.InvalidateWeakPtrs();
+
+ TransitionToState(HasNoCompositor);
+ delegated_frame_host_.reset();
+ root_layer_.reset();
+
+ DCHECK_GT(g_browser_compositor_count, 0u);
+ g_browser_compositor_count -= 1;
+
+ // If there are no compositors allocated, destroy the recyclable
+ // RecyclableCompositorMac.
+ if (!g_browser_compositor_count)
+ g_spare_recyclable_compositor.Get().reset();
+}
+
+ui::AcceleratedWidgetMac* BrowserCompositorMac::GetAcceleratedWidgetMac() {
+ if (recyclable_compositor_)
+ return recyclable_compositor_->accelerated_widget_mac();
+ return nullptr;
+}
+
+DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
+ DCHECK(delegated_frame_host_);
+ return delegated_frame_host_.get();
+}
+
+void BrowserCompositorMac::CopyCompleted(
+ base::WeakPtr<BrowserCompositorMac> browser_compositor,
+ const ReadbackRequestCallback& callback,
+ const SkBitmap& bitmap,
+ ReadbackResponse response) {
+ callback.Run(bitmap, response);
+ if (browser_compositor) {
+ browser_compositor->outstanding_copy_count_ -= 1;
+ browser_compositor->UpdateState();
+ }
+}
+
+void BrowserCompositorMac::CopyFromCompositingSurface(
+ const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ const ReadbackRequestCallback& callback,
+ SkColorType preferred_color_type) {
+ DCHECK(delegated_frame_host_);
+ DCHECK(state_ == HasAttachedCompositor);
+ outstanding_copy_count_ += 1;
+
+ auto callback_with_decrement =
+ base::Bind(&BrowserCompositorMac::CopyCompleted,
+ weak_factory_.GetWeakPtr(), callback);
+ delegated_frame_host_->CopyFromCompositingSurface(
+ src_subrect, dst_size, callback_with_decrement, preferred_color_type);
+}
+
+void BrowserCompositorMac::CopyToVideoFrameCompleted(
+ base::WeakPtr<BrowserCompositorMac> browser_compositor,
+ const base::Callback<void(const gfx::Rect&, bool)>& callback,
+ const gfx::Rect& rect,
+ bool result) {
+ callback.Run(rect, result);
+ if (browser_compositor) {
+ browser_compositor->outstanding_copy_count_ -= 1;
+ browser_compositor->UpdateState();
+ }
+}
+
+void BrowserCompositorMac::CopyFromCompositingSurfaceToVideoFrame(
+ const gfx::Rect& src_subrect,
+ const scoped_refptr<media::VideoFrame>& target,
+ const base::Callback<void(const gfx::Rect&, bool)>& callback) {
+ DCHECK(delegated_frame_host_);
+ DCHECK(state_ == HasAttachedCompositor);
+ outstanding_copy_count_ += 1;
+
+ auto callback_with_decrement =
+ base::Bind(&BrowserCompositorMac::CopyToVideoFrameCompleted,
+ weak_factory_.GetWeakPtr(), callback);
+
+ delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
+ src_subrect, target, callback_with_decrement);
+}
+
+void BrowserCompositorMac::SwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) {
+ // Compute the frame size based on the root render pass rect size.
+ cc::RenderPass* root_pass =
+ frame.delegated_frame_data->render_pass_list.back().get();
+ float scale_factor = frame.metadata.device_scale_factor;
+ gfx::Size pixel_size = root_pass->output_rect.size();
+ gfx::Size dip_size = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
+ root_layer_->SetBounds(gfx::Rect(dip_size));
+ if (recyclable_compositor_) {
+ recyclable_compositor_->compositor()->SetScaleAndSize(scale_factor,
+ pixel_size);
+ }
+ delegated_frame_host_->SwapDelegatedFrame(output_surface_id,
+ std::move(frame));
+}
+
+void BrowserCompositorMac::SetHasTransparentBackground(bool transparent) {
+ has_transparent_background_ = transparent;
+ if (recyclable_compositor_) {
+ recyclable_compositor_->compositor()->SetHostHasTransparentBackground(
+ has_transparent_background_);
+ }
+}
+
+void BrowserCompositorMac::UpdateVSyncParameters(
+ const base::TimeTicks& timebase,
+ const base::TimeDelta& interval) {
+ if (recyclable_compositor_) {
+ recyclable_compositor_->compositor()
+ ->vsync_manager()
+ ->UpdateVSyncParameters(timebase, interval);
+ }
+}
+
+void BrowserCompositorMac::SetRenderWidgetHostIsHidden(bool hidden) {
+ render_widget_host_is_hidden_ = hidden;
+ UpdateState();
+}
+
+void BrowserCompositorMac::SetNSViewAttachedToWindow(bool attached) {
+ ns_view_attached_to_window_ = attached;
+ UpdateState();
+}
+
+void BrowserCompositorMac::UpdateState() {
+ if (!render_widget_host_is_hidden_ || outstanding_copy_count_ > 0)
+ TransitionToState(HasAttachedCompositor);
+ else if (ns_view_attached_to_window_)
+ TransitionToState(HasDetachedCompositor);
+ else
+ TransitionToState(HasNoCompositor);
+}
+
+void BrowserCompositorMac::TransitionToState(State new_state) {
+ // Transition HasNoCompositor -> HasDetachedCompositor.
+ if (state_ == HasNoCompositor && new_state != HasNoCompositor) {
+ recyclable_compositor_ = RecyclableCompositorMac::Create();
+ recyclable_compositor_->compositor()->SetRootLayer(root_layer_.get());
+ recyclable_compositor_->compositor()->SetHostHasTransparentBackground(
+ has_transparent_background_);
+ recyclable_compositor_->accelerated_widget_mac()->SetNSView(
+ accelerated_widget_mac_ns_view_);
+ state_ = HasDetachedCompositor;
+ }
+
+ // Transition HasDetachedCompositor -> HasAttachedCompositor.
+ if (state_ == HasDetachedCompositor && new_state == HasAttachedCompositor) {
+ NSView* ns_view =
+ accelerated_widget_mac_ns_view_->AcceleratedWidgetGetNSView();
+ float scale_factor = ui::GetScaleFactorForNativeView(ns_view);
+ NSSize dip_ns_size = [ns_view bounds].size;
+ gfx::Size pixel_size(dip_ns_size.width * scale_factor,
+ dip_ns_size.height * scale_factor);
+
+ delegated_frame_host_->SetCompositor(recyclable_compositor_->compositor());
+ delegated_frame_host_->WasShown(ui::LatencyInfo());
+ // Unsuspend the browser compositor after showing the delegated frame host.
+ // If there is not a saved delegated frame, then the delegated frame host
+ // will keep the compositor locked until a delegated frame is swapped.
+ recyclable_compositor_->compositor()->SetScaleAndSize(scale_factor,
+ pixel_size);
+ recyclable_compositor_->Unsuspend();
+ state_ = HasAttachedCompositor;
+ }
+
+ // Transition HasAttachedCompositor -> HasDetachedCompositor.
+ if (state_ == HasAttachedCompositor && new_state != HasAttachedCompositor) {
+ // Ensure that any changes made to the ui::Compositor do not result in new
+ // frames being produced.
+ recyclable_compositor_->Suspend();
+ // Marking the DelegatedFrameHost as removed from the window hierarchy is
+ // necessary to remove all connections to its old ui::Compositor.
+ delegated_frame_host_->WasHidden();
+ delegated_frame_host_->ResetCompositor();
+ state_ = HasDetachedCompositor;
+ }
+
+ // Transition HasDetachedCompositor -> HasNoCompositor.
+ if (state_ == HasDetachedCompositor && new_state == HasNoCompositor) {
+ recyclable_compositor_->accelerated_widget_mac()->ResetNSView();
+ recyclable_compositor_->compositor()->SetScaleAndSize(1.0, gfx::Size(0, 0));
+ recyclable_compositor_->compositor()->SetRootLayer(nullptr);
+ RecyclableCompositorMac::Recycle(std::move(recyclable_compositor_));
+ state_ = HasNoCompositor;
+ }
}
// static
void BrowserCompositorMac::DisableRecyclingForShutdown() {
g_has_shut_down = true;
- g_recyclable_browser_compositor.Get().reset();
+ g_spare_recyclable_compositor.Get().reset();
+}
+
+void BrowserCompositorMac::SetNeedsBeginFrames(bool needs_begin_frames) {
+ if (needs_begin_frames_ == needs_begin_frames)
+ return;
+
+ needs_begin_frames_ = needs_begin_frames;
+ if (begin_frame_source_) {
+ if (needs_begin_frames_)
+ begin_frame_source_->AddObserver(this);
+ else
+ begin_frame_source_->RemoveObserver(this);
+ }
}
////////////////////////////////////////////////////////////////////////////////
-// BrowserCompositorMacPlaceholder
+// DelegatedFrameHost, public:
+
+ui::Layer* BrowserCompositorMac::DelegatedFrameHostGetLayer() const {
+ return root_layer_.get();
+}
-BrowserCompositorMacPlaceholder::BrowserCompositorMacPlaceholder() {
- g_placeholder_count += 1;
+bool BrowserCompositorMac::DelegatedFrameHostIsVisible() const {
+ return state_ == HasAttachedCompositor;
}
-BrowserCompositorMacPlaceholder::~BrowserCompositorMacPlaceholder() {
- DCHECK_GT(g_placeholder_count, 0u);
- g_placeholder_count -= 1;
+SkColor BrowserCompositorMac::DelegatedFrameHostGetGutterColor(
+ SkColor color) const {
+ return client_->BrowserCompositorMacGetGutterColor(color);
+}
- // If there are no placeholders allocated, destroy the recyclable
- // BrowserCompositorMac.
- if (!g_placeholder_count)
- g_recyclable_browser_compositor.Get().reset();
+gfx::Size BrowserCompositorMac::DelegatedFrameHostDesiredSizeInDIP() const {
+ NSRect bounds = [client_->BrowserCompositorMacGetNSView() bounds];
+ return gfx::Size(bounds.size.width, bounds.size.height);
+}
+
+bool BrowserCompositorMac::DelegatedFrameCanCreateResizeLock() const {
+ // Mac uses the RenderWidgetResizeHelper instead of a resize lock.
+ return false;
+}
+
+std::unique_ptr<ResizeLock>
+BrowserCompositorMac::DelegatedFrameHostCreateResizeLock(
+ bool defer_compositor_lock) {
+ NOTREACHED();
+ return std::unique_ptr<ResizeLock>();
+}
+
+void BrowserCompositorMac::DelegatedFrameHostResizeLockWasReleased() {
+ NOTREACHED();
+}
+
+void BrowserCompositorMac::DelegatedFrameHostSendCompositorSwapAck(
+ int output_surface_id,
+ const cc::CompositorFrameAck& ack) {
+ client_->BrowserCompositorMacSendCompositorSwapAck(output_surface_id, ack);
+}
+
+void BrowserCompositorMac::DelegatedFrameHostSendReclaimCompositorResources(
+ int output_surface_id,
+ const cc::CompositorFrameAck& ack) {
+ client_->BrowserCompositorMacSendReclaimCompositorResources(output_surface_id,
+ ack);
+}
+
+void BrowserCompositorMac::DelegatedFrameHostOnLostCompositorResources() {
+ client_->BrowserCompositorMacOnLostCompositorResources();
+}
+
+void BrowserCompositorMac::DelegatedFrameHostUpdateVSyncParameters(
+ const base::TimeTicks& timebase,
+ const base::TimeDelta& interval) {
+ client_->BrowserCompositorMacUpdateVSyncParameters(timebase, interval);
+}
+
+void BrowserCompositorMac::SetBeginFrameSource(cc::BeginFrameSource* source) {
+ if (begin_frame_source_ && needs_begin_frames_)
+ begin_frame_source_->RemoveObserver(this);
+ begin_frame_source_ = source;
+ if (begin_frame_source_ && needs_begin_frames_)
+ begin_frame_source_->AddObserver(this);
+}
+
+bool BrowserCompositorMac::IsAutoResizeEnabled() const {
+ NOTREACHED();
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// cc::BeginFrameSourceBase, public:
+
+void BrowserCompositorMac::OnBeginFrame(const cc::BeginFrameArgs& args) {
+ delegated_frame_host_->SetVSyncParameters(args.frame_time, args.interval);
+ client_->BrowserCompositorMacSendBeginFrame(args);
+ last_begin_frame_args_ = args;
+}
+
+const cc::BeginFrameArgs& BrowserCompositorMac::LastUsedBeginFrameArgs() const {
+ return last_begin_frame_args_;
+}
+
+void BrowserCompositorMac::OnBeginFrameSourcePausedChanged(bool paused) {
+ // Only used on Android WebView.
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 2aedd746448..838ec057b60 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -7,7 +7,7 @@
#include <android/bitmap.h>
#include <android/native_window_jni.h>
#include <stdint.h>
-
+#include <unordered_set>
#include <utility>
#include "base/android/jni_android.h"
@@ -28,6 +28,7 @@
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "cc/animation/animation_host.h"
#include "cc/base/switches.h"
#include "cc/input/input_handler.h"
#include "cc/layers/layer.h"
@@ -35,10 +36,12 @@
#include "cc/output/context_provider.h"
#include "cc/output/output_surface.h"
#include "cc/output/output_surface_client.h"
+#include "cc/output/texture_mailbox_deleter.h"
#include "cc/output/vulkan_in_process_context_provider.h"
#include "cc/raster/single_thread_task_graph_runner.h"
#include "cc/scheduler/begin_frame_source.h"
-#include "cc/surfaces/onscreen_display_client.h"
+#include "cc/surfaces/display.h"
+#include "cc/surfaces/display_scheduler.h"
#include "cc/surfaces/surface_display_output_surface.h"
#include "cc/surfaces/surface_id_allocator.h"
#include "cc/surfaces/surface_manager.h"
@@ -80,23 +83,40 @@ namespace {
const unsigned int kMaxDisplaySwapBuffers = 1U;
-class ExternalBeginFrameSource : public cc::BeginFrameSourceBase,
+class ExternalBeginFrameSource : public cc::BeginFrameSource,
public CompositorImpl::VSyncObserver {
public:
- ExternalBeginFrameSource(CompositorImpl* compositor)
+ explicit ExternalBeginFrameSource(CompositorImpl* compositor)
: compositor_(compositor) {
compositor_->AddObserver(this);
}
-
~ExternalBeginFrameSource() override { compositor_->RemoveObserver(this); }
- // cc::BeginFrameSourceBase implementation:
- void AddObserver(cc::BeginFrameObserver* obs) override {
- cc::BeginFrameSourceBase::AddObserver(obs);
- DCHECK(needs_begin_frames());
- if (!last_begin_frame_args_.IsValid())
- return;
+ // cc::BeginFrameSource implementation.
+ void AddObserver(cc::BeginFrameObserver* obs) override;
+ void RemoveObserver(cc::BeginFrameObserver* obs) override;
+ void DidFinishFrame(cc::BeginFrameObserver* obs,
+ size_t remaining_frames) override {}
+
+ // CompositorImpl::VSyncObserver implementation.
+ void OnVSync(base::TimeTicks frame_time,
+ base::TimeDelta vsync_period) override;
+ private:
+ CompositorImpl* const compositor_;
+ std::unordered_set<cc::BeginFrameObserver*> observers_;
+ cc::BeginFrameArgs last_begin_frame_args_;
+};
+
+void ExternalBeginFrameSource::AddObserver(cc::BeginFrameObserver* obs) {
+ DCHECK(obs);
+ DCHECK(observers_.find(obs) == observers_.end());
+
+ observers_.insert(obs);
+ obs->OnBeginFrameSourcePausedChanged(false);
+ compositor_->OnNeedsBeginFramesChange(true);
+
+ if (last_begin_frame_args_.IsValid()) {
// Send a MISSED begin frame if necessary.
cc::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
if (!last_args.IsValid() ||
@@ -111,61 +131,56 @@ class ExternalBeginFrameSource : public cc::BeginFrameSourceBase,
obs->OnBeginFrame(last_begin_frame_args_);
}
}
+}
- void OnNeedsBeginFramesChanged(bool needs_begin_frames) override {
- TRACE_EVENT1("compositor", "OnNeedsBeginFramesChanged",
- "needs_begin_frames", needs_begin_frames);
- compositor_->OnNeedsBeginFramesChange(needs_begin_frames);
- }
+void ExternalBeginFrameSource::RemoveObserver(cc::BeginFrameObserver* obs) {
+ DCHECK(obs);
+ DCHECK(observers_.find(obs) != observers_.end());
- // CompositorImpl::VSyncObserver implementation:
- void OnVSync(base::TimeTicks frame_time,
- base::TimeDelta vsync_period) override {
- base::TimeTicks deadline = std::max(base::TimeTicks::Now(), frame_time);
- last_begin_frame_args_ =
- cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
- vsync_period, cc::BeginFrameArgs::NORMAL);
- CallOnBeginFrame(last_begin_frame_args_);
- }
+ observers_.erase(obs);
+ if (observers_.empty())
+ compositor_->OnNeedsBeginFramesChange(false);
+}
- private:
- CompositorImpl* compositor_;
- cc::BeginFrameArgs last_begin_frame_args_;
-};
+void ExternalBeginFrameSource::OnVSync(base::TimeTicks frame_time,
+ base::TimeDelta vsync_period) {
+ base::TimeTicks deadline = std::max(base::TimeTicks::Now(), frame_time);
+ last_begin_frame_args_ =
+ cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
+ vsync_period, cc::BeginFrameArgs::NORMAL);
+ std::unordered_set<cc::BeginFrameObserver*> observers(observers_);
+ for (auto* obs : observers)
+ obs->OnBeginFrame(last_begin_frame_args_);
+}
// Used to override capabilities_.adjust_deadline_for_parent to false
-class OutputSurfaceWithoutParent : public cc::OutputSurface,
- public CompositorImpl::VSyncObserver {
+class OutputSurfaceWithoutParent : public cc::OutputSurface {
public:
OutputSurfaceWithoutParent(
- CompositorImpl* compositor,
- const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
+ scoped_refptr<ContextProviderCommandBuffer> context_provider,
const base::Callback<void(gpu::Capabilities)>&
- populate_gpu_capabilities_callback,
- std::unique_ptr<ExternalBeginFrameSource> begin_frame_source)
- : cc::OutputSurface(context_provider),
- compositor_(compositor),
+ populate_gpu_capabilities_callback)
+ : cc::OutputSurface(std::move(context_provider), nullptr, nullptr),
populate_gpu_capabilities_callback_(populate_gpu_capabilities_callback),
swap_buffers_completion_callback_(
base::Bind(&OutputSurfaceWithoutParent::OnSwapBuffersCompleted,
base::Unretained(this))),
overlay_candidate_validator_(
new display_compositor::
- CompositorOverlayCandidateValidatorAndroid()),
- begin_frame_source_(std::move(begin_frame_source)) {
+ CompositorOverlayCandidateValidatorAndroid()) {
capabilities_.adjust_deadline_for_parent = false;
capabilities_.max_frames_pending = kMaxDisplaySwapBuffers;
}
- ~OutputSurfaceWithoutParent() override { compositor_->RemoveObserver(this); }
+ ~OutputSurfaceWithoutParent() override = default;
- void SwapBuffers(cc::CompositorFrame* frame) override {
- GetCommandBufferProxy()->SetLatencyInfo(frame->metadata.latency_info);
- if (frame->gl_frame_data->sub_buffer_rect.IsEmpty()) {
+ void SwapBuffers(cc::CompositorFrame frame) override {
+ GetCommandBufferProxy()->SetLatencyInfo(frame.metadata.latency_info);
+ if (frame.gl_frame_data->sub_buffer_rect.IsEmpty()) {
context_provider_->ContextSupport()->CommitOverlayPlanes();
} else {
- DCHECK(frame->gl_frame_data->sub_buffer_rect ==
- gfx::Rect(frame->gl_frame_data->size));
+ DCHECK(frame.gl_frame_data->sub_buffer_rect ==
+ gfx::Rect(frame.gl_frame_data->size));
context_provider_->ContextSupport()->Swap();
}
client_->DidSwapBuffers();
@@ -180,22 +195,18 @@ class OutputSurfaceWithoutParent : public cc::OutputSurface,
populate_gpu_capabilities_callback_.Run(
context_provider_->ContextCapabilities());
- compositor_->AddObserver(this);
-
- client->SetBeginFrameSource(begin_frame_source_.get());
-
return true;
}
- void DetachFromClient() override {
- client_->SetBeginFrameSource(nullptr);
- OutputSurface::DetachFromClient();
- }
-
cc::OverlayCandidateValidator* GetOverlayCandidateValidator() const override {
return overlay_candidate_validator_.get();
}
+ uint32_t GetFramebufferCopyTextureFormat() override {
+ auto* gl = static_cast<ContextProviderCommandBuffer*>(context_provider());
+ return gl->GetCopyTextureInternalFormat();
+ }
+
private:
gpu::CommandBufferProxyImpl* GetCommandBufferProxy() {
ContextProviderCommandBuffer* provider_command_buffer =
@@ -215,12 +226,7 @@ class OutputSurfaceWithoutParent : public cc::OutputSurface,
OutputSurface::OnSwapBuffersComplete();
}
- void OnVSync(base::TimeTicks timebase, base::TimeDelta interval) override {
- client_->CommitVSyncParameters(timebase, interval);
- }
-
private:
- CompositorImpl* compositor_;
base::Callback<void(gpu::Capabilities)> populate_gpu_capabilities_callback_;
base::CancelableCallback<void(
const std::vector<ui::LatencyInfo>&,
@@ -228,20 +234,14 @@ class OutputSurfaceWithoutParent : public cc::OutputSurface,
const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac)>
swap_buffers_completion_callback_;
std::unique_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator_;
- std::unique_ptr<ExternalBeginFrameSource> begin_frame_source_;
};
#if defined(ENABLE_VULKAN)
class VulkanOutputSurface : public cc::OutputSurface {
public:
- VulkanOutputSurface(
- scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
- std::unique_ptr<ExternalBeginFrameSource> begin_frame_source)
- : OutputSurface(nullptr,
- nullptr,
- std::move(vulkan_context_provider),
- nullptr),
- begin_frame_source_(std::move(begin_frame_source)) {}
+ explicit VulkanOutputSurface(
+ scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider)
+ : OutputSurface(std::move(vulkan_context_provider)) {}
~VulkanOutputSurface() override { Destroy(); }
@@ -261,11 +261,10 @@ class VulkanOutputSurface : public cc::OutputSurface {
bool BindToClient(cc::OutputSurfaceClient* client) override {
if (!OutputSurface::BindToClient(client))
return false;
- client->SetBeginFrameSource(begin_frame_source_.get());
return true;
}
- void SwapBuffers(cc::CompositorFrame* frame) override {
+ void SwapBuffers(cc::CompositorFrame frame) override {
surface_->SwapBuffers();
PostSwapBuffersComplete();
client_->DidSwapBuffers();
@@ -286,7 +285,6 @@ class VulkanOutputSurface : public cc::OutputSurface {
private:
std::unique_ptr<gpu::VulkanSurface> surface_;
- std::unique_ptr<ExternalBeginFrameSource> begin_frame_source_;
DISALLOW_COPY_AND_ASSIGN(VulkanOutputSurface);
};
@@ -473,6 +471,7 @@ void CompositorImpl::CreateLayerTreeHost() {
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();
host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
DCHECK(!host_->visible());
host_->SetRootLayer(root_layer_);
@@ -494,7 +493,7 @@ void CompositorImpl::SetVisible(bool visible) {
host_->ReleaseOutputSurface();
pending_swapbuffers_ = 0;
establish_gpu_channel_timeout_.Stop();
- display_client_.reset();
+ display_.reset();
} else {
host_->SetVisible(true);
if (output_surface_request_pending_)
@@ -515,8 +514,8 @@ void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
size_ = size;
if (host_)
host_->SetViewportSize(size);
- if (display_client_)
- display_client_->display()->Resize(size);
+ if (display_)
+ display_->Resize(size);
root_layer_->SetBounds(size);
}
@@ -598,23 +597,22 @@ void CompositorImpl::CreateOutputSurface() {
scoped_refptr<ContextProviderCommandBuffer> context_provider;
scoped_refptr<cc::VulkanInProcessContextProvider> vulkan_context_provider =
SharedVulkanContextProviderAndroid();
- std::unique_ptr<cc::OutputSurface> real_output_surface;
+ std::unique_ptr<cc::OutputSurface> display_output_surface;
#if defined(ENABLE_VULKAN)
std::unique_ptr<VulkanOutputSurface> vulkan_surface;
if (vulkan_context_provider) {
- vulkan_surface.reset(new VulkanOutputSurface(
- std::move(vulkan_context_provider),
- base::WrapUnique(new ExternalBeginFrameSource(this))));
+ vulkan_surface.reset(
+ new VulkanOutputSurface(std::move(vulkan_context_provider)));
if (!vulkan_surface->Initialize(window_)) {
vulkan_surface->Destroy();
vulkan_surface.reset();
} else {
- real_output_surface = std::move(vulkan_surface);
+ display_output_surface = std::move(vulkan_surface);
}
}
#endif
- if (!real_output_surface) {
+ if (!display_output_surface) {
// This is used for the browser compositor (offscreen) and for the display
// compositor (onscreen), so ask for capabilities needed by either one.
// The default framebuffer for an offscreen context is not used, so it does
@@ -686,41 +684,44 @@ void CompositorImpl::CreateOutputSurface() {
context_provider = new ContextProviderCommandBuffer(
std::move(gpu_channel_host), gpu::GPU_STREAM_DEFAULT,
- gpu::GpuStreamPriority::NORMAL, surface_handle_, url,
- gfx::PreferIntegratedGpu, automatic_flushes, support_locking, limits,
- attributes, nullptr,
+ gpu::GpuStreamPriority::NORMAL, surface_handle_, url, automatic_flushes,
+ support_locking, limits, attributes, nullptr,
command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT);
DCHECK(context_provider.get());
- real_output_surface = base::WrapUnique(new OutputSurfaceWithoutParent(
- this, context_provider,
- base::Bind(&CompositorImpl::PopulateGpuCapabilities,
- base::Unretained(this)),
- base::WrapUnique(new ExternalBeginFrameSource(this))));
+ display_output_surface = base::WrapUnique(new OutputSurfaceWithoutParent(
+ context_provider, base::Bind(&CompositorImpl::PopulateGpuCapabilities,
+ base::Unretained(this))));
}
cc::SurfaceManager* manager = GetSurfaceManager();
- display_client_.reset(new cc::OnscreenDisplayClient(
- std::move(real_output_surface), manager,
- HostSharedBitmapManager::current(),
+ auto* task_runner = base::ThreadTaskRunnerHandle::Get().get();
+ std::unique_ptr<ExternalBeginFrameSource> begin_frame_source(
+ new ExternalBeginFrameSource(this));
+ std::unique_ptr<cc::DisplayScheduler> scheduler(new cc::DisplayScheduler(
+ begin_frame_source.get(), task_runner,
+ display_output_surface->capabilities().max_frames_pending));
+
+ display_.reset(new cc::Display(
+ manager, HostSharedBitmapManager::current(),
BrowserGpuMemoryBufferManager::current(),
- host_->settings().renderer_settings, base::ThreadTaskRunnerHandle::Get(),
- surface_id_allocator_->id_namespace()));
+ host_->settings().renderer_settings,
+ surface_id_allocator_->id_namespace(), std::move(begin_frame_source),
+ std::move(display_output_surface), std::move(scheduler),
+ base::MakeUnique<cc::TextureMailboxDeleter>(task_runner)));
- std::unique_ptr<cc::SurfaceDisplayOutputSurface> surface_output_surface(
+ std::unique_ptr<cc::SurfaceDisplayOutputSurface> delegated_output_surface(
vulkan_context_provider
? new cc::SurfaceDisplayOutputSurface(
- manager, surface_id_allocator_.get(),
+ manager, surface_id_allocator_.get(), display_.get(),
static_cast<scoped_refptr<cc::VulkanContextProvider>>(
vulkan_context_provider))
- : new cc::SurfaceDisplayOutputSurface(manager,
- surface_id_allocator_.get(),
- context_provider, nullptr));
-
- display_client_->set_surface_output_surface(surface_output_surface.get());
- surface_output_surface->set_display_client(display_client_.get());
- display_client_->display()->Resize(size_);
- host_->SetOutputSurface(std::move(surface_output_surface));
+ : new cc::SurfaceDisplayOutputSurface(
+ manager, surface_id_allocator_.get(), display_.get(),
+ context_provider, nullptr));
+
+ display_->Resize(size_);
+ host_->SetOutputSurface(std::move(delegated_output_surface));
}
void CompositorImpl::PopulateGpuCapabilities(
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index b0ef00703eb..cf3c7113bc3 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -31,9 +31,9 @@ class SkBitmap;
struct ANativeWindow;
namespace cc {
+class Display;
class Layer;
class LayerTreeHost;
-class OnscreenDisplayClient;
class SurfaceIdAllocator;
class SurfaceManager;
class VulkanInProcessContextProvider;
@@ -110,9 +110,6 @@ class CONTENT_EXPORT CompositorImpl
void DidCommitAndDrawFrame() override {}
void DidCompleteSwapBuffers() override;
void DidCompletePageScaleAnimation() override {}
- void ReportFixedRasterScaleUseCounters(
- bool has_blurry_content,
- bool has_potential_performance_regression) override {}
// LayerTreeHostSingleThreadClient implementation.
void DidPostSwapBuffers() override;
@@ -142,7 +139,7 @@ class CONTENT_EXPORT CompositorImpl
std::unique_ptr<cc::LayerTreeHost> host_;
ui::ResourceManagerImpl resource_manager_;
- std::unique_ptr<cc::OnscreenDisplayClient> display_client_;
+ std::unique_ptr<cc::Display> display_;
gfx::Size size_;
bool has_transparent_background_;
diff --git a/chromium/content/browser/renderer_host/database_message_filter.cc b/chromium/content/browser/renderer_host/database_message_filter.cc
index 5f9a8ae5d72..8bf1adbb41a 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.cc
+++ b/chromium/content/browser/renderer_host/database_message_filter.cc
@@ -25,6 +25,7 @@
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/common/database/database_identifier.h"
#include "third_party/sqlite/sqlite3.h"
+#include "url/origin.h"
#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
@@ -42,6 +43,10 @@ namespace {
const int kNumDeleteRetries = 2;
const int kDelayDeleteRetryMs = 100;
+bool IsOriginValid(const url::Origin& origin) {
+ return !origin.unique();
+}
+
} // namespace
DatabaseMessageFilter::DatabaseMessageFilter(
@@ -249,10 +254,17 @@ void DatabaseMessageFilter::OnDatabaseGetFileSize(
}
void DatabaseMessageFilter::OnDatabaseGetSpaceAvailable(
- const std::string& origin_identifier, IPC::Message* reply_msg) {
+ const url::Origin& origin,
+ IPC::Message* reply_msg) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(db_tracker_->quota_manager_proxy());
+ if (!IsOriginValid(origin)) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::DBMF_INVALID_ORIGIN_ON_GET_SPACE);
+ return;
+ }
+
QuotaManager* quota_manager =
db_tracker_->quota_manager_proxy()->quota_manager();
if (!quota_manager) {
@@ -267,10 +279,9 @@ void DatabaseMessageFilter::OnDatabaseGetSpaceAvailable(
TRACE_EVENT0("io", "DatabaseMessageFilter::OnDatabaseGetSpaceAvailable");
quota_manager->GetUsageAndQuota(
- storage::GetOriginFromIdentifier(origin_identifier),
- storage::kStorageTypeTemporary,
- base::Bind(
- &DatabaseMessageFilter::OnDatabaseGetUsageAndQuota, this, reply_msg));
+ GURL(origin.Serialize()), storage::kStorageTypeTemporary,
+ base::Bind(&DatabaseMessageFilter::OnDatabaseGetUsageAndQuota, this,
+ reply_msg));
}
void DatabaseMessageFilter::OnDatabaseGetUsageAndQuota(
@@ -298,36 +309,45 @@ void DatabaseMessageFilter::OnDatabaseSetFileSize(
}
void DatabaseMessageFilter::OnDatabaseOpened(
- const std::string& origin_identifier,
+ const url::Origin& origin,
const base::string16& database_name,
const base::string16& description,
int64_t estimated_size) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- if (!storage::IsValidOriginIdentifier(origin_identifier)) {
+ if (!IsOriginValid(origin)) {
bad_message::ReceivedBadMessage(this,
bad_message::DBMF_INVALID_ORIGIN_ON_OPEN);
return;
}
- UMA_HISTOGRAM_BOOLEAN(
- "websql.OpenDatabase",
- IsOriginSecure(storage::GetOriginFromIdentifier(origin_identifier)));
+ GURL origin_url(origin.Serialize());
+ UMA_HISTOGRAM_BOOLEAN("websql.OpenDatabase", IsOriginSecure(origin_url));
int64_t database_size = 0;
+ std::string origin_identifier(storage::GetIdentifierFromOrigin(origin_url));
db_tracker_->DatabaseOpened(origin_identifier, database_name, description,
estimated_size, &database_size);
+
database_connections_.AddConnection(origin_identifier, database_name);
- Send(new DatabaseMsg_UpdateSize(origin_identifier, database_name,
- database_size));
+ Send(new DatabaseMsg_UpdateSize(origin, database_name, database_size));
}
void DatabaseMessageFilter::OnDatabaseModified(
- const std::string& origin_identifier,
+ const url::Origin& origin,
const base::string16& database_name) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- if (!database_connections_.IsDatabaseOpened(
- origin_identifier, database_name)) {
+
+ if (!IsOriginValid(origin)) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::DBMF_INVALID_ORIGIN_ON_MODIFIED);
+ return;
+ }
+
+ std::string origin_identifier(
+ storage::GetIdentifierFromOrigin(GURL(origin.Serialize())));
+ if (!database_connections_.IsDatabaseOpened(origin_identifier,
+ database_name)) {
bad_message::ReceivedBadMessage(this,
bad_message::DBMF_DB_NOT_OPEN_ON_MODIFY);
return;
@@ -337,9 +357,18 @@ void DatabaseMessageFilter::OnDatabaseModified(
}
void DatabaseMessageFilter::OnDatabaseClosed(
- const std::string& origin_identifier,
+ const url::Origin& origin,
const base::string16& database_name) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+
+ if (!IsOriginValid(origin)) {
+ bad_message::ReceivedBadMessage(this,
+ bad_message::DBMF_INVALID_ORIGIN_ON_CLOSED);
+ return;
+ }
+
+ std::string origin_identifier(
+ storage::GetIdentifierFromOrigin(GURL(origin.Serialize())));
if (!database_connections_.IsDatabaseOpened(
origin_identifier, database_name)) {
bad_message::ReceivedBadMessage(this,
@@ -352,17 +381,18 @@ void DatabaseMessageFilter::OnDatabaseClosed(
}
void DatabaseMessageFilter::OnHandleSqliteError(
- const std::string& origin_identifier,
+ const url::Origin& origin,
const base::string16& database_name,
int error) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- if (!storage::IsValidOriginIdentifier(origin_identifier)) {
+ if (!IsOriginValid(origin)) {
bad_message::ReceivedBadMessage(
this, bad_message::DBMF_INVALID_ORIGIN_ON_SQLITE_ERROR);
return;
}
-
- db_tracker_->HandleSqliteError(origin_identifier, database_name, error);
+ db_tracker_->HandleSqliteError(
+ storage::GetIdentifierFromOrigin(GURL(origin.Serialize())), database_name,
+ error);
}
void DatabaseMessageFilter::OnDatabaseSizeChanged(
@@ -371,8 +401,9 @@ void DatabaseMessageFilter::OnDatabaseSizeChanged(
int64_t database_size) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
if (database_connections_.IsOriginUsed(origin_identifier)) {
- Send(new DatabaseMsg_UpdateSize(origin_identifier, database_name,
- database_size));
+ Send(new DatabaseMsg_UpdateSize(
+ url::Origin(storage::GetOriginFromIdentifier(origin_identifier)),
+ database_name, database_size));
}
}
@@ -380,7 +411,9 @@ void DatabaseMessageFilter::OnDatabaseScheduledForDeletion(
const std::string& origin_identifier,
const base::string16& database_name) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- Send(new DatabaseMsg_CloseImmediately(origin_identifier, database_name));
+ Send(new DatabaseMsg_CloseImmediately(
+ url::Origin(storage::GetOriginFromIdentifier(origin_identifier)),
+ database_name));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/database_message_filter.h b/chromium/content/browser/renderer_host/database_message_filter.h
index 4cf4e92fb80..125dcefbb18 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.h
+++ b/chromium/content/browser/renderer_host/database_message_filter.h
@@ -15,6 +15,10 @@
#include "storage/common/database/database_connections.h"
#include "storage/common/quota/quota_types.h"
+namespace url {
+class Origin;
+} // namespace url
+
namespace content {
class DatabaseMessageFilter : public BrowserMessageFilter,
@@ -56,7 +60,7 @@ class DatabaseMessageFilter : public BrowserMessageFilter,
bool* success);
// Quota message handler (io thread)
- void OnDatabaseGetSpaceAvailable(const std::string& origin_identifier,
+ void OnDatabaseGetSpaceAvailable(const url::Origin& origin,
IPC::Message* reply_msg);
void OnDatabaseGetUsageAndQuota(IPC::Message* reply_msg,
storage::QuotaStatusCode status,
@@ -64,15 +68,15 @@ class DatabaseMessageFilter : public BrowserMessageFilter,
int64_t quota);
// Database tracker message handlers (file thread)
- void OnDatabaseOpened(const std::string& origin_identifier,
+ void OnDatabaseOpened(const url::Origin& origin,
const base::string16& database_name,
const base::string16& description,
int64_t estimated_size);
- void OnDatabaseModified(const std::string& origin_identifier,
+ void OnDatabaseModified(const url::Origin& origin,
const base::string16& database_name);
- void OnDatabaseClosed(const std::string& origin_identifier,
+ void OnDatabaseClosed(const url::Origin& origin,
const base::string16& database_name);
- void OnHandleSqliteError(const std::string& origin_identifier,
+ void OnHandleSqliteError(const url::Origin& origin,
const base::string16& database_name,
int error);
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.cc b/chromium/content/browser/renderer_host/delegated_frame_host.cc
index 6df1b6d1812..3f3d415d8dd 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.cc
@@ -41,15 +41,15 @@ namespace content {
namespace {
void SatisfyCallback(cc::SurfaceManager* manager,
- cc::SurfaceSequence sequence) {
+ const cc::SurfaceSequence& sequence) {
std::vector<uint32_t> sequences;
sequences.push_back(sequence.sequence);
manager->DidSatisfySequences(sequence.id_namespace, &sequences);
}
void RequireCallback(cc::SurfaceManager* manager,
- cc::SurfaceId id,
- cc::SurfaceSequence sequence) {
+ const cc::SurfaceId& id,
+ const cc::SurfaceSequence& sequence) {
cc::Surface* surface = manager->GetSurfaceForId(id);
if (!surface) {
LOG(ERROR) << "Attempting to require callback on nonexistent surface";
@@ -75,7 +75,7 @@ DelegatedFrameHost::DelegatedFrameHost(DelegatedFrameHostClient* client)
can_lock_compositor_(YES_CAN_LOCK),
delegated_frame_evictor_(new DelegatedFrameEvictor(this)) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- factory->AddObserver(this);
+ factory->GetContextFactory()->AddObserver(this);
id_allocator_ = factory->GetContextFactory()->CreateSurfaceIdAllocator();
factory->GetSurfaceManager()->RegisterSurfaceFactoryClient(
id_allocator_->id_namespace(), this);
@@ -381,12 +381,14 @@ void DelegatedFrameHost::AttemptFrameSubscriberCapture(
}
}
-void DelegatedFrameHost::SwapDelegatedFrame(
- uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {
- DCHECK(frame->delegated_frame_data.get());
- cc::DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
- float frame_device_scale_factor = frame->metadata.device_scale_factor;
+void DelegatedFrameHost::SwapDelegatedFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) {
+ DCHECK(frame.delegated_frame_data.get());
+#if defined(OS_CHROMEOS)
+ DCHECK(!resize_lock_ || !client_->IsAutoResizeEnabled());
+#endif
+ cc::DelegatedFrameData* frame_data = frame.delegated_frame_data.get();
+ float frame_device_scale_factor = frame.metadata.device_scale_factor;
DCHECK(!frame_data->render_pass_list.empty());
@@ -407,8 +409,8 @@ void DelegatedFrameHost::SwapDelegatedFrame(
&ack.resources);
skipped_latency_info_list_.insert(skipped_latency_info_list_.end(),
- frame->metadata.latency_info.begin(),
- frame->metadata.latency_info.end());
+ frame.metadata.latency_info.begin(),
+ frame.metadata.latency_info.end());
client_->DelegatedFrameHostSendCompositorSwapAck(output_surface_id, ack);
skipped_frames_ = true;
@@ -444,7 +446,7 @@ void DelegatedFrameHost::SwapDelegatedFrame(
bool skip_frame = false;
pending_delegated_ack_count_++;
- background_color_ = frame->metadata.root_background_color;
+ background_color_ = frame.metadata.root_background_color;
if (frame_size.IsEmpty()) {
DCHECK(frame_data->resource_list.empty());
@@ -471,9 +473,9 @@ void DelegatedFrameHost::SwapDelegatedFrame(
current_scale_factor_ = frame_device_scale_factor;
}
- frame->metadata.latency_info.insert(frame->metadata.latency_info.end(),
- skipped_latency_info_list_.begin(),
- skipped_latency_info_list_.end());
+ frame.metadata.latency_info.insert(frame.metadata.latency_info.end(),
+ skipped_latency_info_list_.begin(),
+ skipped_latency_info_list_.end());
skipped_latency_info_list_.clear();
gfx::Size desired_size = client_->DelegatedFrameHostDesiredSizeInDIP();
@@ -550,7 +552,7 @@ void DelegatedFrameHost::ReturnResources(
SendReturnedDelegatedResources(last_output_surface_id_);
}
-void DelegatedFrameHost::WillDrawSurface(cc::SurfaceId id,
+void DelegatedFrameHost::WillDrawSurface(const cc::SurfaceId& id,
const gfx::Rect& damage_rect) {
// Frame subscribers are only interested in changes to the target surface, so
// do not attempt capture if |damage_rect| is empty. This prevents the draws
@@ -807,7 +809,7 @@ void DelegatedFrameHost::OnLostResources() {
DelegatedFrameHost::~DelegatedFrameHost() {
DCHECK(!compositor_);
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- factory->RemoveObserver(this);
+ factory->GetContextFactory()->RemoveObserver(this);
if (!surface_id_.is_null())
surface_factory_->Destroy(surface_id_);
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.h b/chromium/content/browser/renderer_host/delegated_frame_host.h
index 9fda24d18ed..b969d32a642 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.h
@@ -81,6 +81,7 @@ class CONTENT_EXPORT DelegatedFrameHostClient {
const base::TimeTicks& timebase,
const base::TimeDelta& interval) = 0;
virtual void SetBeginFrameSource(cc::BeginFrameSource* source) = 0;
+ virtual bool IsAutoResizeEnabled() const = 0;
};
// The DelegatedFrameHost is used to host all of the RenderWidgetHostView state
@@ -91,7 +92,7 @@ class CONTENT_EXPORT DelegatedFrameHost
: public ui::CompositorObserver,
public ui::CompositorVSyncManager::Observer,
public ui::LayerOwnerDelegate,
- public ImageTransportFactoryObserver,
+ public ui::ContextFactoryObserver,
public DelegatedFrameEvictorClient,
public cc::SurfaceFactoryClient,
public base::SupportsWeakPtr<DelegatedFrameHost> {
@@ -123,7 +124,8 @@ class CONTENT_EXPORT DelegatedFrameHost
// cc::SurfaceFactoryClient implementation.
void ReturnResources(const cc::ReturnedResourceArray& resources) override;
- void WillDrawSurface(cc::SurfaceId id, const gfx::Rect& damage_rect) override;
+ void WillDrawSurface(const cc::SurfaceId& id,
+ const gfx::Rect& damage_rect) override;
void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override;
bool CanCopyToBitmap() const;
@@ -131,7 +133,7 @@ class CONTENT_EXPORT DelegatedFrameHost
// Public interface exposed to RenderWidgetHostView.
void SwapDelegatedFrame(uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame);
+ cc::CompositorFrame frame);
void ClearDelegatedFrame();
void WasHidden();
void WasShown(const ui::LatencyInfo& latency_info);
diff --git a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
index 22e189c7b8a..b7f0a6c7735 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
+++ b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
@@ -20,9 +20,9 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/dwrite_font_proxy_messages.h"
-#include "content/common/dwrite_text_analysis_source_win.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/win/direct_write.h"
+#include "ui/gfx/win/text_analysis_source.h"
namespace mswr = Microsoft::WRL;
@@ -101,7 +101,7 @@ void DWriteFontProxyMessageFilter::OverrideThreadForMessage(
const IPC::Message& message,
content::BrowserThread::ID* thread) {
if (IPC_MESSAGE_CLASS(message) == DWriteFontProxyMsgStart)
- *thread = BrowserThread::FILE;
+ *thread = BrowserThread::FILE_USER_BLOCKING;
}
void DWriteFontProxyMessageFilter::OnFindFamily(
@@ -258,7 +258,7 @@ void DWriteFontProxyMessageFilter::OnMapCharacters(
return;
}
mswr::ComPtr<IDWriteTextAnalysisSource> analysis_source;
- if (FAILED(mswr::MakeAndInitialize<TextAnalysisSource>(
+ if (FAILED(mswr::MakeAndInitialize<gfx::win::TextAnalysisSource>(
&analysis_source, text, locale_name, number_substitution.Get(),
static_cast<DWRITE_READING_DIRECTION>(reading_direction)))) {
DCHECK(false);
@@ -325,7 +325,7 @@ void DWriteFontProxyMessageFilter::OnMapCharacters(
}
void DWriteFontProxyMessageFilter::InitializeDirectWrite() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE_USER_BLOCKING);
if (direct_write_initialized_)
return;
direct_write_initialized_ = true;
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 343c2ac807a..4804d975d92 100644
--- a/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h
+++ b/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h
@@ -8,17 +8,22 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/shared_memory.h"
-#include "content/browser/gamepad/gamepad_consumer.h"
#include "content/public/browser/browser_message_filter.h"
+#include "device/gamepad/gamepad_consumer.h"
-namespace content {
+namespace device {
class GamepadService;
+
+}
+
+namespace content {
+
class RenderProcessHost;
class GamepadBrowserMessageFilter :
public BrowserMessageFilter,
- public GamepadConsumer {
+ public device::GamepadConsumer {
public:
GamepadBrowserMessageFilter();
diff --git a/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc b/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
index bc1728406aa..9785958481f 100644
--- a/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
@@ -102,9 +102,7 @@ class CompositedScrollingBrowserTest : public ContentBrowserTest {
int ExecuteScriptAndExtractInt(const std::string& script) {
int value = 0;
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(" + script + ")",
- &value));
+ shell(), "domAutomationController.send(" + script + ")", &value));
return value;
}
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 f713acce797..51f63d0eb11 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
@@ -13,6 +13,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -125,9 +126,7 @@ class GestureEventQueueTest : public testing::Test,
queue()->ProcessGestureAck(ack, type, ui::LatencyInfo());
}
- void RunUntilIdle() {
- base::MessageLoop::current()->RunUntilIdle();
- }
+ void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
size_t GetAndResetSentGestureEventCount() {
size_t count = sent_gesture_event_count_;
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 aee5c790312..4428a69b9fa 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -21,7 +21,6 @@
#include "content/common/content_constants_internal.h"
#include "content/common/edit_command.h"
#include "content/common/input/input_event_ack_state.h"
-#include "content/common/input/input_event_utils.h"
#include "content/common/input/touch_action.h"
#include "content/common/input/web_touch_event_traits.h"
#include "content/common/input_messages.h"
@@ -84,9 +83,7 @@ InputRouterImpl::InputRouterImpl(IPC::Sender* sender,
flush_requested_(false),
active_renderer_fling_count_(0),
touch_scroll_started_sent_(false),
- wheel_event_queue_(this,
- UseGestureBasedWheelScrolling(),
- kDefaultWheelScrollTransactionMs),
+ wheel_event_queue_(this, kDefaultWheelScrollTransactionMs),
touch_event_queue_(this, config.touch_config),
gesture_event_queue_(this, this, config.gesture_config),
device_scale_factor_(1.f) {
@@ -431,6 +428,12 @@ bool InputRouterImpl::OfferToClient(const WebInputEvent& input_event,
bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
const ui::LatencyInfo& latency_info,
InputEventDispatchType dispatch_type) {
+ DCHECK(input_event.type != blink::WebInputEvent::GestureFlingStart ||
+ static_cast<const blink::WebGestureEvent&>(input_event)
+ .data.flingStart.velocityX != 0.0 ||
+ static_cast<const blink::WebGestureEvent&>(input_event)
+ .data.flingStart.velocityY != 0.0);
+
// This conversion is temporary. WebInputEvent should be generated
// directly from ui::Event with the viewport coordinates. See
// crbug.com/563730.
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 5903b6649bd..304bd053d2c 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
@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/run_loop.h"
#include "content/browser/renderer_host/input/input_ack_handler.h"
#include "content/browser/renderer_host/input/input_router_client.h"
#include "content/browser/renderer_host/input/input_router_impl.h"
@@ -223,7 +224,7 @@ class InputRouterImplPerfTest : public testing::Test {
}
void TearDown() override {
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
input_router_.reset();
ack_handler_.reset();
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 d8ce0648722..105b02e6a79 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
@@ -9,10 +9,12 @@
#include <stdint.h>
#include <memory>
+#include <tuple>
#include "base/command_line.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -39,7 +41,6 @@
#include "ui/events/event.h"
#endif
-using base::TimeDelta;
using blink::WebGestureDevice;
using blink::WebGestureEvent;
using blink::WebKeyboardEvent;
@@ -90,7 +91,7 @@ void ExpectIPCMessageWithArg1(const IPC::Message* msg, const ARG_T1& arg1) {
ASSERT_EQ(MSG_T::ID, msg->type());
typename MSG_T::Schema::Param param;
ASSERT_TRUE(MSG_T::Read(msg, &param));
- EXPECT_EQ(arg1, base::get<0>(param));
+ EXPECT_EQ(arg1, std::get<0>(param));
}
template<typename MSG_T, typename ARG_T1, typename ARG_T2>
@@ -100,8 +101,8 @@ void ExpectIPCMessageWithArg2(const IPC::Message* msg,
ASSERT_EQ(MSG_T::ID, msg->type());
typename MSG_T::Schema::Param param;
ASSERT_TRUE(MSG_T::Read(msg, &param));
- EXPECT_EQ(arg1, base::get<0>(param));
- EXPECT_EQ(arg2, base::get<1>(param));
+ EXPECT_EQ(arg1, std::get<0>(param));
+ EXPECT_EQ(arg2, std::get<1>(param));
}
#if defined(USE_AURA)
@@ -113,7 +114,7 @@ bool TouchEventsAreEquivalent(const ui::TouchEvent& first,
return false;
if (first.touch_id() != second.touch_id())
return false;
- if (second.time_stamp().InSeconds() != first.time_stamp().InSeconds())
+ if (second.time_stamp() != first.time_stamp())
return false;
return true;
}
@@ -161,7 +162,7 @@ class InputRouterImplTest : public testing::Test {
void TearDown() override {
// Process all pending tasks to avoid leaks.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
input_router_.reset();
client_.reset();
@@ -169,18 +170,6 @@ class InputRouterImplTest : public testing::Test {
browser_context_.reset();
}
- void SetUpForGestureBasedWheelScrolling(bool enabled) {
- CHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableWheelGestures) &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableWheelGestures));
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- enabled ? switches::kEnableWheelGestures
- : switches::kDisableWheelGestures);
- TearDown();
- SetUp();
- }
-
void SetUpForTouchAckTimeoutTest(int desktop_timeout_ms,
int mobile_timeout_ms) {
config_.touch_config.desktop_touch_ack_timeout_delay =
@@ -265,7 +254,7 @@ class InputRouterImplTest : public testing::Test {
velocity_x, velocity_y, source_device));
}
- void SetTouchTimestamp(base::TimeDelta timestamp) {
+ void SetTouchTimestamp(base::TimeTicks timestamp) {
touch_event_.SetTimestamp(timestamp);
}
@@ -730,7 +719,7 @@ TEST_F(InputRouterImplTest, CoalescesWheelEvents) {
// The coalesced events can queue up a delayed ack
// so that additional input events can be processed before
// we turn off coalescing.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -744,7 +733,7 @@ TEST_F(InputRouterImplTest, CoalescesWheelEvents) {
// Ack the second event (which had the third coalesced into it).
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID));
@@ -758,7 +747,7 @@ TEST_F(InputRouterImplTest, CoalescesWheelEvents) {
// Ack the fourth event.
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
EXPECT_TRUE(
process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
@@ -771,7 +760,7 @@ TEST_F(InputRouterImplTest, CoalescesWheelEvents) {
// Ack the fifth event.
SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
EXPECT_TRUE(
process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
@@ -785,7 +774,7 @@ TEST_F(InputRouterImplTest, CoalescesWheelEvents) {
// After the final ack, the queue should be empty.
SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
}
@@ -869,7 +858,7 @@ TEST_F(InputRouterImplTest, AckedTouchEventState) {
// Use a custom timestamp for all the events to test that the acked events
// have the same timestamp;
- base::TimeDelta timestamp = base::Time::NowFromSystemTime() - base::Time();
+ base::TimeTicks timestamp = base::TimeTicks::Now();
timestamp -= base::TimeDelta::FromSeconds(600);
// Press the first finger.
@@ -946,44 +935,6 @@ TEST_F(InputRouterImplTest, AckedTouchEventState) {
#endif // defined(USE_AURA)
TEST_F(InputRouterImplTest, UnhandledWheelEvent) {
- SetUpForGestureBasedWheelScrolling(false);
-
- // Simulate wheel events.
- SimulateWheelEvent(0, 0, 0, -5, 0, false); // sent directly
- SimulateWheelEvent(0, 0, 0, -10, 0, false); // enqueued
-
- // Check that only the first event was sent.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Indicate that the wheel event was unhandled.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Check that the correct unhandled wheel event was received.
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_handler_->ack_state());
- EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -5);
-
- // Check that the second event was sent.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Indicate that the wheel event was unhandled.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Check that the correct unhandled wheel event was received.
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_handler_->ack_state());
- EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -10);
-}
-
-TEST_F(InputRouterImplTest, UnhandledWheelEventWithGestureScrolling) {
- SetUpForGestureBasedWheelScrolling(true);
-
// Simulate wheel events.
SimulateWheelEvent(0, 0, 0, -5, 0, false); // sent directly
SimulateWheelEvent(0, 0, 0, -10, 0, false); // enqueued
@@ -1925,7 +1876,7 @@ class InputRouterImplScaleEventTest : public InputRouterImplTest {
InputMsg_HandleInputEvent::Schema::Param param;
InputMsg_HandleInputEvent::Read(process_->sink().GetMessageAt(0), &param);
- return static_cast<const T*>(base::get<0>(param));
+ return static_cast<const T*>(std::get<0>(param));
}
template <typename T>
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 972f82110d7..95f0fc7721a 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
@@ -33,12 +33,10 @@ class QueuedWebMouseWheelEvent : public MouseWheelEventWithLatencyInfo {
};
MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client,
- bool send_gestures,
int64_t scroll_transaction_ms)
: client_(client),
needs_scroll_begin_(true),
needs_scroll_end_(false),
- send_gestures_(send_gestures),
scroll_transaction_ms_(scroll_transaction_ms),
scrolling_device_(blink::WebGestureDeviceUninitialized) {
DCHECK(client);
@@ -81,8 +79,8 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
client_->OnMouseWheelEventAck(*event_sent_for_gesture_ack_, ack_result);
// If event wasn't consumed then generate a gesture scroll for it.
- if (send_gestures_ && ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
- event_sent_for_gesture_ack_->event.canScroll &&
+ if (ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
+ WebInputEventTraits::CanCauseScroll(event_sent_for_gesture_ack_->event) &&
event_sent_for_gesture_ack_->event.resendingPluginId == -1 &&
(scrolling_device_ == blink::WebGestureDeviceUninitialized ||
scrolling_device_ == blink::WebGestureDeviceTouchpad)) {
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 1b7a5f36f2d..a2722310b74 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
@@ -47,7 +47,6 @@ class CONTENT_EXPORT MouseWheelEventQueue {
// |scroll_transaction_ms| is the duration in which the
// ScrollEnd should be sent after a ScrollUpdate.
MouseWheelEventQueue(MouseWheelEventQueueClient* client,
- bool send_gestures,
int64_t scroll_transaction_ms);
~MouseWheelEventQueue();
@@ -98,7 +97,6 @@ class CONTENT_EXPORT MouseWheelEventQueue {
// GSB has been sent in the past.
bool needs_scroll_end_;
- bool send_gestures_;
int64_t scroll_transaction_ms_;
blink::WebGestureDevice scrolling_device_;
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 e799eeb8b06..ace5eb4cb62 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
@@ -145,7 +145,7 @@ class MouseWheelEventQueueTest : public testing::Test,
MouseWheelEventQueueTest()
: acked_event_count_(0),
last_acked_event_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {
- SetUpForGestureTesting(false);
+ queue_.reset(new MouseWheelEventQueue(this, kScrollEndTimeoutMs));
}
~MouseWheelEventQueueTest() override {}
@@ -176,11 +176,6 @@ class MouseWheelEventQueueTest : public testing::Test,
}
protected:
- void SetUpForGestureTesting(bool send_gestures) {
- queue_.reset(
- new MouseWheelEventQueue(this, send_gestures, kScrollEndTimeoutMs));
- }
-
size_t queued_event_count() const { return queue_->queued_size(); }
bool event_in_flight() const { return queue_->event_in_flight(); }
@@ -435,28 +430,23 @@ TEST_F(MouseWheelEventQueueTest, Basic) {
}
TEST_F(MouseWheelEventQueueTest, GestureSending) {
- SetUpForGestureTesting(true);
GestureSendingTest(false);
}
TEST_F(MouseWheelEventQueueTest, GestureSendingPrecisePixels) {
- SetUpForGestureTesting(true);
GestureSendingTest(false);
}
TEST_F(MouseWheelEventQueueTest, GestureSendingWithPhaseInformation) {
- SetUpForGestureTesting(true);
PhaseGestureSendingTest(false);
}
TEST_F(MouseWheelEventQueueTest,
GestureSendingWithPhaseInformationPrecisePixels) {
- SetUpForGestureTesting(true);
PhaseGestureSendingTest(true);
}
TEST_F(MouseWheelEventQueueTest, GestureSendingInterrupted) {
- SetUpForGestureTesting(true);
const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::Pixels;
SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
@@ -519,7 +509,6 @@ TEST_F(MouseWheelEventQueueTest, GestureSendingInterrupted) {
}
TEST_F(MouseWheelEventQueueTest, GestureRailScrolling) {
- SetUpForGestureTesting(true);
const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::Pixels;
SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
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 87139601ed3..858a53a341e 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
@@ -109,18 +109,10 @@ class NonBlockingEventBrowserTest : public ContentBrowserTest {
main_thread_sync.Wait();
}
- // ContentBrowserTest:
- void SetUpCommandLine(base::CommandLine* cmd) override {
- // TODO(dtapuska): Remove this switch once wheel-gestures ships.
- cmd->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures);
- cmd->AppendSwitch(switches::kEnableWheelGestures);
- }
-
int ExecuteScriptAndExtractInt(const std::string& script) {
int value = 0;
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(), "domAutomationController.send(" + script + ")",
- &value));
+ shell(), "domAutomationController.send(" + script + ")", &value));
return value;
}
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 b0ba89f77e5..3f04887fb1f 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
@@ -25,9 +25,8 @@ void UpdateLatencyCoordinatesImpl(const blink::WebTouchEvent& touch,
LatencyInfo* latency,
float device_scale_factor) {
for (uint32_t i = 0; i < touch.touchesLength; ++i) {
- LatencyInfo::InputCoordinate coordinate(
- touch.touches[i].position.x * device_scale_factor,
- touch.touches[i].position.y * device_scale_factor);
+ gfx::PointF coordinate(touch.touches[i].position.x * device_scale_factor,
+ touch.touches[i].position.y * device_scale_factor);
if (!latency->AddInputCoordinate(coordinate))
break;
}
@@ -36,25 +35,22 @@ void UpdateLatencyCoordinatesImpl(const blink::WebTouchEvent& touch,
void UpdateLatencyCoordinatesImpl(const WebGestureEvent& gesture,
LatencyInfo* latency,
float device_scale_factor) {
- latency->AddInputCoordinate(
- LatencyInfo::InputCoordinate(gesture.x * device_scale_factor,
- gesture.y * device_scale_factor));
+ latency->AddInputCoordinate(gfx::PointF(gesture.x * device_scale_factor,
+ gesture.y * device_scale_factor));
}
void UpdateLatencyCoordinatesImpl(const WebMouseEvent& mouse,
LatencyInfo* latency,
float device_scale_factor) {
- latency->AddInputCoordinate(
- LatencyInfo::InputCoordinate(mouse.x * device_scale_factor,
- mouse.y * device_scale_factor));
+ latency->AddInputCoordinate(gfx::PointF(mouse.x * device_scale_factor,
+ mouse.y * device_scale_factor));
}
void UpdateLatencyCoordinatesImpl(const WebMouseWheelEvent& wheel,
LatencyInfo* latency,
float device_scale_factor) {
- latency->AddInputCoordinate(
- LatencyInfo::InputCoordinate(wheel.x * device_scale_factor,
- wheel.y * device_scale_factor));
+ latency->AddInputCoordinate(gfx::PointF(wheel.x * device_scale_factor,
+ wheel.y * device_scale_factor));
}
void UpdateLatencyCoordinates(const WebInputEvent& event,
@@ -75,66 +71,6 @@ void UpdateLatencyCoordinates(const WebInputEvent& event,
}
}
-void ComputeInputLatencyHistograms(WebInputEvent::Type type,
- int64_t latency_component_id,
- const LatencyInfo& latency) {
- if (latency.coalesced())
- return;
-
- LatencyInfo::LatencyComponent rwh_component;
- if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- latency_component_id, &rwh_component)) {
- return;
- }
- DCHECK_EQ(rwh_component.event_count, 1u);
-
- LatencyInfo::LatencyComponent ui_component;
- if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0,
- &ui_component)) {
- DCHECK_EQ(ui_component.event_count, 1u);
- base::TimeDelta ui_delta =
- rwh_component.event_time - ui_component.event_time;
- switch (type) {
- case blink::WebInputEvent::MouseWheel:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.Browser.WheelUI",
- ui_delta.InMicroseconds(), 1, 20000, 100);
- break;
- case blink::WebInputEvent::TouchTypeFirst:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.Browser.TouchUI",
- ui_delta.InMicroseconds(), 1, 20000, 100);
- break;
- default:
- NOTREACHED();
- break;
- }
- }
-
- LatencyInfo::LatencyComponent acked_component;
- if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
- &acked_component)) {
- DCHECK_EQ(acked_component.event_count, 1u);
- base::TimeDelta acked_delta =
- acked_component.event_time - rwh_component.event_time;
- switch (type) {
- case blink::WebInputEvent::MouseWheel:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.Browser.WheelAcked",
- acked_delta.InMicroseconds(), 1, 1000000, 100);
- break;
- case blink::WebInputEvent::TouchTypeFirst:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.Browser.TouchAcked",
- acked_delta.InMicroseconds(), 1, 1000000, 100);
- break;
- default:
- NOTREACHED();
- break;
- }
- }
-}
-
// Touch to scroll latency that is mostly under 1 second.
#define UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY(name, start, end) \
UMA_HISTOGRAM_CUSTOM_COUNTS( \
@@ -287,11 +223,11 @@ RenderWidgetHostLatencyTracker::RenderWidgetHostLatencyTracker()
: last_event_id_(0),
latency_component_id_(0),
device_scale_factor_(1),
- has_seen_first_gesture_scroll_update_(false) {
-}
+ has_seen_first_gesture_scroll_update_(false),
+ multi_finger_gesture_(false),
+ touch_start_default_prevented_(false) {}
-RenderWidgetHostLatencyTracker::~RenderWidgetHostLatencyTracker() {
-}
+RenderWidgetHostLatencyTracker::~RenderWidgetHostLatencyTracker() {}
void RenderWidgetHostLatencyTracker::Initialize(int routing_id,
int process_id) {
@@ -301,6 +237,164 @@ void RenderWidgetHostLatencyTracker::Initialize(int routing_id,
latency_component_id_ = routing_id | last_event_id_;
}
+void RenderWidgetHostLatencyTracker::ComputeInputLatencyHistograms(
+ WebInputEvent::Type type,
+ int64_t latency_component_id,
+ const LatencyInfo& latency,
+ InputEventAckState ack_result) {
+ if (latency.coalesced())
+ return;
+
+ LatencyInfo::LatencyComponent rwh_component;
+ if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ latency_component_id, &rwh_component)) {
+ return;
+ }
+ DCHECK_EQ(rwh_component.event_count, 1u);
+
+ LatencyInfo::LatencyComponent ui_component;
+ if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0,
+ &ui_component)) {
+ DCHECK_EQ(ui_component.event_count, 1u);
+ base::TimeDelta ui_delta =
+ rwh_component.event_time - ui_component.event_time;
+
+ if (type == blink::WebInputEvent::MouseWheel) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.WheelUI",
+ ui_delta.InMicroseconds(), 1, 20000, 100);
+
+ } else {
+ DCHECK(WebInputEvent::isTouchEventType(type));
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.TouchUI",
+ ui_delta.InMicroseconds(), 1, 20000, 100);
+ }
+ }
+
+ // Both tap and scroll gestures depend on the disposition of the touch start
+ // and the current touch. For touch start, touch_start_default_prevented_ ==
+ // (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED).
+ bool action_prevented = touch_start_default_prevented_ ||
+ ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
+
+ LatencyInfo::LatencyComponent main_component;
+ if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
+ &main_component)) {
+ DCHECK_EQ(main_component.event_count, 1u);
+ base::TimeDelta queueing_delta =
+ main_component.event_time - rwh_component.event_time;
+
+ if (!multi_finger_gesture_) {
+ if (action_prevented) {
+ switch (type) {
+ case WebInputEvent::TouchStart:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.QueueingTime.TouchStartDefaultPrevented",
+ queueing_delta);
+ break;
+ case WebInputEvent::TouchMove:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.QueueingTime.TouchMoveDefaultPrevented",
+ queueing_delta);
+ break;
+ case WebInputEvent::TouchEnd:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.QueueingTime.TouchEndDefaultPrevented",
+ queueing_delta);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (type) {
+ case WebInputEvent::TouchStart:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.QueueingTime.TouchStartDefaultAllowed",
+ queueing_delta);
+ break;
+ case WebInputEvent::TouchMove:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.QueueingTime.TouchMoveDefaultAllowed",
+ queueing_delta);
+ break;
+ case WebInputEvent::TouchEnd:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.QueueingTime.TouchEndDefaultAllowed",
+ queueing_delta);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ LatencyInfo::LatencyComponent acked_component;
+ if (latency.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
+ &acked_component)) {
+ DCHECK_EQ(acked_component.event_count, 1u);
+ base::TimeDelta acked_delta =
+ acked_component.event_time - rwh_component.event_time;
+ if (type == blink::WebInputEvent::MouseWheel) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.WheelAcked",
+ acked_delta.InMicroseconds(), 1, 1000000,
+ 100);
+ } else {
+ DCHECK(WebInputEvent::isTouchEventType(type));
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser.TouchAcked",
+ acked_delta.InMicroseconds(), 1, 1000000,
+ 100);
+ }
+
+ if (!multi_finger_gesture_ &&
+ main_component.event_time != base::TimeTicks()) {
+ base::TimeDelta blocking_delta;
+ blocking_delta = acked_component.event_time - main_component.event_time;
+
+ if (action_prevented) {
+ switch (type) {
+ case WebInputEvent::TouchStart:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.BlockingTime.TouchStartDefaultPrevented",
+ blocking_delta);
+ break;
+ case WebInputEvent::TouchMove:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.BlockingTime.TouchMoveDefaultPrevented",
+ blocking_delta);
+ break;
+ case WebInputEvent::TouchEnd:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.BlockingTime.TouchEndDefaultPrevented",
+ blocking_delta);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (type) {
+ case WebInputEvent::TouchStart:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.BlockingTime.TouchStartDefaultAllowed",
+ blocking_delta);
+ break;
+ case WebInputEvent::TouchMove:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.BlockingTime.TouchMoveDefaultAllowed",
+ blocking_delta);
+ break;
+ case WebInputEvent::TouchEnd:
+ UMA_HISTOGRAM_TIMES(
+ "Event.Latency.BlockingTime.TouchEndDefaultAllowed",
+ blocking_delta);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
+
void RenderWidgetHostLatencyTracker::OnInputEvent(
const blink::WebInputEvent& event,
LatencyInfo* latency) {
@@ -362,7 +456,7 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
void RenderWidgetHostLatencyTracker::OnInputEventAck(
const blink::WebInputEvent& event,
- LatencyInfo* latency) {
+ LatencyInfo* latency, InputEventAckState ack_result) {
DCHECK(latency);
// Latency ends when it is acked but does not cause render scheduling.
@@ -381,13 +475,23 @@ void RenderWidgetHostLatencyTracker::OnInputEventAck(
}
if (WebInputEvent::isTouchEventType(event.type)) {
+ const WebTouchEvent& touch_event =
+ *static_cast<const WebTouchEvent*>(&event);
+ if (event.type == WebInputEvent::TouchStart) {
+ DCHECK(touch_event.touchesLength >= 1);
+ multi_finger_gesture_ = touch_event.touchesLength != 1;
+ touch_start_default_prevented_ =
+ ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
+ }
+
latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0);
+
if (!rendering_scheduled) {
latency->AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, 0);
}
- ComputeInputLatencyHistograms(WebInputEvent::TouchTypeFirst,
- latency_component_id_, *latency);
+ ComputeInputLatencyHistograms(event.type, latency_component_id_, *latency,
+ ack_result);
return;
}
@@ -397,8 +501,8 @@ void RenderWidgetHostLatencyTracker::OnInputEventAck(
latency->AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_WHEEL_COMPONENT, 0, 0);
}
- ComputeInputLatencyHistograms(WebInputEvent::MouseWheel,
- latency_component_id_, *latency);
+ ComputeInputLatencyHistograms(event.type, latency_component_id_, *latency,
+ ack_result);
return;
}
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
index 633e4e878da..f86d628d953 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/content_export.h"
+#include "content/common/input/input_event_ack_state.h"
#include "ui/events/latency_info.h"
namespace content {
@@ -27,6 +28,11 @@ class CONTENT_EXPORT RenderWidgetHostLatencyTracker {
// Called once after the RenderWidgetHost is fully initialized.
void Initialize(int routing_id, int process_id);
+ void ComputeInputLatencyHistograms(blink::WebInputEvent::Type type,
+ int64_t latency_component_id,
+ const ui::LatencyInfo& latency,
+ InputEventAckState ack_result);
+
// Populates the LatencyInfo with relevant entries for latency tracking.
// Called when an event is received by the RenderWidgetHost, prior to
// that event being forwarded to the renderer (via the InputRouter).
@@ -38,7 +44,8 @@ class CONTENT_EXPORT RenderWidgetHostLatencyTracker {
// performing relevant UMA latency reporting. Called when an event is ack'ed
// to the RenderWidgetHost (from the InputRouter).
void OnInputEventAck(const blink::WebInputEvent& event,
- ui::LatencyInfo* latency);
+ ui::LatencyInfo* latency,
+ InputEventAckState ack_result);
// Populates renderer-created LatencyInfo entries with the appropriate latency
// component id. Called when the RenderWidgetHost receives a compositor swap
@@ -65,6 +72,12 @@ class CONTENT_EXPORT RenderWidgetHostLatencyTracker {
int64_t latency_component_id_;
float device_scale_factor_;
bool has_seen_first_gesture_scroll_update_;
+ // Whether the current stream of touch events has ever included more than one
+ // touch point.
+ bool multi_finger_gesture_;
+ // Whether the touch start for the current stream of touch events had its
+ // default action prevented. Only valid for single finger gestures.
+ bool touch_start_default_prevented_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostLatencyTracker);
};
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
index 9b757dc8858..169a49e0329 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
@@ -6,9 +6,12 @@
#include "content/browser/renderer_host/input/render_widget_host_latency_tracker.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/public/browser/native_web_keyboard_event.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::Bucket;
using blink::WebInputEvent;
+using testing::ElementsAre;
namespace content {
namespace {
@@ -74,6 +77,10 @@ class RenderWidgetHostLatencyTrackerTest : public testing::Test {
histogram_tester_.reset(new base::HistogramTester());
}
+ const base::HistogramTester& histogram_tester() {
+ return *histogram_tester_;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostLatencyTrackerTest);
const int kTestRoutingId = 3;
@@ -100,7 +107,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestHistograms) {
EXPECT_TRUE(scroll_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
EXPECT_EQ(1U, scroll_latency.input_coordinates_size());
- tracker()->OnInputEventAck(scroll, &scroll_latency);
+ tracker()->OnInputEventAck(scroll, &scroll_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
{
@@ -118,7 +126,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestHistograms) {
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);
+ tracker()->OnInputEventAck(wheel, &wheel_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
{
@@ -135,7 +144,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestHistograms) {
EXPECT_TRUE(touch_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
EXPECT_EQ(2U, touch_latency.input_coordinates_size());
- tracker()->OnInputEventAck(touch, &touch_latency);
+ tracker()->OnInputEventAck(touch, &touch_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
tracker()->OnFrameSwapped(touch_latency);
}
@@ -177,7 +187,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
// Don't include the rendering schedule component, since we're testing the
// case where rendering isn't scheduled.
tracker()->OnInputEvent(scroll, &scroll_latency);
- tracker()->OnInputEventAck(scroll, &scroll_latency);
+ tracker()->OnInputEventAck(scroll, &scroll_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_TRUE(scroll_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0, nullptr));
EXPECT_TRUE(scroll_latency.terminated());
@@ -189,7 +200,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
ui::LatencyInfo wheel_latency;
AddFakeComponents(*tracker(), &wheel_latency);
tracker()->OnInputEvent(wheel, &wheel_latency);
- tracker()->OnInputEventAck(wheel, &wheel_latency);
+ tracker()->OnInputEventAck(wheel, &wheel_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_TRUE(wheel_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_WHEEL_COMPONENT, 0, nullptr));
EXPECT_TRUE(wheel_latency.terminated());
@@ -201,7 +213,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
ui::LatencyInfo touch_latency;
AddFakeComponents(*tracker(), &touch_latency);
tracker()->OnInputEvent(touch, &touch_latency);
- tracker()->OnInputEventAck(touch, &touch_latency);
+ tracker()->OnInputEventAck(touch, &touch_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_TRUE(touch_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, nullptr));
EXPECT_TRUE(touch_latency.terminated());
@@ -214,7 +227,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
ui::LatencyInfo mouse_latency;
AddFakeComponents(*tracker(), &mouse_latency);
tracker()->OnInputEvent(mouse_move, &mouse_latency);
- tracker()->OnInputEventAck(mouse_move, &mouse_latency);
+ tracker()->OnInputEventAck(mouse_move, &mouse_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_TRUE(mouse_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, nullptr));
EXPECT_TRUE(mouse_latency.terminated());
@@ -226,7 +240,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
ui::LatencyInfo key_latency;
AddFakeComponents(*tracker(), &key_latency);
tracker()->OnInputEvent(key_event, &key_latency);
- tracker()->OnInputEventAck(key_event, &key_latency);
+ tracker()->OnInputEventAck(key_event, &key_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_TRUE(key_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_KEYBOARD_COMPONENT, 0, nullptr));
EXPECT_TRUE(key_latency.terminated());
@@ -263,8 +278,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
ui::LatencyInfo latency_info;
tracker()->OnInputEvent(event, &latency_info);
EXPECT_EQ(1u, latency_info.input_coordinates_size());
- EXPECT_EQ(100, latency_info.input_coordinates()[0].x);
- EXPECT_EQ(200, latency_info.input_coordinates()[0].y);
+ EXPECT_EQ(100, latency_info.input_coordinates()[0].x());
+ EXPECT_EQ(200, latency_info.input_coordinates()[0].y());
}
{
@@ -274,8 +289,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
ui::LatencyInfo latency_info;
tracker()->OnInputEvent(event, &latency_info);
EXPECT_EQ(1u, latency_info.input_coordinates_size());
- EXPECT_EQ(300, latency_info.input_coordinates()[0].x);
- EXPECT_EQ(400, latency_info.input_coordinates()[0].y);
+ EXPECT_EQ(300, latency_info.input_coordinates()[0].x());
+ EXPECT_EQ(400, latency_info.input_coordinates()[0].y());
}
{
@@ -286,8 +301,8 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
ui::LatencyInfo latency_info;
tracker()->OnInputEvent(event, &latency_info);
EXPECT_EQ(1u, latency_info.input_coordinates_size());
- EXPECT_EQ(500, latency_info.input_coordinates()[0].x);
- EXPECT_EQ(600, latency_info.input_coordinates()[0].y);
+ EXPECT_EQ(500, latency_info.input_coordinates()[0].x());
+ EXPECT_EQ(600, latency_info.input_coordinates()[0].y());
}
{
@@ -298,10 +313,10 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
ui::LatencyInfo latency_info;
tracker()->OnInputEvent(event, &latency_info);
EXPECT_EQ(2u, latency_info.input_coordinates_size());
- EXPECT_EQ(700, latency_info.input_coordinates()[0].x);
- EXPECT_EQ(800, latency_info.input_coordinates()[0].y);
- EXPECT_EQ(900, latency_info.input_coordinates()[1].x);
- EXPECT_EQ(1000, latency_info.input_coordinates()[1].y);
+ EXPECT_EQ(700, latency_info.input_coordinates()[0].x());
+ EXPECT_EQ(800, latency_info.input_coordinates()[0].y());
+ EXPECT_EQ(900, latency_info.input_coordinates()[1].x());
+ EXPECT_EQ(1000, latency_info.input_coordinates()[1].y());
}
{
@@ -364,4 +379,192 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
EXPECT_EQ(3U, scroll_latency.latency_components().size());
}
+TEST_F(RenderWidgetHostLatencyTrackerTest, TouchBlockingAndQueueingTime) {
+ // These numbers are sensitive to where the histogram buckets are.
+ int touchstart_timestamps_ms[] = {11, 25, 35};
+ int touchmove_timestamps_ms[] = {1, 5, 12};
+ int touchend_timestamps_ms[] = {3, 8, 12};
+
+ for (InputEventAckState blocking :
+ {INPUT_EVENT_ACK_STATE_NOT_CONSUMED, INPUT_EVENT_ACK_STATE_CONSUMED}) {
+ SyntheticWebTouchEvent event;
+ {
+ // Touch start.
+ event.PressPoint(1, 1);
+
+ ui::LatencyInfo latency;
+ tracker()->OnInputEvent(event, &latency);
+
+ ui::LatencyInfo fake_latency;
+ fake_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), 0,
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[0]),
+ 1);
+
+ fake_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[1]),
+ 1);
+
+ fake_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[2]),
+ 1);
+
+ // Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
+ // overwriting components.
+ tracker()->ComputeInputLatencyHistograms(
+ event.type, tracker()->latency_component_id(), fake_latency,
+ blocking);
+
+ tracker()->OnInputEventAck(event, &latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ }
+
+ {
+ // Touch move.
+ ui::LatencyInfo latency;
+ event.MovePoint(0, 20, 20);
+ tracker()->OnInputEvent(event, &latency);
+
+ EXPECT_TRUE(latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ EXPECT_TRUE(
+ latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), nullptr));
+
+ EXPECT_EQ(2U, latency.latency_components().size());
+
+ ui::LatencyInfo fake_latency;
+ fake_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), 0,
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(touchmove_timestamps_ms[0]),
+ 1);
+
+ fake_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(touchmove_timestamps_ms[1]),
+ 1);
+
+ fake_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(touchmove_timestamps_ms[2]),
+ 1);
+
+ // Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
+ // overwriting components.
+ tracker()->ComputeInputLatencyHistograms(
+ event.type, tracker()->latency_component_id(), fake_latency,
+ blocking);
+ }
+
+ {
+ // Touch end.
+ ui::LatencyInfo latency;
+ event.ReleasePoint(0);
+ tracker()->OnInputEvent(event, &latency);
+
+ EXPECT_TRUE(latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ EXPECT_TRUE(
+ latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), nullptr));
+
+ EXPECT_EQ(2U, latency.latency_components().size());
+
+ ui::LatencyInfo fake_latency;
+ fake_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), 0,
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(touchend_timestamps_ms[0]),
+ 1);
+
+ fake_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(touchend_timestamps_ms[1]),
+ 1);
+
+ fake_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
+ base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(touchend_timestamps_ms[2]),
+ 1);
+
+ // Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
+ // overwriting components.
+ tracker()->ComputeInputLatencyHistograms(
+ event.type, tracker()->latency_component_id(), fake_latency,
+ blocking);
+ }
+ }
+
+ // Touch start.
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples(
+ "Event.Latency.QueueingTime.TouchStartDefaultPrevented"),
+ ElementsAre(Bucket(
+ touchstart_timestamps_ms[1] - touchstart_timestamps_ms[0], 1)));
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples(
+ "Event.Latency.QueueingTime.TouchStartDefaultAllowed"),
+ ElementsAre(Bucket(
+ touchstart_timestamps_ms[1] - touchstart_timestamps_ms[0], 1)));
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples(
+ "Event.Latency.BlockingTime.TouchStartDefaultPrevented"),
+ ElementsAre(Bucket(
+ touchstart_timestamps_ms[2] - touchstart_timestamps_ms[1], 1)));
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples(
+ "Event.Latency.BlockingTime.TouchStartDefaultAllowed"),
+ ElementsAre(Bucket(
+ touchstart_timestamps_ms[2] - touchstart_timestamps_ms[1], 1)));
+
+ // Touch move.
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Event.Latency.QueueingTime.TouchMoveDefaultPrevented"),
+ ElementsAre(Bucket(
+ touchmove_timestamps_ms[1] - touchmove_timestamps_ms[0], 1)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Event.Latency.QueueingTime.TouchMoveDefaultAllowed"),
+ ElementsAre(Bucket(
+ touchmove_timestamps_ms[1] - touchmove_timestamps_ms[0], 1)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Event.Latency.BlockingTime.TouchMoveDefaultPrevented"),
+ ElementsAre(Bucket(
+ touchmove_timestamps_ms[2] - touchmove_timestamps_ms[1], 1)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Event.Latency.BlockingTime.TouchMoveDefaultAllowed"),
+ ElementsAre(Bucket(
+ touchmove_timestamps_ms[2] - touchmove_timestamps_ms[1], 1)));
+
+ // Touch end.
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Event.Latency.QueueingTime.TouchEndDefaultPrevented"),
+ ElementsAre(Bucket(
+ touchend_timestamps_ms[1] - touchend_timestamps_ms[0], 1)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Event.Latency.QueueingTime.TouchEndDefaultAllowed"),
+ ElementsAre(Bucket(
+ touchend_timestamps_ms[1] - touchend_timestamps_ms[0], 1)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Event.Latency.BlockingTime.TouchEndDefaultPrevented"),
+ ElementsAre(Bucket(
+ touchend_timestamps_ms[2] - touchend_timestamps_ms[1], 1)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Event.Latency.BlockingTime.TouchEndDefaultAllowed"),
+ ElementsAre(Bucket(
+ touchend_timestamps_ms[2] - touchend_timestamps_ms[1], 1)));
+}
+
} // 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 2c4ab954bec..ae377fd8f99 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -120,9 +120,7 @@ class TouchActionBrowserTest : public ContentBrowserTest {
int ExecuteScriptAndExtractInt(const std::string& script) {
int value = 0;
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(" + script + ")",
- &value));
+ shell(), "domAutomationController.send(" + script + ")", &value));
return value;
}
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.cc b/chromium/content/browser/renderer_host/input/touch_emulator.cc
index cdbc77da53e..f09716a68c8 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.cc
@@ -39,6 +39,12 @@ ui::GestureProvider::Config GetEmulatorGestureProviderConfig(
return config;
}
+int ModifiersWithoutMouseButtons(const WebInputEvent& event) {
+ const int all_buttons = WebInputEvent::LeftButtonDown |
+ WebInputEvent::MiddleButtonDown | WebInputEvent::RightButtonDown;
+ return event.modifiers & ~all_buttons;
+}
+
// Time between two consecutive mouse moves, during which second mouse move
// is not converted to touch.
const double kMouseMoveDropIntervalSeconds = 5.f / 1000;
@@ -398,7 +404,7 @@ void TouchEmulator::PinchEnd(const WebGestureEvent& event) {
void TouchEmulator::FillPinchEvent(const WebInputEvent& event) {
pinch_event_.timeStampSeconds = event.timeStampSeconds;
- pinch_event_.modifiers = event.modifiers;
+ pinch_event_.modifiers = ModifiersWithoutMouseButtons(event);
pinch_event_.sourceDevice = blink::WebGestureDeviceTouchscreen;
pinch_event_.x = pinch_anchor_.x();
pinch_event_.y = pinch_anchor_.y();
@@ -407,7 +413,7 @@ void TouchEmulator::FillPinchEvent(const WebInputEvent& event) {
void TouchEmulator::ScrollEnd(const WebGestureEvent& event) {
WebGestureEvent scroll_event;
scroll_event.timeStampSeconds = event.timeStampSeconds;
- scroll_event.modifiers = event.modifiers;
+ scroll_event.modifiers = ModifiersWithoutMouseButtons(event);
scroll_event.sourceDevice = blink::WebGestureDeviceTouchscreen;
scroll_event.type = WebInputEvent::GestureScrollEnd;
client_->ForwardEmulatedGestureEvent(scroll_event);
@@ -430,7 +436,7 @@ void TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) {
NOTREACHED() << "Invalid event for touch emulation: " << mouse_event.type;
}
touch_event_.touchesLength = 1;
- touch_event_.modifiers = mouse_event.modifiers;
+ touch_event_.modifiers = ModifiersWithoutMouseButtons(mouse_event);
WebTouchEventTraits::ResetTypeAndTouchStates(
eventType, mouse_event.timeStampSeconds, &touch_event_);
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
index 173a8cbd269..51580ff447b 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
@@ -63,6 +63,9 @@ class TouchEmulatorTest : public testing::Test,
EXPECT_EQ(1U, event.touchesLength);
EXPECT_EQ(last_mouse_x_, event.touches[0].position.x);
EXPECT_EQ(last_mouse_y_, event.touches[0].position.y);
+ const int all_buttons = WebInputEvent::LeftButtonDown |
+ WebInputEvent::MiddleButtonDown | WebInputEvent::RightButtonDown;
+ EXPECT_EQ(0, event.modifiers & all_buttons);
WebInputEvent::DispatchType expected_dispatch_type =
event.type == WebInputEvent::TouchCancel
? WebInputEvent::EventNonBlocking
@@ -84,7 +87,8 @@ class TouchEmulatorTest : public testing::Test,
}
int modifiers() const {
- return shift_pressed_ ? WebInputEvent::ShiftKey : 0;
+ return (shift_pressed_ ? WebInputEvent::ShiftKey : 0) |
+ (mouse_pressed_ ? WebInputEvent::LeftButtonDown : 0);
}
std::string ExpectedEvents() {
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 b3683590d8e..901d61dfcc6 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
@@ -135,8 +135,8 @@ class TouchSelectionControllerClientAuraTest : public ContentBrowserTest {
bool GetPointInsideText(gfx::PointF* point) {
std::string str;
- if (ExecuteScriptAndExtractString(shell()->web_contents()->GetMainFrame(),
- "get_point_inside_text()", &str)) {
+ if (ExecuteScriptAndExtractString(shell(), "get_point_inside_text()",
+ &str)) {
return JSONToPoint(str, point);
}
return false;
@@ -144,17 +144,14 @@ class TouchSelectionControllerClientAuraTest : public ContentBrowserTest {
bool GetPointInsideTextfield(gfx::PointF* point) {
std::string str;
- if (ExecuteScriptAndExtractString(shell()->web_contents()->GetMainFrame(),
- "get_point_inside_textfield()", &str)) {
+ if (ExecuteScriptAndExtractString(shell(), "get_point_inside_textfield()",
+ &str)) {
return JSONToPoint(str, point);
}
return false;
}
- bool EmptyTextfield() {
- return ExecuteScript(shell()->web_contents()->GetMainFrame(),
- "empty_textfield()");
- }
+ bool EmptyTextfield() { return ExecuteScript(shell(), "empty_textfield()"); }
RenderWidgetHostViewAura* GetRenderWidgetHostViewAura() {
return static_cast<RenderWidgetHostViewAura*>(
@@ -212,9 +209,10 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, BasicSelection) {
gfx::PointF point;
ASSERT_TRUE(GetPointInsideText(&point));
- ui::GestureEvent long_press(
- point.x(), point.y(), 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ ui::GestureEventDetails long_press_details(ui::ET_GESTURE_LONG_PRESS);
+ long_press_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent long_press(point.x(), point.y(), 0, ui::EventTimeForNow(),
+ long_press_details);
rwhva->OnGestureEvent(&long_press);
selection_controller_client()->Wait();
@@ -297,6 +295,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
gfx::PointF point;
ASSERT_TRUE(GetPointInsideTextfield(&point));
ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
+ tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
tap_details.set_tap_count(1);
ui::GestureEvent tap(point.x(), point.y(), 0, ui::EventTimeForNow(),
tap_details);
@@ -328,9 +327,10 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
gfx::PointF point;
ASSERT_TRUE(GetPointInsideText(&point));
- ui::GestureEvent long_press(
- point.x(), point.y(), 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ ui::GestureEventDetails long_press_details(ui::ET_GESTURE_LONG_PRESS);
+ long_press_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent long_press(point.x(), point.y(), 0, ui::EventTimeForNow(),
+ long_press_details);
rwhva->OnGestureEvent(&long_press);
selection_controller_client()->Wait();
@@ -387,9 +387,10 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, HiddenOnScroll) {
gfx::PointF point;
ASSERT_TRUE(GetPointInsideText(&point));
- ui::GestureEvent long_press(
- point.x(), point.y(), 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ ui::GestureEventDetails long_press_details(ui::ET_GESTURE_LONG_PRESS);
+ long_press_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent long_press(point.x(), point.y(), 0, ui::EventTimeForNow(),
+ long_press_details);
rwhva->OnGestureEvent(&long_press);
selection_controller_client()->Wait();
@@ -411,9 +412,11 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, HiddenOnScroll) {
// Start scrolling: touch handles should get hidden, while touch selection is
// still active.
- ui::GestureEvent scroll_begin(
- 10, 10, 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
+ ui::GestureEventDetails scroll_begin_details(ui::ET_GESTURE_SCROLL_BEGIN);
+ scroll_begin_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent scroll_begin(10, 10, 0, ui::EventTimeForNow(),
+ scroll_begin_details);
rwhva->OnGestureEvent(&scroll_begin);
EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
rwhva->selection_controller()->active_status());
@@ -421,9 +424,10 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, HiddenOnScroll) {
EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
// End scrolling: touch handles should re-appear.
- ui::GestureEvent scroll_end(
- 10, 10, 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
+ ui::GestureEventDetails scroll_end_details(ui::ET_GESTURE_SCROLL_END);
+ scroll_end_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent scroll_end(10, 10, 0, ui::EventTimeForNow(),
+ scroll_end_details);
rwhva->OnGestureEvent(&scroll_end);
EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
rwhva->selection_controller()->active_status());
@@ -458,9 +462,10 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
gfx::PointF point;
ASSERT_TRUE(GetPointInsideText(&point));
- ui::GestureEvent long_press(
- point.x(), point.y(), 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ ui::GestureEventDetails long_press_details(ui::ET_GESTURE_LONG_PRESS);
+ long_press_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent long_press(point.x(), point.y(), 0, ui::EventTimeForNow(),
+ long_press_details);
rwhva->OnGestureEvent(&long_press);
selection_controller_client()->Wait();
@@ -474,19 +479,25 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
selection_controller_client()->InitWaitForSelectionEvent(
ui::SELECTION_HANDLES_CLEARED);
- ui::GestureEvent scroll_begin(
- 10, 10, 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
+ ui::GestureEventDetails scroll_begin_details(ui::ET_GESTURE_SCROLL_BEGIN);
+ scroll_begin_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent scroll_begin(10, 10, 0, ui::EventTimeForNow(),
+ scroll_begin_details);
rwhva->OnGestureEvent(&scroll_begin);
- ui::GestureEvent scroll_update(
- 210, 10, 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 200, 0));
+ ui::GestureEventDetails scroll_update_details(ui::ET_GESTURE_SCROLL_UPDATE,
+ 200, 0);
+ scroll_update_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent scroll_update(210, 10, 0, ui::EventTimeForNow(),
+ scroll_update_details);
rwhva->OnGestureEvent(&scroll_update);
- ui::GestureEvent scroll_end(
- 210, 10, 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
+ ui::GestureEventDetails scroll_end_details(ui::ET_GESTURE_SCROLL_END);
+ scroll_end_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent scroll_end(210, 10, 0, ui::EventTimeForNow(),
+ scroll_end_details);
rwhva->OnGestureEvent(&scroll_end);
selection_controller_client()->Wait();
@@ -532,9 +543,10 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraScaleFactorTest,
ui::SELECTION_HANDLES_SHOWN);
gfx::PointF point;
ASSERT_TRUE(GetPointInsideText(&point));
- ui::GestureEvent long_press(
- point.x(), point.y(), 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ ui::GestureEventDetails long_press_details(ui::ET_GESTURE_LONG_PRESS);
+ long_press_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent long_press(point.x(), point.y(), 0, ui::EventTimeForNow(),
+ long_press_details);
rwhva->OnGestureEvent(&long_press);
selection_controller_client()->Wait();
@@ -615,6 +627,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraScaleFactorTest,
gfx::PointF point;
ASSERT_TRUE(GetPointInsideTextfield(&point));
ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
+ tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
tap_details.set_tap_count(1);
ui::GestureEvent tap(point.x(), point.y(), 0, ui::EventTimeForNow(),
tap_details);
diff --git a/chromium/content/browser/renderer_host/input/ui_touch_selection_helper.cc b/chromium/content/browser/renderer_host/input/ui_touch_selection_helper.cc
deleted file mode 100644
index c8a68bce23a..00000000000
--- a/chromium/content/browser/renderer_host/input/ui_touch_selection_helper.cc
+++ /dev/null
@@ -1,42 +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/renderer_host/input/ui_touch_selection_helper.h"
-
-#include "base/logging.h"
-#include "cc/output/viewport_selection_bound.h"
-
-namespace content {
-
-namespace {
-
-ui::SelectionBound::Type ConvertSelectionBoundType(
- cc::SelectionBoundType type) {
- switch (type) {
- case cc::SELECTION_BOUND_LEFT:
- return ui::SelectionBound::LEFT;
- case cc::SELECTION_BOUND_RIGHT:
- return ui::SelectionBound::RIGHT;
- case cc::SELECTION_BOUND_CENTER:
- return ui::SelectionBound::CENTER;
- case cc::SELECTION_BOUND_EMPTY:
- return ui::SelectionBound::EMPTY;
- }
- NOTREACHED() << "Unknown selection bound type";
- return ui::SelectionBound::EMPTY;
-}
-
-} // namespace
-
-ui::SelectionBound ConvertSelectionBound(
- const cc::ViewportSelectionBound& bound) {
- ui::SelectionBound ui_bound;
- ui_bound.set_type(ConvertSelectionBoundType(bound.type));
- ui_bound.set_visible(bound.visible);
- if (ui_bound.type() != ui::SelectionBound::EMPTY)
- ui_bound.SetEdge(bound.edge_top, bound.edge_bottom);
- return ui_bound;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/ui_touch_selection_helper.h b/chromium/content/browser/renderer_host/input/ui_touch_selection_helper.h
deleted file mode 100644
index c3660abfc23..00000000000
--- a/chromium/content/browser/renderer_host/input/ui_touch_selection_helper.h
+++ /dev/null
@@ -1,21 +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_RENDERER_HOST_UI_TOUCH_SELECTION_HELPER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_UI_TOUCH_SELECTION_HELPER_H_
-
-#include "ui/base/touch/selection_bound.h"
-
-namespace cc {
-struct ViewportSelectionBound;
-}
-
-namespace content {
-
-ui::SelectionBound ConvertSelectionBound(
- const cc::ViewportSelectionBound& bound);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_UI_TOUCH_SELECTION_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
index 555fecb141d..9b6500a27a5 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
@@ -248,6 +248,133 @@ TEST(WebInputEventBuilderMacTest, SystemKeyEvents) {
EXPECT_TRUE(webEvent.isSystemKey);
}
+// Test generating |windowsKeyCode| from |NSEvent| 'keydown'/'keyup', US
+// keyboard and InputSource.
+TEST(WebInputEventBuilderMacTest, USAlnumNSEventToKeyCode) {
+ struct DomKeyTestCase {
+ int mac_key_code;
+ unichar character;
+ unichar shift_character;
+ ui::KeyboardCode key_code;
+ } table[] = {
+ {kVK_ANSI_0, '0', ')', ui::VKEY_0}, {kVK_ANSI_1, '1', '!', ui::VKEY_1},
+ {kVK_ANSI_2, '2', '@', ui::VKEY_2}, {kVK_ANSI_3, '3', '#', ui::VKEY_3},
+ {kVK_ANSI_4, '4', '$', ui::VKEY_4}, {kVK_ANSI_5, '5', '%', ui::VKEY_5},
+ {kVK_ANSI_6, '6', '^', ui::VKEY_6}, {kVK_ANSI_7, '7', '&', ui::VKEY_7},
+ {kVK_ANSI_8, '8', '*', ui::VKEY_8}, {kVK_ANSI_9, '9', '(', ui::VKEY_9},
+ {kVK_ANSI_A, 'a', 'A', ui::VKEY_A}, {kVK_ANSI_B, 'b', 'B', ui::VKEY_B},
+ {kVK_ANSI_C, 'c', 'C', ui::VKEY_C}, {kVK_ANSI_D, 'd', 'D', ui::VKEY_D},
+ {kVK_ANSI_E, 'e', 'E', ui::VKEY_E}, {kVK_ANSI_F, 'f', 'F', ui::VKEY_F},
+ {kVK_ANSI_G, 'g', 'G', ui::VKEY_G}, {kVK_ANSI_H, 'h', 'H', ui::VKEY_H},
+ {kVK_ANSI_I, 'i', 'I', ui::VKEY_I}, {kVK_ANSI_J, 'j', 'J', ui::VKEY_J},
+ {kVK_ANSI_K, 'k', 'K', ui::VKEY_K}, {kVK_ANSI_L, 'l', 'L', ui::VKEY_L},
+ {kVK_ANSI_M, 'm', 'M', ui::VKEY_M}, {kVK_ANSI_N, 'n', 'N', ui::VKEY_N},
+ {kVK_ANSI_O, 'o', 'O', ui::VKEY_O}, {kVK_ANSI_P, 'p', 'P', ui::VKEY_P},
+ {kVK_ANSI_Q, 'q', 'Q', ui::VKEY_Q}, {kVK_ANSI_R, 'r', 'R', ui::VKEY_R},
+ {kVK_ANSI_S, 's', 'S', ui::VKEY_S}, {kVK_ANSI_T, 't', 'T', ui::VKEY_T},
+ {kVK_ANSI_U, 'u', 'U', ui::VKEY_U}, {kVK_ANSI_V, 'v', 'V', ui::VKEY_V},
+ {kVK_ANSI_W, 'w', 'W', ui::VKEY_W}, {kVK_ANSI_X, 'x', 'X', ui::VKEY_X},
+ {kVK_ANSI_Y, 'y', 'Y', ui::VKEY_Y}, {kVK_ANSI_Z, 'z', 'Z', ui::VKEY_Z}};
+
+ for (const DomKeyTestCase& entry : table) {
+ // Test without modifiers.
+ NSEvent* mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, entry.character, 0, NSKeyDown);
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, entry.character, 0, NSKeyUp);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ // Test with Shift.
+ mac_event = BuildFakeKeyEvent(entry.mac_key_code, entry.shift_character,
+ NSShiftKeyMask, NSKeyDown);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ mac_event = BuildFakeKeyEvent(entry.mac_key_code, entry.shift_character,
+ NSShiftKeyMask, NSKeyUp);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ }
+}
+
+// Test generating |windowsKeyCode| from |NSEvent| 'keydown'/'keyup', JIS
+// keyboard and InputSource.
+TEST(WebInputEventBuilderMacTest, JISNumNSEventToKeyCode) {
+ struct DomKeyTestCase {
+ int mac_key_code;
+ unichar character;
+ unichar shift_character;
+ ui::KeyboardCode key_code;
+ } table[] = {
+ {kVK_ANSI_0, '0', '0', ui::VKEY_0}, {kVK_ANSI_1, '1', '!', ui::VKEY_1},
+ {kVK_ANSI_2, '2', '\"', ui::VKEY_2}, {kVK_ANSI_3, '3', '#', ui::VKEY_3},
+ {kVK_ANSI_4, '4', '$', ui::VKEY_4}, {kVK_ANSI_5, '5', '%', ui::VKEY_5},
+ {kVK_ANSI_6, '6', '&', ui::VKEY_6}, {kVK_ANSI_7, '7', '\'', ui::VKEY_7},
+ {kVK_ANSI_8, '8', '(', ui::VKEY_8}, {kVK_ANSI_9, '9', ')', ui::VKEY_9}};
+
+ for (const DomKeyTestCase& entry : table) {
+ // Test without modifiers.
+ NSEvent* mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, entry.character, 0, NSKeyDown);
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, entry.character, 0, NSKeyUp);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ // Test with Shift.
+ mac_event = BuildFakeKeyEvent(entry.mac_key_code, entry.shift_character,
+ NSShiftKeyMask, NSKeyDown);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ mac_event = BuildFakeKeyEvent(entry.mac_key_code, entry.shift_character,
+ NSShiftKeyMask, NSKeyUp);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ }
+}
+
+// Test generating |windowsKeyCode| from |NSEvent| 'keydown'/'keyup',
+// US keyboard and Dvorak InputSource.
+TEST(WebInputEventBuilderMacTest, USDvorakAlnumNSEventToKeyCode) {
+ struct DomKeyTestCase {
+ int mac_key_code;
+ unichar character;
+ ui::KeyboardCode key_code;
+ } table[] = {
+ {kVK_ANSI_0, '0', ui::VKEY_0}, {kVK_ANSI_1, '1', ui::VKEY_1},
+ {kVK_ANSI_2, '2', ui::VKEY_2}, {kVK_ANSI_3, '3', ui::VKEY_3},
+ {kVK_ANSI_4, '4', ui::VKEY_4}, {kVK_ANSI_5, '5', ui::VKEY_5},
+ {kVK_ANSI_6, '6', ui::VKEY_6}, {kVK_ANSI_7, '7', ui::VKEY_7},
+ {kVK_ANSI_8, '8', ui::VKEY_8}, {kVK_ANSI_9, '9', ui::VKEY_9},
+ {kVK_ANSI_A, 'a', ui::VKEY_A}, {kVK_ANSI_B, 'x', ui::VKEY_X},
+ {kVK_ANSI_C, 'j', ui::VKEY_J}, {kVK_ANSI_D, 'e', ui::VKEY_E},
+ {kVK_ANSI_E, '.', ui::VKEY_OEM_PERIOD}, {kVK_ANSI_F, 'u', ui::VKEY_U},
+ {kVK_ANSI_G, 'i', ui::VKEY_I}, {kVK_ANSI_H, 'd', ui::VKEY_D},
+ {kVK_ANSI_I, 'c', ui::VKEY_C}, {kVK_ANSI_J, 'h', ui::VKEY_H},
+ {kVK_ANSI_K, 't', ui::VKEY_T}, {kVK_ANSI_L, 'n', ui::VKEY_N},
+ {kVK_ANSI_M, 'm', ui::VKEY_M}, {kVK_ANSI_N, 'b', ui::VKEY_B},
+ {kVK_ANSI_O, 'r', ui::VKEY_R}, {kVK_ANSI_P, 'l', ui::VKEY_L},
+ {kVK_ANSI_Q, '\'', ui::VKEY_OEM_7}, {kVK_ANSI_R, 'p', ui::VKEY_P},
+ {kVK_ANSI_S, 'o', ui::VKEY_O}, {kVK_ANSI_T, 'y', ui::VKEY_Y},
+ {kVK_ANSI_U, 'g', ui::VKEY_G}, {kVK_ANSI_V, 'k', ui::VKEY_K},
+ {kVK_ANSI_W, ',', ui::VKEY_OEM_COMMA}, {kVK_ANSI_X, 'q', ui::VKEY_Q},
+ {kVK_ANSI_Y, 'f', ui::VKEY_F}, {kVK_ANSI_Z, ';', ui::VKEY_OEM_1}};
+
+ for (const DomKeyTestCase& entry : table) {
+ // Test without modifiers.
+ NSEvent* mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, entry.character, 0, NSKeyDown);
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, entry.character, 0, NSKeyUp);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.key_code, web_event.windowsKeyCode);
+ }
+}
+
// Test conversion from key combination with Control to DomKey.
// TODO(chongz): Move DomKey tests for all platforms into one place.
// http://crbug.com/587589
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
index 20dce73ec21..85dac815742 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
@@ -42,7 +42,7 @@ TEST(WebInputEventUtilTest, MotionEventConversion) {
pointer.pressure = 30;
pointer.touch_minor = 35;
pointer.orientation = static_cast<float>(-M_PI / 2);
- pointer.tilt = static_cast<float>(-M_PI / 3);
+ pointer.tilt = static_cast<float>(M_PI / 3);
for (MotionEvent::ToolType tool_type : tool_types) {
pointer.tool_type = tool_type;
MotionEventGeneric event(
@@ -67,7 +67,7 @@ TEST(WebInputEventUtilTest, MotionEventConversion) {
expected_pointer.rotationAngle = 0.f;
expected_pointer.force = pointer.pressure;
if (tool_type == MotionEvent::TOOL_TYPE_STYLUS) {
- expected_pointer.tiltX = -60;
+ expected_pointer.tiltX = 60;
expected_pointer.tiltY = 0;
} else {
expected_pointer.tiltX = 0;
@@ -96,6 +96,7 @@ TEST(WebInputEventUtilTest, ScrollUpdateConversion) {
ui::GestureEventDetails details(ui::ET_GESTURE_SCROLL_UPDATE,
delta.x(),
delta.y());
+ details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
details.mark_previous_scroll_update_in_sequence_prevented();
ui::GestureEventData event(details,
motion_event_id,
@@ -107,7 +108,8 @@ TEST(WebInputEventUtilTest, ScrollUpdateConversion) {
raw_pos.y(),
touch_points,
rect,
- flags);
+ flags,
+ 0U);
blink::WebGestureEvent web_event =
ui::CreateWebGestureEventFromGestureEventData(event);
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 5e1a1a63831..3525ec8c69d 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
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/move.h"
#include "content/common/content_export.h"
#include "media/audio/audio_input_writer.h"
#include "media/base/audio_parameters.h"
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 13b6360f0cc..1cc59fe11e0 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
@@ -81,7 +81,7 @@ struct AudioInputRendererHost::AudioEntry {
// The AudioInputController that manages the audio input stream.
scoped_refptr<media::AudioInputController> controller;
- // The audio input stream ID in the render view.
+ // The audio input stream ID in the RenderFrame.
int stream_id;
// Shared memory for transmission of the audio data. It has
@@ -436,16 +436,18 @@ void AudioInputRendererHost::DoCreateStream(
// entry and construct an AudioInputController.
entry->writer.reset(writer.release());
if (WebContentsMediaCaptureId::IsWebContentsDeviceId(device_id)) {
+ // For MEDIA_DESKTOP_AUDIO_CAPTURE, the source is selected from picker
+ // window, we do not mute the source audio.
+ // For MEDIA_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute
+ // the source audio.
+ // TODO(qiangchen): Analyze audio constraints to make a duplicating or
+ // diverting decision. It would give web developer more flexibility.
entry->controller = media::AudioInputController::CreateForStream(
- audio_manager_->GetTaskRunner(),
- this,
+ audio_manager_->GetTaskRunner(), this,
WebContentsAudioInputStream::Create(
- device_id,
- audio_params,
- audio_manager_->GetWorkerTaskRunner(),
- audio_mirroring_manager_),
- entry->writer.get(),
- user_input_monitor_);
+ device_id, audio_params, audio_manager_->GetWorkerTaskRunner(),
+ audio_mirroring_manager_, type == MEDIA_DESKTOP_AUDIO_CAPTURE),
+ entry->writer.get(), 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);
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 caa326127b6..98817e2127f 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
@@ -233,9 +233,20 @@ bool AudioInputSyncWriter::PushDataToFifo(const AudioBus* data,
bool key_pressed,
uint32_t hardware_delay_bytes) {
if (overflow_buses_.size() == kMaxOverflowBusesSize) {
- const std::string error_message = "AISW: No room in fifo.";
- LOG(ERROR) << error_message;
- AddToNativeLog(error_message);
+ // We use |write_error_count_| for capping number of log messages.
+ // |write_error_count_| also includes socket Send() errors, but those should
+ // be rare.
+ if (write_error_count_ <= 50) {
+ const std::string error_message = "AISW: No room in fifo.";
+ LOG(WARNING) << error_message;
+ AddToNativeLog(error_message);
+ if (write_error_count_ == 50) {
+ const std::string error_message =
+ "AISW: Log cap reached, suppressing further fifo overflow logs.";
+ LOG(WARNING) << error_message;
+ AddToNativeLog(error_message);
+ }
+ }
return false;
}
@@ -321,7 +332,7 @@ bool AudioInputSyncWriter::SignalDataWrittenAndUpdateCounters() {
if (socket_->Send(&current_segment_id_, sizeof(current_segment_id_)) !=
sizeof(current_segment_id_)) {
const std::string error_message = "AISW: No room in socket buffer.";
- LOG(ERROR) << error_message;
+ LOG(WARNING) << error_message;
AddToNativeLog(error_message);
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 0cf02958b07..61647894542 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -109,6 +109,13 @@ void MaybeFixAudioParameters(media::AudioParameters* params) {
*params = media::AudioParameters::UnavailableDeviceParams();
}
+void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time) {
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.OutputDeviceAuthorizationTime",
+ base::TimeTicks::Now() - auth_start_time,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(5000), 50);
+}
+
} // namespace
class AudioRendererHost::AudioEntry
@@ -194,13 +201,12 @@ AudioRendererHost::AudioEntry::~AudioEntry() {}
///////////////////////////////////////////////////////////////////////////////
// AudioRendererHost implementations.
-AudioRendererHost::AudioRendererHost(
- int render_process_id,
- media::AudioManager* audio_manager,
- AudioMirroringManager* mirroring_manager,
- MediaInternals* media_internals,
- MediaStreamManager* media_stream_manager,
- const ResourceContext::SaltCallback& salt_callback)
+AudioRendererHost::AudioRendererHost(int render_process_id,
+ media::AudioManager* audio_manager,
+ AudioMirroringManager* mirroring_manager,
+ MediaInternals* media_internals,
+ MediaStreamManager* media_stream_manager,
+ const std::string& salt)
: BrowserMessageFilter(AudioMsgStart),
render_process_id_(render_process_id),
audio_manager_(audio_manager),
@@ -209,7 +215,7 @@ AudioRendererHost::AudioRendererHost(
media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)),
media_stream_manager_(media_stream_manager),
num_playing_streams_(0),
- salt_callback_(salt_callback),
+ salt_(salt),
max_simultaneous_streams_(0) {
DCHECK(audio_manager_);
DCHECK(media_stream_manager_);
@@ -399,6 +405,8 @@ void AudioRendererHost::OnRequestDeviceAuthorization(
const std::string& device_id,
const url::Origin& security_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const base::TimeTicks auth_start_time = base::TimeTicks::Now();
+
DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization"
<< "(stream_id=" << stream_id
<< ", render_frame_id=" << render_frame_id
@@ -409,6 +417,7 @@ void AudioRendererHost::OnRequestDeviceAuthorization(
return;
if (!IsValidDeviceId(device_id)) {
+ UMALogDeviceAuthorizationTime(auth_start_time);
Send(new AudioMsg_NotifyDeviceAuthorized(
stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
media::AudioParameters::UnavailableDeviceParams(), std::string()));
@@ -433,10 +442,11 @@ void AudioRendererHost::OnRequestDeviceAuthorization(
authorizations_.insert(MakeAuthorizationData(
stream_id, true, info->device.matched_output_device_id));
MaybeFixAudioParameters(&output_params);
+ UMALogDeviceAuthorizationTime(auth_start_time);
// Hash matched device id and pass it to the renderer
Send(new AudioMsg_NotifyDeviceAuthorized(
stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params,
- GetHMACForMediaDeviceID(salt_callback_, security_origin,
+ GetHMACForMediaDeviceID(salt_, security_origin,
info->device.matched_output_device_id)));
return;
}
@@ -447,22 +457,26 @@ void AudioRendererHost::OnRequestDeviceAuthorization(
CheckOutputDeviceAccess(
render_frame_id, device_id, security_origin,
base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id,
- device_id, security_origin));
+ device_id, security_origin, auth_start_time));
}
void AudioRendererHost::OnDeviceAuthorized(int stream_id,
const std::string& device_id,
const url::Origin& security_origin,
+ base::TimeTicks auth_start_time,
bool have_access) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const auto& auth_data = authorizations_.find(stream_id);
// A close request was received while access check was in progress.
- if (auth_data == authorizations_.end())
+ if (auth_data == authorizations_.end()) {
+ UMALogDeviceAuthorizationTime(auth_start_time);
return;
+ }
if (!have_access) {
authorizations_.erase(auth_data);
+ UMALogDeviceAuthorizationTime(auth_start_time);
Send(new AudioMsg_NotifyDeviceAuthorized(
stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
media::AudioParameters::UnavailableDeviceParams(), std::string()));
@@ -480,29 +494,33 @@ void AudioRendererHost::OnDeviceAuthorized(int stream_id,
audio_manager_->GetTaskRunner(), FROM_HERE,
base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_),
base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id,
- true));
+ auth_start_time, true));
} else {
media_stream_manager_->audio_output_device_enumerator()->Enumerate(
base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id,
security_origin,
base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this,
- stream_id)));
+ stream_id, auth_start_time)));
}
}
void AudioRendererHost::OnDeviceIDTranslated(
int stream_id,
+ base::TimeTicks auth_start_time,
bool device_found,
const AudioOutputDeviceInfo& device_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const auto& auth_data = authorizations_.find(stream_id);
// A close request was received while translation was in progress
- if (auth_data == authorizations_.end())
+ if (auth_data == authorizations_.end()) {
+ UMALogDeviceAuthorizationTime(auth_start_time);
return;
+ }
if (!device_found) {
authorizations_.erase(auth_data);
+ UMALogDeviceAuthorizationTime(auth_start_time);
Send(new AudioMsg_NotifyDeviceAuthorized(
stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
media::AudioParameters::UnavailableDeviceParams(), std::string()));
@@ -514,6 +532,7 @@ void AudioRendererHost::OnDeviceIDTranslated(
media::AudioParameters output_params = device_info.output_params;
MaybeFixAudioParameters(&output_params);
+ UMALogDeviceAuthorizationTime(auth_start_time);
Send(new AudioMsg_NotifyDeviceAuthorized(
stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string()));
}
@@ -795,9 +814,8 @@ void AudioRendererHost::TranslateDeviceID(
callback.Run(true, device_info);
return;
}
- } else if (content::DoesMediaDeviceIDMatchHMAC(salt_callback_,
- security_origin, device_id,
- device_info.unique_id)) {
+ } else if (content::DoesMediaDeviceIDMatchHMAC(
+ salt_, security_origin, device_id, device_info.unique_id)) {
callback.Run(true, device_info);
return;
}
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 4f2747be947..3e5374a2477 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
@@ -86,7 +86,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
AudioMirroringManager* mirroring_manager,
MediaInternals* media_internals,
MediaStreamManager* media_stream_manager,
- const ResourceContext::SaltCallback& salt_callback);
+ const std::string& salt);
// Calls |callback| with the list of AudioOutputControllers for this object.
void GetOutputControllers(
@@ -174,10 +174,12 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
void OnDeviceAuthorized(int stream_id,
const std::string& device_id,
const url::Origin& security_origin,
+ base::TimeTicks auth_start_time,
bool have_access);
// Proceed with device authorization after translating device ID.
void OnDeviceIDTranslated(int stream_id,
+ base::TimeTicks auth_start_time,
bool device_found,
const AudioOutputDeviceInfo& device_info);
@@ -255,7 +257,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
base::AtomicRefCount num_playing_streams_;
// Salt required to translate renderer device IDs to raw device unique IDs
- ResourceContext::SaltCallback salt_callback_;
+ std::string salt_;
// Map of device authorizations for streams that are not yet created
// The key is the stream ID, and the value is a pair. The pair's first element
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 467e2be3645..f0b232dc977 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
@@ -66,13 +66,13 @@ class MockAudioRendererHost : public AudioRendererHost {
AudioMirroringManager* mirroring_manager,
MediaInternals* media_internals,
MediaStreamManager* media_stream_manager,
- const ResourceContext::SaltCallback& salt_callback)
+ const std::string& salt)
: AudioRendererHost(kRenderProcessId,
audio_manager,
mirroring_manager,
media_internals,
media_stream_manager,
- salt_callback),
+ salt),
shared_memory_length_(0) {}
// A list of mock methods.
@@ -170,18 +170,12 @@ class MockAudioRendererHost : public AudioRendererHost {
};
namespace {
-std::string ReturnMockSalt() {
- return std::string();
-}
-
-ResourceContext::SaltCallback GetMockSaltCallback() {
- return base::Bind(&ReturnMockSalt);
-}
void WaitForEnumeration(base::RunLoop* loop,
const AudioOutputDeviceEnumeration& e) {
loop->Quit();
}
+
} // namespace
class AudioRendererHostTest : public testing::Test {
@@ -202,10 +196,10 @@ class AudioRendererHostTest : public testing::Test {
base::Bind(&WaitForEnumeration, &run_loop));
run_loop.Run();
- host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_,
- MediaInternals::GetInstance(),
- media_stream_manager_.get(),
- GetMockSaltCallback());
+ host_ =
+ new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_,
+ MediaInternals::GetInstance(),
+ media_stream_manager_.get(), std::string());
// Simulate IPC channel connected.
host_->set_peer_process_for_testing(base::Process::Current());
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 8fa0e0449db..5aa187d8cec 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
@@ -8,6 +8,7 @@
#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"
@@ -20,12 +21,12 @@ namespace content {
MediaStreamDispatcherHost::MediaStreamDispatcherHost(
int render_process_id,
- const ResourceContext::SaltCallback& salt_callback,
+ const std::string& salt,
MediaStreamManager* media_stream_manager,
bool use_fake_ui)
: BrowserMessageFilter(MediaStreamMsgStart),
render_process_id_(render_process_id),
- salt_callback_(salt_callback),
+ salt_(salt),
media_stream_manager_(media_stream_manager),
use_fake_ui_(use_fake_ui),
weak_factory_(this) {}
@@ -167,8 +168,8 @@ void MediaStreamDispatcherHost::OnGenerateStream(
return;
media_stream_manager_->GenerateStream(
- this, render_process_id_, render_frame_id, salt_callback_,
- page_request_id, controls, security_origin, user_gesture);
+ this, render_process_id_, render_frame_id, salt_, page_request_id,
+ controls, security_origin, user_gesture);
}
void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_frame_id,
@@ -203,8 +204,8 @@ void MediaStreamDispatcherHost::OnEnumerateDevices(
return;
media_stream_manager_->EnumerateDevices(
- this, render_process_id_, render_frame_id, salt_callback_,
- page_request_id, type, security_origin);
+ this, render_process_id_, render_frame_id, salt_, page_request_id, type,
+ security_origin);
}
void MediaStreamDispatcherHost::OnCancelEnumerateDevices(
@@ -230,9 +231,9 @@ void MediaStreamDispatcherHost::OnOpenDevice(
if (!MediaStreamManager::IsOriginAllowed(render_process_id_, security_origin))
return;
- media_stream_manager_->OpenDevice(
- this, render_process_id_, render_frame_id, salt_callback_,
- page_request_id, device_id, type, security_origin);
+ media_stream_manager_->OpenDevice(this, render_process_id_, render_frame_id,
+ salt_, page_request_id, device_id, type,
+ security_origin);
}
void MediaStreamDispatcherHost::OnCloseDevice(
@@ -275,7 +276,10 @@ void MediaStreamDispatcherHost::OnCancelDeviceChangeNotifications(
[render_frame_id](const DeviceChangeSubscriberInfo& subscriber_info) {
return subscriber_info.render_frame_id == render_frame_id;
});
- CHECK(it != device_change_subscribers_.end());
+ 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);
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 4d82cc78d1b..53195cc9404 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
@@ -33,7 +33,7 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
public MediaStreamRequester {
public:
MediaStreamDispatcherHost(int render_process_id,
- const ResourceContext::SaltCallback& salt_callback,
+ const std::string& salt,
MediaStreamManager* media_stream_manager,
bool use_fake_ui = false);
@@ -118,7 +118,7 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
bool have_access);
int render_process_id_;
- ResourceContext::SaltCallback salt_callback_;
+ std::string salt_;
MediaStreamManager* media_stream_manager_;
struct DeviceChangeSubscriberInfo {
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 08ceff66ce2..1749674eb21 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
@@ -63,10 +63,10 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
public TestContentBrowserClient {
public:
MockMediaStreamDispatcherHost(
- const ResourceContext::SaltCallback salt_callback,
+ const std::string& salt,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
MediaStreamManager* manager)
- : MediaStreamDispatcherHost(kProcessId, salt_callback, manager, true),
+ : MediaStreamDispatcherHost(kProcessId, salt, manager, true),
task_runner_(task_runner),
current_ipc_(NULL) {}
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 fa521ecb147..8e4c7ca211e 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -177,11 +177,6 @@ std::string GetLogMessageString(MediaStreamType stream_type,
return output_string;
}
-// Needed for MediaStreamManager::GenerateStream below.
-std::string ReturnEmptySalt() {
- return std::string();
-}
-
// Clears the MediaStreamDevice.name from all devices in |devices|.
void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) {
for (content::StreamDeviceInfo& device_info : *devices)
@@ -218,7 +213,7 @@ class MediaStreamManager::DeviceRequest {
bool user_gesture,
MediaStreamRequestType request_type,
const StreamControls& controls,
- const ResourceContext::SaltCallback& salt_callback)
+ const std::string& salt)
: requester(requester),
requesting_process_id(requesting_process_id),
requesting_frame_id(requesting_frame_id),
@@ -227,7 +222,7 @@ class MediaStreamManager::DeviceRequest {
user_gesture(user_gesture),
request_type(request_type),
controls(controls),
- salt_callback(salt_callback),
+ salt(salt),
state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED),
audio_type_(MEDIA_NO_SERVICE),
video_type_(MEDIA_NO_SERVICE),
@@ -346,7 +341,7 @@ class MediaStreamManager::DeviceRequest {
const StreamControls controls;
- ResourceContext::SaltCallback salt_callback;
+ const std::string salt;
StreamDeviceInfoArray devices;
@@ -466,11 +461,11 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
// TODO(perkj): The argument list with NULL parameters to DeviceRequest
// suggests that this is the wrong design. Can this be refactored?
- DeviceRequest* request = new DeviceRequest(
- NULL, render_process_id, render_frame_id, page_request_id,
- security_origin,
- false, // user gesture
- MEDIA_DEVICE_ACCESS, controls, base::Bind(&ReturnEmptySalt));
+ DeviceRequest* request =
+ new DeviceRequest(NULL, render_process_id, render_frame_id,
+ page_request_id, security_origin,
+ false, // user gesture
+ MEDIA_DEVICE_ACCESS, controls, std::string());
const std::string& label = AddRequest(request);
@@ -490,7 +485,7 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
int render_process_id,
int render_frame_id,
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
int page_request_id,
const StreamControls& controls,
const url::Origin& security_origin,
@@ -500,7 +495,7 @@ void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
DeviceRequest* request = new DeviceRequest(
requester, render_process_id, render_frame_id, page_request_id,
- security_origin, user_gesture, MEDIA_GENERATE_STREAM, controls, sc);
+ security_origin, user_gesture, MEDIA_GENERATE_STREAM, controls, salt);
const std::string& label = AddRequest(request);
@@ -685,7 +680,7 @@ std::string MediaStreamManager::EnumerateDevices(
MediaStreamRequester* requester,
int render_process_id,
int render_frame_id,
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
int page_request_id,
MediaStreamType type,
const url::Origin& security_origin) {
@@ -699,7 +694,7 @@ std::string MediaStreamManager::EnumerateDevices(
new DeviceRequest(requester, render_process_id, render_frame_id,
page_request_id, security_origin,
false, // user gesture
- MEDIA_ENUMERATE_DEVICES, StreamControls(), sc);
+ MEDIA_ENUMERATE_DEVICES, StreamControls(), salt);
if (IsAudioInputMediaType(type) || type == MEDIA_DEVICE_AUDIO_OUTPUT)
request->SetAudioType(type);
else if (IsVideoMediaType(type))
@@ -801,7 +796,7 @@ void MediaStreamManager::AudioOutputDevicesEnumerated(
void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
int render_process_id,
int render_frame_id,
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
int page_request_id,
const std::string& device_id,
MediaStreamType type,
@@ -824,7 +819,7 @@ void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
new DeviceRequest(requester, render_process_id, render_frame_id,
page_request_id, security_origin,
false, // user gesture
- MEDIA_OPEN_DEVICE_PEPPER_ONLY, controls, sc);
+ MEDIA_OPEN_DEVICE_PEPPER_ONLY, controls, salt);
const std::string& label = AddRequest(request);
// Post a task and handle the request asynchronously. The reason is that the
@@ -840,7 +835,7 @@ void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
bool MediaStreamManager::TranslateSourceIdToDeviceId(
MediaStreamType stream_type,
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
const url::Origin& security_origin,
const std::string& source_id,
std::string* device_id) const {
@@ -859,7 +854,7 @@ bool MediaStreamManager::TranslateSourceIdToDeviceId(
return false;
for (const StreamDeviceInfo& device_info : cache->devices) {
- if (DoesMediaDeviceIDMatchHMAC(sc, security_origin, source_id,
+ if (DoesMediaDeviceIDMatchHMAC(salt, security_origin, source_id,
device_info.device.id)) {
*device_id = device_info.device.id;
return true;
@@ -902,7 +897,7 @@ void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) {
const DeviceRequest* request = labeled_request.second;
for (const StreamDeviceInfo& device_info : request->devices) {
const std::string source_id = GetHMACForMediaDeviceID(
- request->salt_callback, request->security_origin, device.id);
+ request->salt, request->security_origin, device.id);
if (device_info.device.id == source_id &&
device_info.device.type == device.type) {
session_ids.push_back(device_info.session_id);
@@ -991,20 +986,19 @@ void MediaStreamManager::StartMonitoringOnUIThread() {
// Pick the first valid (translatable) device ID from lists of required
// and optional IDs.
-bool MediaStreamManager::PickDeviceId(
- MediaStreamType type,
- const ResourceContext::SaltCallback& salt_callback,
- const url::Origin& security_origin,
- const TrackControls& controls,
- std::string* device_id) const {
+bool MediaStreamManager::PickDeviceId(MediaStreamType type,
+ const std::string& salt,
+ const url::Origin& security_origin,
+ const TrackControls& controls,
+ std::string* device_id) const {
if (!controls.device_ids.empty()) {
if (controls.device_ids.size() > 1) {
LOG(ERROR) << "Only one required device ID is supported";
return false;
}
const std::string& candidate_id = controls.device_ids[0];
- if (!TranslateSourceIdToDeviceId(type, salt_callback, security_origin,
- candidate_id, device_id)) {
+ if (!TranslateSourceIdToDeviceId(type, salt, security_origin, candidate_id,
+ device_id)) {
LOG(WARNING) << "Invalid mandatory capture ID = " << candidate_id;
return false;
}
@@ -1012,8 +1006,8 @@ bool MediaStreamManager::PickDeviceId(
}
// We don't have a required ID. Look at the alternates.
for (const std::string& candidate_id : controls.alternate_device_ids) {
- if (TranslateSourceIdToDeviceId(type, salt_callback, security_origin,
- candidate_id, device_id)) {
+ if (TranslateSourceIdToDeviceId(type, salt, security_origin, candidate_id,
+ device_id)) {
return true;
} else {
LOG(WARNING) << "Invalid optional capture ID = " << candidate_id;
@@ -1027,13 +1021,11 @@ bool MediaStreamManager::GetRequestedDeviceCaptureId(
MediaStreamType type,
std::string* device_id) const {
if (type == MEDIA_DEVICE_AUDIO_CAPTURE) {
- return PickDeviceId(type, request->salt_callback, request->security_origin,
- request->controls.audio,
- device_id);
+ return PickDeviceId(type, request->salt, request->security_origin,
+ request->controls.audio, device_id);
} else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) {
- return PickDeviceId(type, request->salt_callback, request->security_origin,
- request->controls.video,
- device_id);
+ return PickDeviceId(type, request->salt, request->security_origin,
+ request->controls.video, device_id);
} else {
NOTREACHED();
}
@@ -1046,7 +1038,7 @@ void MediaStreamManager::TranslateDeviceIdToSourceId(
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_callback,
+ device->id = GetHMACForMediaDeviceID(request->salt,
request->security_origin, device->id);
}
}
@@ -1388,9 +1380,8 @@ bool MediaStreamManager::FindExistingRequestedDeviceInfo(
DCHECK(existing_device_info);
DCHECK(existing_request_state);
- std::string source_id =
- GetHMACForMediaDeviceID(new_request.salt_callback,
- new_request.security_origin, new_device_info.id);
+ std::string source_id = GetHMACForMediaDeviceID(
+ new_request.salt, new_request.security_origin, new_device_info.id);
for (const LabeledDeviceRequest& labeled_request : requests_) {
const DeviceRequest* request = labeled_request.second;
@@ -2133,7 +2124,7 @@ void MediaStreamManager::NotifyDeviceChangeSubscribers(MediaStreamType type) {
// static
std::string MediaStreamManager::GetHMACForMediaDeviceID(
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
const url::Origin& security_origin,
const std::string& raw_unique_id) {
DCHECK(!raw_unique_id.empty());
@@ -2145,7 +2136,6 @@ std::string MediaStreamManager::GetHMACForMediaDeviceID(
crypto::HMAC hmac(crypto::HMAC::SHA256);
const size_t digest_length = hmac.DigestLength();
std::vector<uint8_t> digest(digest_length);
- std::string salt = sc.Run();
bool result = hmac.Init(security_origin.Serialize()) &&
hmac.Sign(raw_unique_id + salt, &digest[0], digest.size());
DCHECK(result);
@@ -2154,13 +2144,13 @@ std::string MediaStreamManager::GetHMACForMediaDeviceID(
// static
bool MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
const url::Origin& security_origin,
const std::string& device_guid,
const std::string& raw_unique_id) {
DCHECK(!raw_unique_id.empty());
std::string guid_from_raw_device_id =
- GetHMACForMediaDeviceID(sc, security_origin, raw_unique_id);
+ GetHMACForMediaDeviceID(salt, security_origin, raw_unique_id);
return guid_from_raw_device_id == device_guid;
}
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 d5f220fdf86..0fddf64ace8 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.h
@@ -119,7 +119,7 @@ class CONTENT_EXPORT MediaStreamManager
void GenerateStream(MediaStreamRequester* requester,
int render_process_id,
int render_frame_id,
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
int page_request_id,
const StreamControls& controls,
const url::Origin& security_origin,
@@ -151,7 +151,7 @@ class CONTENT_EXPORT MediaStreamManager
virtual std::string EnumerateDevices(MediaStreamRequester* requester,
int render_process_id,
int render_frame_id,
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
int page_request_id,
MediaStreamType type,
const url::Origin& security_origin);
@@ -162,7 +162,7 @@ class CONTENT_EXPORT MediaStreamManager
void OpenDevice(MediaStreamRequester* requester,
int render_process_id,
int render_frame_id,
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
int page_request_id,
const std::string& device_id,
MediaStreamType type,
@@ -172,7 +172,7 @@ class CONTENT_EXPORT MediaStreamManager
// |source_id|. Returns true if there was a raw device id that matched the
// given |source_id|, false if nothing matched it.
bool TranslateSourceIdToDeviceId(MediaStreamType stream_type,
- const ResourceContext::SaltCallback& rc,
+ const std::string& salt,
const url::Origin& security_origin,
const std::string& source_id,
std::string* device_id) const;
@@ -242,18 +242,16 @@ class CONTENT_EXPORT MediaStreamManager
// Generates a hash of a device's unique ID usable by one
// particular security origin.
- static std::string GetHMACForMediaDeviceID(
- const ResourceContext::SaltCallback& sc,
- const url::Origin& security_origin,
- const std::string& raw_unique_id);
+ static std::string GetHMACForMediaDeviceID(const std::string& salt,
+ const url::Origin& security_origin,
+ const std::string& raw_unique_id);
// Convenience method to check if |device_guid| is an HMAC of
// |raw_device_id| for |security_origin|.
- static bool DoesMediaDeviceIDMatchHMAC(
- const ResourceContext::SaltCallback& sc,
- const url::Origin& security_origin,
- const std::string& device_guid,
- const std::string& raw_unique_id);
+ static bool DoesMediaDeviceIDMatchHMAC(const std::string& salt,
+ const url::Origin& security_origin,
+ const std::string& device_guid,
+ const std::string& raw_unique_id);
// Returns true if the renderer process identified with |render_process_id|
// is allowed to access |origin|.
@@ -405,7 +403,7 @@ class CONTENT_EXPORT MediaStreamManager
// Returns false if the required device ID is present and invalid.
// Otherwise, if no valid device is found, device_id is unchanged.
bool PickDeviceId(MediaStreamType type,
- const ResourceContext::SaltCallback& salt_callback,
+ const std::string& salt,
const url::Origin& security_origin,
const TrackControls& controls,
std::string* device_id) const;
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 2f207197a2e..b7bc6b89135 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
@@ -60,13 +60,7 @@ typedef media::FakeAudioManager AudioManagerPlatform;
namespace {
-std::string ReturnMockSalt() {
- return std::string();
-}
-
-ResourceContext::SaltCallback GetMockSaltCallback() {
- return base::Bind(&ReturnMockSalt);
-}
+const char kMockSalt[] = "";
// This class mocks the audio manager and overrides some methods to ensure that
// we can run our tests on the buildbots.
@@ -316,30 +310,28 @@ TEST_F(MediaStreamManagerTest, DeviceID) {
const std::string unique_default_id(
media::AudioDeviceDescription::kDefaultDeviceId);
const std::string hashed_default_id =
- MediaStreamManager::GetHMACForMediaDeviceID(
- GetMockSaltCallback(), security_origin, unique_default_id);
+ MediaStreamManager::GetHMACForMediaDeviceID(kMockSalt, security_origin,
+ unique_default_id);
EXPECT_TRUE(MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
- GetMockSaltCallback(), security_origin, hashed_default_id,
- unique_default_id));
+ kMockSalt, security_origin, hashed_default_id, unique_default_id));
EXPECT_EQ(unique_default_id, hashed_default_id);
const std::string unique_communications_id(
media::AudioDeviceDescription::kCommunicationsDeviceId);
const std::string hashed_communications_id =
- MediaStreamManager::GetHMACForMediaDeviceID(
- GetMockSaltCallback(), security_origin, unique_communications_id);
+ MediaStreamManager::GetHMACForMediaDeviceID(kMockSalt, security_origin,
+ unique_communications_id);
EXPECT_TRUE(MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
- GetMockSaltCallback(), security_origin, hashed_communications_id,
+ kMockSalt, security_origin, hashed_communications_id,
unique_communications_id));
EXPECT_EQ(unique_communications_id, hashed_communications_id);
const std::string unique_other_id("other-unique-id");
const std::string hashed_other_id =
- MediaStreamManager::GetHMACForMediaDeviceID(
- GetMockSaltCallback(), security_origin, unique_other_id);
+ MediaStreamManager::GetHMACForMediaDeviceID(kMockSalt, security_origin,
+ unique_other_id);
EXPECT_TRUE(MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
- GetMockSaltCallback(), security_origin, hashed_other_id,
- unique_other_id));
+ kMockSalt, security_origin, hashed_other_id, unique_other_id));
EXPECT_NE(unique_other_id, hashed_other_id);
EXPECT_EQ(hashed_other_id.size(), 64U);
for (const char& c : hashed_other_id)
@@ -360,7 +352,7 @@ TEST_F(MediaStreamManagerTest, EnumerationOutputDevices) {
EXPECT_CALL(requester,
MockDevicesEnumerated(render_frame_id, page_request_id, _, _));
std::string label = media_stream_manager_->EnumerateDevices(
- &requester, render_process_id, render_frame_id, GetMockSaltCallback(),
+ &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.
@@ -389,7 +381,7 @@ TEST_F(MediaStreamManagerTest, NotifyDeviceChanges) {
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, GetMockSaltCallback(),
+ &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);
@@ -420,7 +412,7 @@ TEST_F(MediaStreamManagerTest, NotifyDeviceChanges) {
EXPECT_CALL(requester,
MockDevicesEnumerated(render_frame_id, page_request_id, _, _));
std::string label = media_stream_manager_->EnumerateDevices(
- &requester, render_process_id, render_frame_id, GetMockSaltCallback(),
+ &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);
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 f10f85ff127..721c87e1db2 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -356,8 +356,7 @@ VideoCaptureController::~VideoCaptureController() {
void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread(
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
- const scoped_refptr<VideoFrame>& frame,
- const base::TimeTicks& timestamp) {
+ const scoped_refptr<VideoFrame>& frame) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const int buffer_id = buffer->id();
DCHECK_NE(buffer_id, VideoCaptureBufferPool::kInvalidId);
@@ -396,10 +395,8 @@ void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread(
if (is_new_buffer)
DoNewBufferOnIOThread(client, buffer.get(), frame);
- client->event_handler->OnBufferReady(client->controller_id,
- buffer_id,
- frame,
- timestamp);
+ client->event_handler->OnBufferReady(client->controller_id, buffer_id,
+ frame);
const bool inserted =
client->active_buffers.insert(std::make_pair(buffer_id, frame))
.second;
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 8baca918c99..a9b93206405 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.h
@@ -128,8 +128,7 @@ class CONTENT_EXPORT VideoCaptureController {
// Worker functions on IO thread. Called by the VideoCaptureDeviceClient.
virtual void DoIncomingCapturedVideoFrameOnIOThread(
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp);
+ const scoped_refptr<media::VideoFrame>& frame);
virtual void DoErrorOnIOThread();
virtual void DoLogOnIOThread(const std::string& message);
virtual void DoBufferDestroyedOnIOThread(int buffer_id_to_drop);
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 3285de9c065..0ad2bbb2e18 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
@@ -48,8 +48,7 @@ class CONTENT_EXPORT VideoCaptureControllerEventHandler {
// A buffer has been filled with a captured VideoFrame.
virtual void OnBufferReady(VideoCaptureControllerID id,
int buffer_id,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp) = 0;
+ const scoped_refptr<media::VideoFrame>& frame) = 0;
// The capture session has ended and no more frames will be sent.
virtual void OnEnded(VideoCaptureControllerID 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 814185619ac..3f19667f4fc 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
@@ -78,15 +78,17 @@ class MockVideoCaptureControllerEventHandler
}
void OnBufferReady(VideoCaptureControllerID id,
int buffer_id,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp) override {
- EXPECT_EQ(frame->format(), media::PIXEL_FORMAT_I420);
- DoI420BufferReady(id, frame->coded_size());
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureController::ReturnBuffer,
- base::Unretained(controller_), id, this, buffer_id,
- gpu::SyncToken(), resource_utilization_));
+ const scoped_refptr<media::VideoFrame>& frame) override {
+ EXPECT_EQ(frame->format(), media::PIXEL_FORMAT_I420);
+ base::TimeTicks reference_time;
+ EXPECT_TRUE(frame->metadata()->GetTimeTicks(
+ media::VideoFrameMetadata::REFERENCE_TIME, &reference_time));
+ DoI420BufferReady(id, frame->coded_size());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoCaptureController::ReturnBuffer,
+ base::Unretained(controller_), id, this, buffer_id,
+ gpu::SyncToken(), resource_utilization_));
}
void OnEnded(VideoCaptureControllerID id) override {
DoEnded(id);
@@ -325,8 +327,9 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
media::VideoFrameMetadata::RESOURCE_UTILIZATION));
client_a_->resource_utilization_ = 0.5;
client_b_->resource_utilization_ = -1.0;
- device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame,
- base::TimeTicks());
+ video_frame->metadata()->SetTimeTicks(
+ media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks());
+ device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
@@ -355,8 +358,9 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
media::VideoFrameMetadata::RESOURCE_UTILIZATION));
client_a_->resource_utilization_ = 0.5;
client_b_->resource_utilization_ = 3.14;
- device_->OnIncomingCapturedVideoFrame(std::move(buffer2), video_frame,
- base::TimeTicks());
+ video_frame->metadata()->SetTimeTicks(
+ media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks());
+ device_->OnIncomingCapturedVideoFrame(std::move(buffer2), video_frame);
// The buffer should be delivered to the clients in any order.
{
@@ -410,8 +414,9 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
video_frame = WrapI420Buffer(capture_resolution,
static_cast<uint8_t*>(buffer->data()));
ASSERT_TRUE(video_frame);
- device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame,
- base::TimeTicks());
+ 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(
@@ -459,8 +464,9 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
video_frame = WrapI420Buffer(capture_resolution,
static_cast<uint8_t*>(buffer3->data()));
ASSERT_TRUE(video_frame);
- device_->OnIncomingCapturedVideoFrame(std::move(buffer3), video_frame,
- base::TimeTicks());
+ 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,
@@ -476,8 +482,9 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
video_frame = WrapI420Buffer(capture_resolution,
static_cast<uint8_t*>(buffer4->data()));
ASSERT_TRUE(video_frame);
- device_->OnIncomingCapturedVideoFrame(std::move(buffer4), video_frame,
- base::TimeTicks());
+ 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_,
@@ -524,8 +531,9 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
scoped_refptr<media::VideoFrame> video_frame =
WrapI420Buffer(capture_resolution, static_cast<uint8_t*>(buffer->data()));
ASSERT_TRUE(video_frame);
- device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame,
- base::TimeTicks());
+ video_frame->metadata()->SetTimeTicks(
+ media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks());
+ device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame);
base::RunLoop().RunUntilIdle();
}
@@ -563,8 +571,9 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
WrapI420Buffer(dims, static_cast<uint8_t*>(buffer->data()));
ASSERT_TRUE(video_frame);
device_->OnError(FROM_HERE, "Test Error");
- device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame,
- base::TimeTicks());
+ video_frame->metadata()->SetTimeTicks(
+ media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks());
+ device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame);
EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/renderer_host/media/video_capture_device_client.cc b/chromium/content/browser/renderer_host/media/video_capture_device_client.cc
index cf6ad3a9814..f6f8cba1aa5 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_device_client.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_device_client.cc
@@ -85,7 +85,8 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData(
int length,
const VideoCaptureFormat& frame_format,
int rotation,
- const base::TimeTicks& timestamp) {
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp) {
TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData");
DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage);
@@ -138,7 +139,7 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData(
ReserveI420OutputBuffer(dimensions, output_pixel_storage, &y_plane_data,
&u_plane_data, &v_plane_data));
if (!buffer.get()) {
- DLOG(ERROR) << "Failed to reserve I420 output buffer.";
+ DLOG(WARNING) << "Failed to reserve I420 output buffer.";
return;
}
@@ -225,7 +226,8 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData(
frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG &&
rotation == 0 && !flip) {
external_jpeg_decoder_->DecodeCapturedData(data, length, frame_format,
- timestamp, std::move(buffer));
+ reference_time, timestamp,
+ std::move(buffer));
return;
}
}
@@ -254,7 +256,8 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData(
const VideoCaptureFormat output_format = VideoCaptureFormat(
dimensions, frame_format.frame_rate,
media::PIXEL_FORMAT_I420, output_pixel_storage);
- OnIncomingCapturedBuffer(std::move(buffer), output_format, timestamp);
+ OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time,
+ timestamp);
}
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>
@@ -287,7 +290,8 @@ VideoCaptureDeviceClient::ReserveOutputBuffer(
void VideoCaptureDeviceClient::OnIncomingCapturedBuffer(
std::unique_ptr<Buffer> buffer,
const VideoCaptureFormat& frame_format,
- const base::TimeTicks& timestamp) {
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp) {
// Currently, only I420 pixel format is supported.
DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format);
@@ -302,7 +306,7 @@ void VideoCaptureDeviceClient::OnIncomingCapturedBuffer(
reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kYPlane)),
reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kUPlane)),
reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kVPlane)),
- handle, handle, handle, base::TimeDelta());
+ handle, handle, handle, timestamp);
break;
}
case media::PIXEL_STORAGE_CPU:
@@ -312,29 +316,26 @@ void VideoCaptureDeviceClient::OnIncomingCapturedBuffer(
reinterpret_cast<uint8_t*>(buffer->data()),
VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420,
frame_format.frame_size),
- base::SharedMemory::NULLHandle(), 0u, base::TimeDelta());
+ base::SharedMemory::NULLHandle(), 0u, timestamp);
break;
}
if (!frame)
return;
frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE,
frame_format.frame_rate);
- OnIncomingCapturedVideoFrame(std::move(buffer), frame, timestamp);
+ frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
+ reference_time);
+ OnIncomingCapturedVideoFrame(std::move(buffer), frame);
}
void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
std::unique_ptr<Buffer> buffer,
- const scoped_refptr<VideoFrame>& frame,
- const base::TimeTicks& timestamp) {
+ const scoped_refptr<VideoFrame>& frame) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
+ BrowserThread::IO, FROM_HERE,
base::Bind(
&VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread,
- controller_,
- base::Passed(&buffer),
- frame,
- timestamp));
+ controller_, base::Passed(&buffer), frame));
}
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>
diff --git a/chromium/content/browser/renderer_host/media/video_capture_device_client.h b/chromium/content/browser/renderer_host/media/video_capture_device_client.h
index 46a8d106da1..2d6cccc8b2c 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_device_client.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_device_client.h
@@ -49,18 +49,19 @@ class CONTENT_EXPORT VideoCaptureDeviceClient
int length,
const media::VideoCaptureFormat& frame_format,
int rotation,
- const base::TimeTicks& timestamp) override;
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp) override;
std::unique_ptr<Buffer> ReserveOutputBuffer(
const gfx::Size& dimensions,
media::VideoPixelFormat format,
media::VideoPixelStorage storage) override;
void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer,
const media::VideoCaptureFormat& frame_format,
- const base::TimeTicks& timestamp) override;
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp) override;
void OnIncomingCapturedVideoFrame(
std::unique_ptr<Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp) override;
+ const scoped_refptr<media::VideoFrame>& frame) override;
std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
const gfx::Size& dimensions,
media::VideoPixelFormat format,
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 5d1d3a685d5..c944647d6b9 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
@@ -45,8 +45,7 @@ class MockVideoCaptureController : public VideoCaptureController {
void DoIncomingCapturedVideoFrameOnIOThread(
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp) override {
+ const scoped_refptr<media::VideoFrame>& frame) override {
MockDoIncomingCapturedVideoFrameOnIOThread(frame->coded_size());
}
};
@@ -87,7 +86,7 @@ TEST_F(VideoCaptureDeviceClientTest, Minimal) {
.Times(1);
device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
kFrameFormat, 0 /*clockwise rotation*/,
- base::TimeTicks());
+ base::TimeTicks(), base::TimeDelta());
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(controller_.get());
}
@@ -109,7 +108,7 @@ TEST_F(VideoCaptureDeviceClientTest, FailsSilentlyGivenInvalidFrameFormat) {
.Times(0);
device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
kFrameFormat, 0 /*clockwise rotation*/,
- base::TimeTicks());
+ base::TimeTicks(), base::TimeDelta());
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(controller_.get());
}
@@ -130,10 +129,10 @@ TEST_F(VideoCaptureDeviceClientTest, DropsFrameIfNoBuffer) {
// Pass two frames. The second will be dropped.
device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
kFrameFormat, 0 /*clockwise rotation*/,
- base::TimeTicks());
+ base::TimeTicks(), base::TimeDelta());
device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
kFrameFormat, 0 /*clockwise rotation*/,
- base::TimeTicks());
+ base::TimeTicks(), base::TimeDelta());
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(controller_.get());
}
@@ -178,7 +177,8 @@ TEST_F(VideoCaptureDeviceClientTest, DataCaptureGoodPixelFormats) {
.Times(1);
device_client_->OnIncomingCapturedData(
data, params.requested_format.ImageAllocationSize(),
- params.requested_format, 0 /* clockwise_rotation */, base::TimeTicks());
+ params.requested_format, 0 /* clockwise_rotation */, base::TimeTicks(),
+ base::TimeDelta());
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(controller_.get());
}
@@ -223,7 +223,8 @@ TEST_F(VideoCaptureDeviceClientTest, CheckRotationsAndCrops) {
.WillOnce(SaveArg<0>(&coded_size));
device_client_->OnIncomingCapturedData(
data, params.requested_format.ImageAllocationSize(),
- params.requested_format, size_and_rotation.rotation, base::TimeTicks());
+ params.requested_format, size_and_rotation.rotation, base::TimeTicks(),
+ base::TimeDelta());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(coded_size.width(), size_and_rotation.output_resolution.width());
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 e47dd24a07b..4937c3ad7dc 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
@@ -79,7 +79,8 @@ void VideoCaptureGpuJpegDecoder::DecodeCapturedData(
const uint8_t* data,
size_t in_buffer_size,
const media::VideoCaptureFormat& frame_format,
- const base::TimeTicks& timestamp,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp,
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> out_buffer) {
DCHECK(CalledOnValidThread());
DCHECK(decoder_);
@@ -133,7 +134,7 @@ void VideoCaptureGpuJpegDecoder::DecodeCapturedData(
out_buffer->mapped_size(), // data_size
out_handle, // handle
0, // shared_memory_offset
- base::TimeDelta()); // timestamp
+ timestamp); // timestamp
if (!out_frame) {
base::AutoLock lock(lock_);
decoder_status_ = FAILED;
@@ -143,10 +144,13 @@ void VideoCaptureGpuJpegDecoder::DecodeCapturedData(
out_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE,
frame_format.frame_rate);
+ out_frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
+ reference_time);
+
{
base::AutoLock lock(lock_);
- decode_done_closure_ = base::Bind(
- decode_done_cb_, base::Passed(&out_buffer), out_frame, timestamp);
+ decode_done_closure_ =
+ base::Bind(decode_done_cb_, base::Passed(&out_buffer), out_frame);
}
decoder_->Decode(in_buffer, out_frame);
#else
diff --git a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
index 1650357ac94..85f94f0348f 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
@@ -54,8 +54,7 @@ class CONTENT_EXPORT VideoCaptureGpuJpegDecoder
typedef base::Callback<void(
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>,
- const scoped_refptr<media::VideoFrame>&,
- const base::TimeTicks&)>
+ const scoped_refptr<media::VideoFrame>&)>
DecodeDoneCB;
// |decode_done_cb| is called on the IO thread when decode succeed. This can
@@ -75,7 +74,8 @@ class CONTENT_EXPORT VideoCaptureGpuJpegDecoder
const uint8_t* data,
size_t in_buffer_size,
const media::VideoCaptureFormat& frame_format,
- const base::TimeTicks& timestamp,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp,
std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> out_buffer);
// JpegDecodeAccelerator::Client implementation.
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 46db2279ee5..20e34a2d678 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -91,8 +91,7 @@ void VideoCaptureHost::OnBufferDestroyed(VideoCaptureControllerID controller_id,
void VideoCaptureHost::OnBufferReady(
VideoCaptureControllerID controller_id,
int buffer_id,
- const scoped_refptr<media::VideoFrame>& video_frame,
- const base::TimeTicks& timestamp) {
+ const scoped_refptr<media::VideoFrame>& video_frame) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (entries_.find(controller_id) == entries_.end())
return;
@@ -100,7 +99,7 @@ void VideoCaptureHost::OnBufferReady(
VideoCaptureMsg_BufferReady_Params params;
params.device_id = controller_id;
params.buffer_id = buffer_id;
- params.timestamp = timestamp;
+ params.timestamp = video_frame->timestamp();
video_frame->metadata()->MergeInternalValuesInto(&params.metadata);
params.pixel_format = video_frame->format();
params.storage_type = video_frame->storage_type();
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 800f562e16f..90f1dc939be 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -91,8 +91,7 @@ class CONTENT_EXPORT VideoCaptureHost
int buffer_id) override;
void OnBufferReady(VideoCaptureControllerID id,
int buffer_id,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp) override;
+ const scoped_refptr<media::VideoFrame>& frame) override;
void OnEnded(VideoCaptureControllerID id) override;
private:
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 5ae03ca10f6..7ddfe507b9b 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -144,13 +144,13 @@ class VideoCaptureManager::DeviceEntry {
VideoCaptureController* video_capture_controller() const;
media::VideoCaptureDevice* video_capture_device() const;
- void SetVideoCaptureDevice(std::unique_ptr<media::VideoCaptureDevice> device);
- std::unique_ptr<media::VideoCaptureDevice> ReleaseVideoCaptureDevice();
+ void SetVideoCaptureDevice(std::unique_ptr<VideoCaptureDevice> device);
+ std::unique_ptr<VideoCaptureDevice> ReleaseVideoCaptureDevice();
private:
const std::unique_ptr<VideoCaptureController> video_capture_controller_;
- std::unique_ptr<media::VideoCaptureDevice> video_capture_device_;
+ std::unique_ptr<VideoCaptureDevice> video_capture_device_;
base::ThreadChecker thread_checker_;
};
@@ -199,7 +199,7 @@ VideoCaptureManager::DeviceEntry::~DeviceEntry() {
}
void VideoCaptureManager::DeviceEntry::SetVideoCaptureDevice(
- std::unique_ptr<media::VideoCaptureDevice> device) {
+ std::unique_ptr<VideoCaptureDevice> device) {
DCHECK(thread_checker_.CalledOnValidThread());
video_capture_device_.swap(device);
}
@@ -252,6 +252,7 @@ void VideoCaptureManager::Register(
listener_ = listener;
device_task_runner_ = device_task_runner;
#if defined(OS_ANDROID)
+ application_state_has_running_activities_ = true;
app_status_listener_.reset(new base::android::ApplicationStatusListener(
base::Bind(&VideoCaptureManager::OnApplicationStateChange,
base::Unretained(this))));
@@ -280,7 +281,7 @@ void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) {
// Bind a callback to ConsolidateDevicesInfoOnDeviceThread() with an argument
// for another callback to OnDevicesInfoEnumerated() to be run in the current
// loop, i.e. IO loop. Pass a timer for UMA histogram collection.
- base::Callback<void(std::unique_ptr<media::VideoCaptureDevice::Names>)>
+ base::Callback<void(std::unique_ptr<VideoCaptureDevice::Names>)>
devices_enumerated_callback = base::Bind(
&VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread, this,
media::BindToCurrentLoop(
@@ -329,8 +330,8 @@ void VideoCaptureManager::Close(int capture_session_id) {
return;
}
- DeviceEntry* const existing_device = GetDeviceEntryForMediaStreamDevice(
- session_it->second);
+ DeviceEntry* const existing_device =
+ GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id);
if (existing_device) {
// Remove any client that is still using the session. This is safe to call
// even if there are no clients using the session.
@@ -362,7 +363,12 @@ void VideoCaptureManager::QueueStartDevice(
void VideoCaptureManager::DoStopDevice(DeviceEntry* entry) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(std::find(devices_.begin(), devices_.end(), entry) != devices_.end());
+ // TODO(mcasas): use a helper function https://crbug.com/624854.
+ DCHECK(
+ std::find_if(devices_.begin(), devices_.end(),
+ [entry](const std::unique_ptr<DeviceEntry>& device_entry) {
+ return device_entry.get() == entry;
+ }) != devices_.end());
// Find the matching start request.
for (DeviceStartQueue::reverse_iterator request =
@@ -379,7 +385,7 @@ void VideoCaptureManager::DoStopDevice(DeviceEntry* entry) {
DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id
<< " serial_id = " << entry->serial_id << ".";
entry->video_capture_controller()->DoLogOnIOThread(
- base::StringPrintf("Stopping device: id: %s\n", entry->id.c_str()));
+ base::StringPrintf("Stopping device: id: %s", entry->id.c_str()));
if (entry->video_capture_device()) {
// |entry->video_capture_device| can be null if creating the device fails.
@@ -402,13 +408,8 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
return;
const int serial_id = request->serial_id();
- DeviceEntries::iterator entry_it = std::find_if(
- devices_.begin(), devices_.end(),
- [serial_id] (const DeviceEntry* e) {
- return e->serial_id == serial_id;
- });
- DCHECK(entry_it != devices_.end());
- DeviceEntry* entry = (*entry_it);
+ DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id);
+ DCHECK(entry);
#if defined(OS_MACOSX)
if (NeedToInitializeCaptureDeviceApi(entry->stream_type)) {
@@ -421,7 +422,7 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = "
<< entry->id << " start id = " << entry->serial_id;
- base::Callback<std::unique_ptr<media::VideoCaptureDevice>(void)>
+ base::Callback<std::unique_ptr<VideoCaptureDevice>(void)>
start_capture_function;
switch (entry->stream_type) {
@@ -429,8 +430,7 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
// We look up the device id from the renderer in our local enumeration
// since the renderer does not have all the information that might be
// held in the browser-side VideoCaptureDevice::Name structure.
- const media::VideoCaptureDeviceInfo* found =
- FindDeviceInfoById(entry->id, devices_info_cache_);
+ const media::VideoCaptureDeviceInfo* found = GetDeviceInfoById(entry->id);
if (found) {
entry->video_capture_controller()->DoLogOnIOThread(base::StringPrintf(
"Starting device: id: %s, name: %s, api: %s",
@@ -487,7 +487,7 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
void VideoCaptureManager::OnDeviceStarted(
int serial_id,
- std::unique_ptr<media::VideoCaptureDevice> device) {
+ std::unique_ptr<VideoCaptureDevice> device) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(serial_id == device_start_queue_.begin()->serial_id());
DVLOG(3) << "OnDeviceStarted";
@@ -505,13 +505,8 @@ void VideoCaptureManager::OnDeviceStarted(
device_ptr->StopAndDeAllocate();
}
} else {
- DeviceEntries::iterator entry_it = std::find_if(
- devices_.begin(), devices_.end(),
- [serial_id] (const DeviceEntry* e) {
- return e->serial_id == serial_id;
- });
- DCHECK(entry_it != devices_.end());
- DeviceEntry* entry = *entry_it;
+ DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id);
+ DCHECK(entry);
DCHECK(!entry->video_capture_device());
entry->SetVideoCaptureDevice(std::move(device));
@@ -529,13 +524,13 @@ void VideoCaptureManager::OnDeviceStarted(
std::unique_ptr<media::VideoCaptureDevice>
VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread(
- const media::VideoCaptureDevice::Name& name,
+ const VideoCaptureDevice::Name& name,
const media::VideoCaptureParams& params,
- std::unique_ptr<media::VideoCaptureDevice::Client> device_client) {
+ std::unique_ptr<VideoCaptureDevice::Client> device_client) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(IsOnDeviceThread());
- std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
+ std::unique_ptr<VideoCaptureDevice> video_capture_device;
video_capture_device = video_capture_device_factory_->Create(name);
if (!video_capture_device) {
@@ -551,11 +546,11 @@ std::unique_ptr<media::VideoCaptureDevice>
VideoCaptureManager::DoStartTabCaptureOnDeviceThread(
const std::string& id,
const media::VideoCaptureParams& params,
- std::unique_ptr<media::VideoCaptureDevice::Client> device_client) {
+ std::unique_ptr<VideoCaptureDevice::Client> device_client) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(IsOnDeviceThread());
- std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
+ std::unique_ptr<VideoCaptureDevice> video_capture_device;
video_capture_device.reset(WebContentsVideoCaptureDevice::Create(id));
if (!video_capture_device) {
@@ -571,11 +566,11 @@ std::unique_ptr<media::VideoCaptureDevice>
VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread(
const std::string& id,
const media::VideoCaptureParams& params,
- std::unique_ptr<media::VideoCaptureDevice::Client> device_client) {
+ std::unique_ptr<VideoCaptureDevice::Client> device_client) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(IsOnDeviceThread());
- std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
+ std::unique_ptr<VideoCaptureDevice> video_capture_device;
#if defined(ENABLE_SCREEN_CAPTURE)
DesktopMediaID desktop_id = DesktopMediaID::Parse(id);
if (desktop_id.is_null()) {
@@ -648,7 +643,7 @@ void VideoCaptureManager::StopCaptureForClient(
DCHECK(controller);
DCHECK(client_handler);
- DeviceEntry* entry = GetDeviceEntryForController(controller);
+ DeviceEntry* entry = GetDeviceEntryByController(controller);
if (!entry) {
NOTREACHED();
return;
@@ -692,11 +687,9 @@ void VideoCaptureManager::PauseCaptureForClient(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(controller);
DCHECK(client_handler);
- DeviceEntry* entry = GetDeviceEntryForController(controller);
- if (!entry) {
- NOTREACHED();
- DVLOG(1) << "Got Null entry while pausing capture";
- }
+ DeviceEntry* entry = GetDeviceEntryByController(controller);
+ if (!entry)
+ NOTREACHED() << "Got Null entry while pausing capture";
// Do not pause Content Video Capture devices, e.g. Tab or Screen capture.
if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
@@ -715,11 +708,9 @@ void VideoCaptureManager::ResumeCaptureForClient(
DCHECK(controller);
DCHECK(client_handler);
- DeviceEntry* entry = GetDeviceEntryForController(controller);
- if (!entry) {
- NOTREACHED();
- DVLOG(1) << "Got Null entry while resuming capture";
- }
+ DeviceEntry* entry = GetDeviceEntryByController(controller);
+ if (!entry)
+ NOTREACHED() << "Got Null entry while resuming capture";
// Do not resume Content Video Capture devices, e.g. Tab or Screen capture.
if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
@@ -732,11 +723,11 @@ void VideoCaptureManager::RequestRefreshFrameForClient(
VideoCaptureController* controller) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (DeviceEntry* entry = GetDeviceEntryForController(controller)) {
+ if (DeviceEntry* entry = GetDeviceEntryByController(controller)) {
if (media::VideoCaptureDevice* device = entry->video_capture_device()) {
device_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&media::VideoCaptureDevice::RequestRefreshFrame,
+ base::Bind(&VideoCaptureDevice::RequestRefreshFrame,
// Unretained is safe to use here because |device| would be
// null if it was scheduled for shutdown and destruction,
// and because this task is guaranteed to run before the
@@ -759,7 +750,7 @@ bool VideoCaptureManager::GetDeviceSupportedFormats(
// Return all available formats of the device, regardless its started state.
media::VideoCaptureDeviceInfo* existing_device =
- FindDeviceInfoById(it->second.id, devices_info_cache_);
+ GetDeviceInfoById(it->second.id);
if (existing_device)
*supported_formats = existing_device->supported_formats;
return true;
@@ -778,7 +769,7 @@ bool VideoCaptureManager::GetDeviceFormatsInUse(
// Return the currently in-use format(s) of the device, if it's started.
DeviceEntry* device_in_use =
- GetDeviceEntryForMediaStreamDevice(it->second);
+ GetDeviceEntryByTypeAndId(it->second.type, it->second.id);
if (device_in_use) {
// Currently only one format-in-use is supported at the VCC level.
formats_in_use->push_back(
@@ -800,12 +791,11 @@ void VideoCaptureManager::SetDesktopCaptureWindowId(
void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
media::VideoCaptureSessionId session_id) {
SessionMap::iterator session_it = sessions_.find(session_id);
- if (session_it == sessions_.end()) {
+ if (session_it == sessions_.end())
return;
- }
DeviceEntry* const existing_device =
- GetDeviceEntryForMediaStreamDevice(session_it->second);
+ GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id);
if (!existing_device) {
DVLOG(2) << "Failed to find an existing screen capture device.";
return;
@@ -840,40 +830,40 @@ void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
notification_window_ids_.erase(window_id_it);
}
-bool VideoCaptureManager::TakePhoto(
+void VideoCaptureManager::GetPhotoCapabilities(
int session_id,
- const media::VideoCaptureDevice::TakePhotoCallback& photo_callback) {
+ media::ScopedResultCallback<
+ VideoCaptureDevice::GetPhotoCapabilitiesCallback> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- SessionMap::const_iterator session_it = sessions_.find(session_id);
- if (session_it == sessions_.end())
- return false;
-
- DeviceEntry* const device_info =
- GetDeviceEntryForMediaStreamDevice(session_it->second);
- if (!device_info)
- return false;
+ VideoCaptureDevice* device = GetVideoCaptureDeviceBySessionId(session_id);
+ if (!device)
+ return;
+ // Unretained(device) is safe to use here because |device| would be null if it
+ // was scheduled for shutdown and destruction, and because this task is
+ // guaranteed to run before the task that destroys the |device|.
device_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&VideoCaptureManager::DoTakePhotoOnDeviceThread, this,
- device_info->video_capture_device(), photo_callback));
- return true;
+ FROM_HERE, base::Bind(&VideoCaptureDevice::GetPhotoCapabilities,
+ base::Unretained(device), base::Passed(&callback)));
}
-void VideoCaptureManager::DoTakePhotoOnDeviceThread(
- media::VideoCaptureDevice* device,
- const media::VideoCaptureDevice::TakePhotoCallback& photo_callback) {
- DCHECK(IsOnDeviceThread());
- if (device->TakePhoto(photo_callback))
+void VideoCaptureManager::TakePhoto(
+ int session_id,
+ media::ScopedResultCallback<VideoCaptureDevice::TakePhotoCallback>
+ callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ VideoCaptureDevice* device = GetVideoCaptureDeviceBySessionId(session_id);
+ if (!device)
return;
-
- // TakePhoto() failed synchronously: Make sure |photo_callback| is Run().
- std::unique_ptr<std::vector<uint8_t>> empty_vector(
- new std::vector<uint8_t>());
- photo_callback.Run("", std::move(empty_vector));
+ // Unretained(device) is safe to use here because |device| would be null if it
+ // was scheduled for shutdown and destruction, and because this task is
+ // guaranteed to run before the task that destroys the |device|.
+ device_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&VideoCaptureDevice::TakePhoto,
+ base::Unretained(device), base::Passed(&callback)));
}
void VideoCaptureManager::DoStopDeviceOnDeviceThread(
- std::unique_ptr<media::VideoCaptureDevice> device) {
+ std::unique_ptr<VideoCaptureDevice> device) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
DCHECK(IsOnDeviceThread());
device->StopAndDeAllocate();
@@ -938,15 +928,15 @@ void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
on_devices_enumerated_callback,
MediaStreamType stream_type,
const media::VideoCaptureDeviceInfos& old_device_info_cache,
- std::unique_ptr<media::VideoCaptureDevice::Names> names_snapshot) {
+ std::unique_ptr<VideoCaptureDevice::Names> names_snapshot) {
DCHECK(IsOnDeviceThread());
// Construct |new_devices_info_cache| with the cached devices that are still
// present in the system, and remove their names from |names_snapshot|, so we
// keep there the truly new devices.
media::VideoCaptureDeviceInfos new_devices_info_cache;
for (const auto& device_info : old_device_info_cache) {
- for (media::VideoCaptureDevice::Names::iterator it =
- names_snapshot->begin(); it != names_snapshot->end(); ++it) {
+ for (VideoCaptureDevice::Names::iterator it = names_snapshot->begin();
+ it != names_snapshot->end(); ++it) {
if (device_info.name.id() == it->id()) {
new_devices_info_cache.push_back(device_info);
names_snapshot->erase(it);
@@ -967,47 +957,85 @@ void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
on_devices_enumerated_callback.Run(new_devices_info_cache);
}
+void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Removal of the last client stops the device.
+ if (!entry->video_capture_controller()->HasActiveClient() &&
+ !entry->video_capture_controller()->HasPausedClient()) {
+ DVLOG(1) << "VideoCaptureManager stopping device (type = "
+ << entry->stream_type << ", id = " << entry->id << ")";
+
+ // The DeviceEntry is removed from |devices_| immediately. The controller is
+ // deleted immediately, and the device is freed asynchronously. After this
+ // point, subsequent requests to open this same device ID will create a new
+ // DeviceEntry, VideoCaptureController, and VideoCaptureDevice.
+ DoStopDevice(entry);
+ // TODO(mcasas): use a helper function https://crbug.com/624854.
+ DeviceEntries::iterator device_it =
+ std::find_if(devices_.begin(), devices_.end(),
+ [entry](const std::unique_ptr<DeviceEntry>& device_entry) {
+ return device_entry.get() == entry;
+ });
+ devices_.erase(device_it);
+ }
+}
+
+media::VideoCaptureDevice*
+VideoCaptureManager::GetVideoCaptureDeviceBySessionId(int session_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ SessionMap::const_iterator session_it = sessions_.find(session_id);
+ if (session_it == sessions_.end())
+ return nullptr;
+
+ DeviceEntry* const device_info =
+ GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id);
+ return device_info ? device_info->video_capture_device() : nullptr;
+}
+
VideoCaptureManager::DeviceEntry*
-VideoCaptureManager::GetDeviceEntryForMediaStreamDevice(
- const MediaStreamDevice& device_info) {
+VideoCaptureManager::GetDeviceEntryByTypeAndId(
+ MediaStreamType type,
+ const std::string& device_id) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- for (DeviceEntry* device : devices_) {
- if (device_info.type == device->stream_type && device_info.id == device->id)
- return device;
+ for (const std::unique_ptr<DeviceEntry>& device : devices_) {
+ if (type == device->stream_type && device_id == device->id)
+ return device.get();
}
return nullptr;
}
VideoCaptureManager::DeviceEntry*
-VideoCaptureManager::GetDeviceEntryForController(
+VideoCaptureManager::GetDeviceEntryByController(
const VideoCaptureController* controller) const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
// Look up |controller| in |devices_|.
- for (DeviceEntry* device : devices_) {
+ for (const std::unique_ptr<DeviceEntry>& device : devices_) {
if (device->video_capture_controller() == controller)
- return device;
+ return device.get();
}
return nullptr;
}
-void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
+VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetDeviceEntryBySerialId(
+ int serial_id) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Removal of the last client stops the device.
- if (!entry->video_capture_controller()->HasActiveClient() &&
- !entry->video_capture_controller()->HasPausedClient()) {
- DVLOG(1) << "VideoCaptureManager stopping device (type = "
- << entry->stream_type << ", id = " << entry->id << ")";
- // The DeviceEntry is removed from |devices_| immediately. The controller is
- // deleted immediately, and the device is freed asynchronously. After this
- // point, subsequent requests to open this same device ID will create a new
- // DeviceEntry, VideoCaptureController, and VideoCaptureDevice.
- DoStopDevice(entry);
- DeviceEntries::iterator device_it = std::find(devices_.begin(),
- devices_.end(),
- entry);
- devices_.erase(device_it);
+ for (const std::unique_ptr<DeviceEntry>& device : devices_) {
+ if (device->serial_id == serial_id)
+ return device.get();
}
+ return nullptr;
+}
+
+media::VideoCaptureDeviceInfo* VideoCaptureManager::GetDeviceInfoById(
+ const std::string& id) {
+ for (auto& it : devices_info_cache_) {
+ if (it.name.id() == id)
+ return &it;
+ }
+ return nullptr;
}
VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
@@ -1023,7 +1051,7 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
// Check if another session has already opened this device. If so, just
// use that opened device.
DeviceEntry* const existing_device =
- GetDeviceEntryForMediaStreamDevice(device_info);
+ GetDeviceEntryByTypeAndId(device_info.type, device_info.id);
if (existing_device) {
DCHECK_EQ(device_info.type, existing_device->stream_type);
return existing_device;
@@ -1036,20 +1064,10 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
DeviceEntry* new_device =
new DeviceEntry(device_info.type, device_info.id,
std::move(video_capture_controller), params);
- devices_.push_back(new_device);
+ devices_.emplace_back(new_device);
return new_device;
}
-media::VideoCaptureDeviceInfo* VideoCaptureManager::FindDeviceInfoById(
- const std::string& id,
- media::VideoCaptureDeviceInfos& device_vector) {
- for (auto& it : device_vector) {
- if (it.name.id() == id)
- return &(it);
- }
- return nullptr;
-}
-
void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread(
media::VideoCaptureDevice* device,
gfx::NativeViewId window_id) {
@@ -1093,10 +1111,15 @@ void VideoCaptureManager::OnApplicationStateChange(
base::android::ApplicationState state) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
+ // Only release/resume devices when the Application state changes from
+ // RUNNING->STOPPED->RUNNING.
+ if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES &&
+ !application_state_has_running_activities_) {
ResumeDevices();
+ application_state_has_running_activities_ = true;
} else if (state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) {
ReleaseDevices();
+ application_state_has_running_activities_ = false;
}
}
@@ -1108,7 +1131,7 @@ void VideoCaptureManager::ReleaseDevices() {
if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
continue;
- DoStopDevice(entry);
+ DoStopDevice(entry.get());
}
}
@@ -1117,11 +1140,7 @@ void VideoCaptureManager::ResumeDevices() {
for (auto& entry : devices_) {
// Do not resume Content Video Capture devices, e.g. Tab or Screen capture.
- // Do not try to restart already running devices. A device will be running
- // if the Application state changes from
- // APPLICATION_STATE_HAS_RUNNING_ACTIVITIES
- // ->APPLICATION_STATE_HAS_PAUSED_ACTIVITIES
- // ->APPLICATION_STATE_HAS_RUNNING_ACTIVITIES
+ // Do not try to restart already running devices.
if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE ||
entry->video_capture_device())
continue;
@@ -1138,7 +1157,7 @@ void VideoCaptureManager::ResumeDevices() {
if (!device_in_queue) {
// Session ID is only valid for Screen capture. So we can fake it to
// resume video capture devices here.
- QueueStartDevice(kFakeSessionId, entry, entry->parameters);
+ QueueStartDevice(kFakeSessionId, entry.get(), entry->parameters);
}
}
}
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 941bcf2418a..3afd0ec6659 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -19,7 +19,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
@@ -46,9 +45,11 @@ class VideoCaptureControllerEventHandler;
// VideoCaptureManager opens/closes and start/stops video capture devices.
class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
public:
+ using VideoCaptureDevice = media::VideoCaptureDevice;
+
// Callback used to signal the completion of a controller lookup.
- typedef base::Callback<
- void(const base::WeakPtr<VideoCaptureController>&)> DoneCB;
+ using DoneCB =
+ base::Callback<void(const base::WeakPtr<VideoCaptureController>&)>;
explicit VideoCaptureManager(
std::unique_ptr<media::VideoCaptureDeviceFactory> factory);
@@ -157,11 +158,13 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
return device_task_runner_;
}
-
- bool TakePhoto(int session_id,
- const media::VideoCaptureDevice::TakePhotoCallback&
- photo_callback) WARN_UNUSED_RESULT;
-
+ void GetPhotoCapabilities(
+ int session_id,
+ media::ScopedResultCallback<
+ VideoCaptureDevice::GetPhotoCapabilitiesCallback> callback);
+ void TakePhoto(int session_id,
+ media::ScopedResultCallback<
+ VideoCaptureDevice::TakePhotoCallback> callback);
#if defined(OS_ANDROID)
// Some devices had troubles when stopped and restarted quickly, so the device
// is only stopped when Chrome is sent to background and not when, e.g., a tab
@@ -170,14 +173,14 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
#endif
private:
+ class CaptureDeviceStartRequest;
class DeviceEntry;
- ~VideoCaptureManager() override;
+ using SessionMap = std::map<media::VideoCaptureSessionId, MediaStreamDevice>;
+ using DeviceEntries = std::vector<std::unique_ptr<DeviceEntry>>;
+ using DeviceStartQueue = std::list<CaptureDeviceStartRequest>;
- // Checks to see if |entry| has no clients left on its controller. If so,
- // remove it from the list of devices, and delete it asynchronously. |entry|
- // may be freed by this function.
- void DestroyDeviceEntryIfNoClients(DeviceEntry* entry);
+ ~VideoCaptureManager() override;
// Helpers to report an event to our Listener.
void OnOpened(MediaStreamType type,
@@ -189,20 +192,6 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
base::ElapsedTimer* timer,
const media::VideoCaptureDeviceInfos& new_devices_info_cache);
- // Finds a DeviceEntry by its device ID and type, if it is already opened.
- DeviceEntry* GetDeviceEntryForMediaStreamDevice(
- const MediaStreamDevice& device_info);
-
- // Finds a DeviceEntry entry for the indicated session, creating a fresh one
- // if necessary. Returns NULL if the session id is invalid.
- DeviceEntry* GetOrCreateDeviceEntry(
- media::VideoCaptureSessionId capture_session_id,
- const media::VideoCaptureParams& params);
-
- // Finds the DeviceEntry that owns a particular controller pointer.
- DeviceEntry* GetDeviceEntryForController(
- const VideoCaptureController* controller) const;
-
bool IsOnDeviceThread() const;
// Consolidates the cached devices list with the list of currently connected
@@ -213,7 +202,35 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
on_devices_enumerated_callback,
MediaStreamType stream_type,
const media::VideoCaptureDeviceInfos& old_device_info_cache,
- std::unique_ptr<media::VideoCaptureDevice::Names> names_snapshot);
+ std::unique_ptr<VideoCaptureDevice::Names> names_snapshot);
+
+ // Checks to see if |entry| has no clients left on its controller. If so,
+ // remove it from the list of devices, and delete it asynchronously. |entry|
+ // may be freed by this function.
+ void DestroyDeviceEntryIfNoClients(DeviceEntry* entry);
+
+ // Retrieve the VideoCaptureDevice associated to |session_id|, or nullptr
+ // if not found.
+ VideoCaptureDevice* GetVideoCaptureDeviceBySessionId(int session_id);
+
+ // Finds a DeviceEntry in different ways: by its |device_id| and |type| (if it
+ // is already opened), by its |controller| or by its |serial_id|. In all
+ // cases, if not found, nullptr is returned.
+ DeviceEntry* GetDeviceEntryByTypeAndId(MediaStreamType type,
+ const std::string& device_id) const;
+ DeviceEntry* GetDeviceEntryByController(
+ const VideoCaptureController* controller) const;
+ DeviceEntry* GetDeviceEntryBySerialId(int serial_id) const;
+
+ // Finds the device info by |id| in |devices_info_cache_|, or nullptr.
+ media::VideoCaptureDeviceInfo* GetDeviceInfoById(const std::string& id);
+
+ // Finds a DeviceEntry entry for the indicated |capture_session_id|, creating
+ // a fresh one if necessary. Returns nullptr if said |capture_session_id| is
+ // invalid.
+ DeviceEntry* GetOrCreateDeviceEntry(
+ media::VideoCaptureSessionId capture_session_id,
+ const media::VideoCaptureParams& params);
// Starting a capture device can take 1-2 seconds.
// To avoid multiple unnecessary start/stop commands to the OS, each start
@@ -225,7 +242,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
DeviceEntry* entry,
const media::VideoCaptureParams& params);
void OnDeviceStarted(int serial_id,
- std::unique_ptr<media::VideoCaptureDevice> device);
+ std::unique_ptr<VideoCaptureDevice> device);
void DoStopDevice(DeviceEntry* entry);
void HandleQueuedStartRequest();
@@ -233,33 +250,23 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// VideoCaptureDevice is returned to the IO-thread and stored in
// a DeviceEntry in |devices_|. Ownership of |client| passes to
// the device.
- std::unique_ptr<media::VideoCaptureDevice> DoStartDeviceCaptureOnDeviceThread(
- const media::VideoCaptureDevice::Name& name,
+ std::unique_ptr<VideoCaptureDevice> DoStartDeviceCaptureOnDeviceThread(
+ const VideoCaptureDevice::Name& name,
const media::VideoCaptureParams& params,
- std::unique_ptr<media::VideoCaptureDevice::Client> client);
+ std::unique_ptr<VideoCaptureDevice::Client> client);
- std::unique_ptr<media::VideoCaptureDevice> DoStartTabCaptureOnDeviceThread(
+ std::unique_ptr<VideoCaptureDevice> DoStartTabCaptureOnDeviceThread(
const std::string& device_id,
const media::VideoCaptureParams& params,
- std::unique_ptr<media::VideoCaptureDevice::Client> client);
+ std::unique_ptr<VideoCaptureDevice::Client> client);
- std::unique_ptr<media::VideoCaptureDevice>
- DoStartDesktopCaptureOnDeviceThread(
+ std::unique_ptr<VideoCaptureDevice> DoStartDesktopCaptureOnDeviceThread(
const std::string& device_id,
const media::VideoCaptureParams& params,
- std::unique_ptr<media::VideoCaptureDevice::Client> client);
+ std::unique_ptr<VideoCaptureDevice::Client> client);
// Stops and destroys the VideoCaptureDevice held in |device|.
- void DoStopDeviceOnDeviceThread(
- std::unique_ptr<media::VideoCaptureDevice> device);
-
- void DoTakePhotoOnDeviceThread(
- media::VideoCaptureDevice* device,
- const media::VideoCaptureDevice::TakePhotoCallback& photo_callback);
-
- media::VideoCaptureDeviceInfo* FindDeviceInfoById(
- const std::string& id,
- media::VideoCaptureDeviceInfos& device_vector);
+ void DoStopDeviceOnDeviceThread(std::unique_ptr<VideoCaptureDevice> device);
void MaybePostDesktopCaptureWindowId(media::VideoCaptureSessionId session_id);
void SetDesktopCaptureWindowIdOnDeviceThread(
@@ -292,6 +299,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
std::unique_ptr<base::android::ApplicationStatusListener>
app_status_listener_;
+ bool application_state_has_running_activities_;
#endif
// The message loop of media stream device thread, where VCD's live.
@@ -305,16 +313,13 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// the Open() entry point. The keys are session_id's. This map is used to
// determine which device to use when StartCaptureForClient() occurs. Used
// only on the IO thread.
- typedef std::map<media::VideoCaptureSessionId, MediaStreamDevice> SessionMap;
SessionMap sessions_;
- // Currently opened devices. The device may or may not be started. This member
- // is only accessed on IO tbhread.
- typedef ScopedVector<DeviceEntry> DeviceEntries;
+ // Currently opened DeviceEntry instances (each owning a VideoCaptureDevice -
+ // VideoCaptureController pair). The device may or may not be started. This
+ // member is only accessed on IO thread.
DeviceEntries devices_;
- class CaptureDeviceStartRequest;
- typedef std::list<CaptureDeviceStartRequest> DeviceStartQueue;
DeviceStartQueue device_start_queue_;
// Device creation factory injected on construction from MediaStreamManager or
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 2bbeb886339..5785e487891 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
@@ -61,8 +61,7 @@ class MockFrameObserver : public VideoCaptureControllerEventHandler {
void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override {}
void OnBufferReady(VideoCaptureControllerID id,
int buffer_id,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp) override {}
+ const scoped_refptr<media::VideoFrame>& frame) override {}
void OnEnded(VideoCaptureControllerID id) override {}
void OnGotControllerCallback(VideoCaptureControllerID) {}
@@ -106,7 +105,7 @@ class VideoCaptureManagerTest : public testing::Test {
ASSERT_TRUE(0 == controllers_.count(id));
controllers_[id] = controller.get();
} else {
- ASSERT_TRUE(NULL == controller);
+ ASSERT_FALSE(controller);
}
quit_closure.Run();
}
diff --git a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
index a0dc5a6fd13..e5f0dbd04ff 100644
--- a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <deque>
+#include <tuple>
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/media/webrtc/webrtc_identity_store.h"
@@ -159,10 +160,10 @@ class WebRTCIdentityServiceHostTest : public ::testing::Test {
IPC::Message ipc = host_->GetLastMessage();
EXPECT_EQ(ipc.type(), WebRTCIdentityHostMsg_RequestFailed::ID);
- base::Tuple<int, int> error_in_message;
+ std::tuple<int, int> error_in_message;
WebRTCIdentityHostMsg_RequestFailed::Read(&ipc, &error_in_message);
- EXPECT_EQ(kFakeRequestId, base::get<0>(error_in_message));
- EXPECT_EQ(error, base::get<1>(error_in_message));
+ EXPECT_EQ(kFakeRequestId, std::get<0>(error_in_message));
+ EXPECT_EQ(error, std::get<1>(error_in_message));
}
void VerifyIdentityReadyMessage(const std::string& cert,
@@ -171,11 +172,11 @@ class WebRTCIdentityServiceHostTest : public ::testing::Test {
IPC::Message ipc = host_->GetLastMessage();
EXPECT_EQ(ipc.type(), WebRTCIdentityHostMsg_IdentityReady::ID);
- base::Tuple<int, std::string, std::string> identity_in_message;
+ std::tuple<int, std::string, std::string> identity_in_message;
WebRTCIdentityHostMsg_IdentityReady::Read(&ipc, &identity_in_message);
- EXPECT_EQ(kFakeRequestId, base::get<0>(identity_in_message));
- EXPECT_EQ(cert, base::get<1>(identity_in_message));
- EXPECT_EQ(key, base::get<2>(identity_in_message));
+ EXPECT_EQ(kFakeRequestId, std::get<0>(identity_in_message));
+ EXPECT_EQ(cert, std::get<1>(identity_in_message));
+ EXPECT_EQ(key, std::get<2>(identity_in_message));
}
protected:
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
index b84c879b074..86bce36ea57 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
@@ -27,8 +27,7 @@ namespace content {
NativeWebKeyboardEvent::NativeWebKeyboardEvent()
: os_event(NULL),
- skip_in_browser(false),
- match_edit_command(false) {
+ skip_in_browser(false) {
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(gfx::NativeEvent native_event)
@@ -38,24 +37,21 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(gfx::NativeEvent native_event)
NativeWebKeyboardEvent::NativeWebKeyboardEvent(const ui::KeyEvent& key_event)
: WebKeyboardEvent(MakeWebKeyboardEvent(key_event)),
os_event(CopyEvent(&key_event)),
- skip_in_browser(false),
- match_edit_command(false) {
+ skip_in_browser(false) {
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(
const NativeWebKeyboardEvent& other)
: WebKeyboardEvent(other),
os_event(CopyEvent(other.os_event)),
- skip_in_browser(other.skip_in_browser),
- match_edit_command(false) {
+ skip_in_browser(other.skip_in_browser) {
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(const ui::KeyEvent& key_event,
base::char16 character)
: WebKeyboardEvent(MakeWebKeyboardEvent(key_event)),
os_event(NULL),
- skip_in_browser(false),
- match_edit_command(false) {
+ skip_in_browser(false) {
type = blink::WebInputEvent::Char;
windowsKeyCode = character;
text[0] = character;
@@ -69,7 +65,6 @@ NativeWebKeyboardEvent& NativeWebKeyboardEvent::operator=(
delete os_event;
os_event = CopyEvent(other.os_event);
skip_in_browser = other.skip_in_browser;
- match_edit_command = other.match_edit_command;
return *this;
}
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
new file mode 100644
index 00000000000..8e56b01416a
--- /dev/null
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -0,0 +1,87 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
+
+#include "base/bind_helpers.h"
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_manager.h"
+#include "content/browser/compositor/surface_utils.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+// static
+void OffscreenCanvasSurfaceImpl::Create(
+ mojo::InterfaceRequest<blink::mojom::OffscreenCanvasSurface> request) {
+ // |binding_| will take ownership of OffscreenCanvasSurfaceImpl
+ new OffscreenCanvasSurfaceImpl(std::move(request));
+}
+
+OffscreenCanvasSurfaceImpl::OffscreenCanvasSurfaceImpl(
+ mojo::InterfaceRequest<blink::mojom::OffscreenCanvasSurface> request)
+ : id_allocator_(CreateSurfaceIdAllocator()),
+ binding_(this, std::move(request)) {}
+
+OffscreenCanvasSurfaceImpl::~OffscreenCanvasSurfaceImpl() {
+ if (!GetSurfaceManager()) {
+ // Inform both members that SurfaceManager's no longer alive to
+ // avoid their destruction errors.
+ if (surface_factory_)
+ surface_factory_->DidDestroySurfaceManager();
+ if (id_allocator_)
+ id_allocator_->DidDestroySurfaceManager();
+ }
+ surface_factory_->Destroy(surface_id_);
+}
+
+void OffscreenCanvasSurfaceImpl::GetSurfaceId(
+ const GetSurfaceIdCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ surface_id_ = id_allocator_->GenerateId();
+
+ callback.Run(surface_id_);
+}
+
+void OffscreenCanvasSurfaceImpl::RequestSurfaceCreation(
+ const cc::SurfaceId& surface_id) {
+ cc::SurfaceManager* manager = GetSurfaceManager();
+ if (!surface_factory_) {
+ surface_factory_ = base::MakeUnique<cc::SurfaceFactory>(manager, this);
+ }
+ surface_factory_->Create(surface_id);
+}
+
+void OffscreenCanvasSurfaceImpl::Require(const cc::SurfaceId& surface_id,
+ const cc::SurfaceSequence& sequence) {
+ cc::SurfaceManager* manager = GetSurfaceManager();
+ cc::Surface* surface = manager->GetSurfaceForId(surface_id);
+ if (!surface) {
+ DLOG(ERROR) << "Attempting to require callback on nonexistent surface";
+ return;
+ }
+ surface->AddDestructionDependency(sequence);
+}
+
+void OffscreenCanvasSurfaceImpl::Satisfy(const cc::SurfaceSequence& sequence) {
+ std::vector<uint32_t> sequences;
+ sequences.push_back(sequence.sequence);
+ cc::SurfaceManager* manager = GetSurfaceManager();
+ manager->DidSatisfySequences(sequence.id_namespace, &sequences);
+}
+
+// TODO(619136): Implement cc::SurfaceFactoryClient functions for resources
+// return.
+void OffscreenCanvasSurfaceImpl::ReturnResources(
+ const cc::ReturnedResourceArray& resources) {}
+
+void OffscreenCanvasSurfaceImpl::WillDrawSurface(const cc::SurfaceId& id,
+ const gfx::Rect& damage_rect) {
+}
+
+void OffscreenCanvasSurfaceImpl::SetBeginFrameSource(
+ cc::BeginFrameSource* begin_frame_source) {}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h
new file mode 100644
index 00000000000..cf85fe5aec7
--- /dev/null
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h
@@ -0,0 +1,55 @@
+// 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_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_SURFACE_IMPL_H_
+
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_factory_client.h"
+#include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surface_id_allocator.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/string.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom.h"
+
+namespace content {
+
+class OffscreenCanvasSurfaceImpl : public blink::mojom::OffscreenCanvasSurface,
+ public cc::SurfaceFactoryClient {
+ public:
+ static void Create(
+ mojo::InterfaceRequest<blink::mojom::OffscreenCanvasSurface> request);
+
+ // blink::mojom::OffscreenCanvasSurface implementation.
+ void GetSurfaceId(const GetSurfaceIdCallback& callback) override;
+ void RequestSurfaceCreation(const cc::SurfaceId& surface_id) override;
+ void Require(const cc::SurfaceId& surface_id,
+ const cc::SurfaceSequence& sequence) override;
+ void Satisfy(const cc::SurfaceSequence& sequence) override;
+
+ // cc::SurfaceFactoryClient implementation.
+ void ReturnResources(const cc::ReturnedResourceArray& resources) override;
+ void WillDrawSurface(const cc::SurfaceId& id,
+ const gfx::Rect& damage_rect) override;
+ void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override;
+
+ private:
+ ~OffscreenCanvasSurfaceImpl() override;
+ explicit OffscreenCanvasSurfaceImpl(
+ mojo::InterfaceRequest<blink::mojom::OffscreenCanvasSurface> request);
+
+ // Surface-related state
+ std::unique_ptr<cc::SurfaceIdAllocator> id_allocator_;
+ cc::SurfaceId surface_id_;
+ std::unique_ptr<cc::SurfaceFactory> surface_factory_;
+
+ mojo::StrongBinding<blink::mojom::OffscreenCanvasSurface> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(OffscreenCanvasSurfaceImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_SURFACE_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index 34c631a56dd..2f063027435 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -7,7 +7,6 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
-#include "content/common/input/input_event_utils.h"
#include "content/public/browser/overscroll_configuration.h"
#include "content/public/common/content_switches.h"
@@ -36,15 +35,13 @@ OverscrollController::OverscrollController()
scroll_state_(STATE_UNKNOWN),
overscroll_delta_x_(0.f),
overscroll_delta_y_(0.f),
- delegate_(NULL),
- use_gesture_wheel_scrolling_(UseGestureBasedWheelScrolling()) {}
+ delegate_(NULL) {}
OverscrollController::~OverscrollController() {
}
bool OverscrollController::ShouldProcessEvent(
const blink::WebInputEvent& event) {
- if (use_gesture_wheel_scrolling_) {
switch (event.type) {
case blink::WebInputEvent::MouseWheel:
return false;
@@ -76,7 +73,6 @@ bool OverscrollController::ShouldProcessEvent(
default:
break;
}
- }
return true;
}
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index 90f310f19fb..f8163433f8d 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -122,7 +122,6 @@ class OverscrollController {
// The delegate that receives the overscroll updates. The delegate is not
// owned by this controller.
OverscrollControllerDelegate* delegate_;
- bool use_gesture_wheel_scrolling_;
DISALLOW_COPY_AND_ASSIGN(OverscrollController);
};
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 f044331e922..12040677924 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -334,7 +334,10 @@ void P2PSocketDispatcherHost::OnDestroySocket(int socket_id) {
void P2PSocketDispatcherHost::DoGetNetworkList() {
net::NetworkInterfaceList list;
- net::GetNetworkList(&list, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
+ if (!net::GetNetworkList(&list, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
+ LOG(ERROR) << "GetNetworkList failed.";
+ return;
+ }
default_ipv4_local_address_ = GetDefaultLocalAddress(AF_INET);
default_ipv6_local_address_ = GetDefaultLocalAddress(AF_INET6);
BrowserThread::PostTask(
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 e55cce722d1..1687a3a474a 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -183,11 +183,15 @@ void P2PSocketHostTcpBase::StartTls() {
new net::ClientSocketHandle());
socket_handle->SetSocket(std::move(socket_));
- net::SSLClientSocketContext context;
- context.cert_verifier = url_context_->GetURLRequestContext()->cert_verifier();
- context.transport_security_state =
- url_context_->GetURLRequestContext()->transport_security_state();
- DCHECK(context.transport_security_state);
+ const net::URLRequestContext* url_request_context =
+ url_context_->GetURLRequestContext();
+ net::SSLClientSocketContext context(
+ url_request_context->cert_verifier(),
+ nullptr, /* TODO(rkn): ChannelIDService is not thread safe. */
+ url_request_context->transport_security_state(),
+ url_request_context->cert_transparency_verifier(),
+ url_request_context->ct_policy_enforcer(),
+ std::string() /* TODO(rsleevi): Ensure a proper unique shard. */);
// Default ssl config.
const net::SSLConfig ssl_config;
@@ -196,7 +200,7 @@ void P2PSocketHostTcpBase::StartTls() {
// Calling net::HostPortPair::FromIPEndPoint will crash if the IP address is
// empty.
if (!remote_address_.ip_address.address().empty()) {
- net::HostPortPair::FromIPEndPoint(remote_address_.ip_address);
+ net::HostPortPair::FromIPEndPoint(remote_address_.ip_address);
} else {
dest_host_port_pair.set_port(remote_address_.ip_address.port());
}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
index f1a60cc72a6..e90fdb78a24 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <tuple>
#include <vector>
#include "content/common/p2p_messages.h"
@@ -108,7 +109,7 @@ MATCHER_P(MatchPacketMessage, packet_content, "") {
return false;
P2PMsg_OnDataReceived::Param params;
P2PMsg_OnDataReceived::Read(arg, &params);
- return base::get<2>(params) == packet_content;
+ return std::get<2>(params) == packet_content;
}
MATCHER_P(MatchIncomingSocketMessage, address, "") {
@@ -117,7 +118,7 @@ MATCHER_P(MatchIncomingSocketMessage, address, "") {
P2PMsg_OnIncomingTcpConnection::Param params;
P2PMsg_OnIncomingTcpConnection::Read(
arg, &params);
- return base::get<1>(params) == address;
+ return std::get<1>(params) == address;
}
#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TEST_UTILS_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h
index 963f7901340..0da28d93f5c 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h
@@ -10,8 +10,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "content/browser/gamepad/gamepad_consumer.h"
#include "content/common/content_export.h"
+#include "device/gamepad/gamepad_consumer.h"
#include "ppapi/host/resource_host.h"
namespace ppapi {
@@ -27,7 +27,7 @@ class GamepadService;
class CONTENT_EXPORT PepperGamepadHost :
public ppapi::host::ResourceHost,
- public GamepadConsumer {
+ public device::GamepadConsumer {
public:
PepperGamepadHost(BrowserPpapiHost* host,
PP_Instance instance,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
index 42ff212bf41..f3e2648a4c0 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
@@ -12,9 +12,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
-#include "content/browser/gamepad/gamepad_test_helpers.h"
+#include "content/browser/gamepad/gamepad_service_test_helpers.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_test.h"
#include "content/common/gamepad_hardware_buffer.h"
+#include "device/gamepad/gamepad_test_helpers.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/proxy/gamepad_resource.h"
@@ -151,7 +152,7 @@ TEST_F(PepperGamepadHostTest, MAYBE_WaitForReply) {
gamepad_host.OnResourceMessageReceived(
PpapiHostMsg_Gamepad_RequestMemory(), &context));
- MockGamepadDataFetcher* fetcher = service_->data_fetcher();
+ device::MockGamepadDataFetcher* fetcher = service_->data_fetcher();
fetcher->WaitForDataReadAndCallbacksIssued();
// It should not have sent the callback message.
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc
index 30570b177e5..3ae9075a5cb 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/pepper/pepper_printing_host.h"
#include <stdint.h>
+#include <tuple>
#include <utility>
#include "base/macros.h"
@@ -108,7 +109,7 @@ TEST_F(PepperPrintingHostTest, GetDefaultPrintSettings) {
reply_msg_param;
ASSERT_TRUE(PpapiPluginMsg_Printing_GetDefaultPrintSettingsReply::Read(
&reply_msg, &reply_msg_param));
- PP_PrintSettings_Dev actual_settings = base::get<0>(reply_msg_param);
+ PP_PrintSettings_Dev actual_settings = std::get<0>(reply_msg_param);
EXPECT_TRUE(PP_RectEqual(expected_settings.printable_area,
actual_settings.printable_area));
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
index d14ce51586a..73fcb569735 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
@@ -79,47 +80,48 @@ bool GetCertificateFields(const net::X509Certificate& cert,
ppapi::PPB_X509Certificate_Fields* fields) {
const net::CertPrincipal& issuer = cert.issuer();
fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COMMON_NAME,
- new base::StringValue(issuer.common_name));
+ base::MakeUnique<base::StringValue>(issuer.common_name));
fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_LOCALITY_NAME,
- new base::StringValue(issuer.locality_name));
- fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_STATE_OR_PROVINCE_NAME,
- new base::StringValue(issuer.state_or_province_name));
- fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COUNTRY_NAME,
- new base::StringValue(issuer.country_name));
- fields->SetField(
- PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_NAME,
- new base::StringValue(base::JoinString(issuer.organization_names, "\n")));
+ base::MakeUnique<base::StringValue>(issuer.locality_name));
fields->SetField(
- PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_UNIT_NAME,
- new base::StringValue(
- base::JoinString(issuer.organization_unit_names, "\n")));
+ PP_X509CERTIFICATE_PRIVATE_ISSUER_STATE_OR_PROVINCE_NAME,
+ base::MakeUnique<base::StringValue>(issuer.state_or_province_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COUNTRY_NAME,
+ base::MakeUnique<base::StringValue>(issuer.country_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_NAME,
+ base::MakeUnique<base::StringValue>(
+ base::JoinString(issuer.organization_names, "\n")));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_UNIT_NAME,
+ base::MakeUnique<base::StringValue>(
+ base::JoinString(issuer.organization_unit_names, "\n")));
const net::CertPrincipal& subject = cert.subject();
fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COMMON_NAME,
- new base::StringValue(subject.common_name));
+ base::MakeUnique<base::StringValue>(subject.common_name));
fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_LOCALITY_NAME,
- new base::StringValue(subject.locality_name));
- fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_STATE_OR_PROVINCE_NAME,
- new base::StringValue(subject.state_or_province_name));
- fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COUNTRY_NAME,
- new base::StringValue(subject.country_name));
+ base::MakeUnique<base::StringValue>(subject.locality_name));
fields->SetField(
- PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_NAME,
- new base::StringValue(
- base::JoinString(subject.organization_names, "\n")));
- fields->SetField(
- PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_UNIT_NAME,
- new base::StringValue(
- base::JoinString(subject.organization_unit_names, "\n")));
+ PP_X509CERTIFICATE_PRIVATE_SUBJECT_STATE_OR_PROVINCE_NAME,
+ base::MakeUnique<base::StringValue>(subject.state_or_province_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COUNTRY_NAME,
+ base::MakeUnique<base::StringValue>(subject.country_name));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_NAME,
+ base::MakeUnique<base::StringValue>(
+ base::JoinString(subject.organization_names, "\n")));
+ fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_UNIT_NAME,
+ base::MakeUnique<base::StringValue>(base::JoinString(
+ subject.organization_unit_names, "\n")));
const std::string& serial_number = cert.serial_number();
fields->SetField(PP_X509CERTIFICATE_PRIVATE_SERIAL_NUMBER,
base::BinaryValue::CreateWithCopiedBuffer(
serial_number.data(), serial_number.length()));
- fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_BEFORE,
- new base::FundamentalValue(cert.valid_start().ToDoubleT()));
+ fields->SetField(
+ PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_BEFORE,
+ base::MakeUnique<base::FundamentalValue>(cert.valid_start().ToDoubleT()));
fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_AFTER,
- new base::FundamentalValue(cert.valid_expiry().ToDoubleT()));
+ base::MakeUnique<base::FundamentalValue>(
+ cert.valid_expiry().ToDoubleT()));
std::string der;
net::X509Certificate::GetDEREncoded(cert.os_cert_handle(), &der);
fields->SetField(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
index 8dde061e128..23dea67f2cc 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -334,6 +334,9 @@ int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
ssl_context.transport_security_state =
ssl_context_helper_->GetTransportSecurityState();
+ ssl_context.cert_transparency_verifier =
+ ssl_context_helper_->GetCertTransparencyVerifier();
+ ssl_context.ct_policy_enforcer = ssl_context_helper_->GetCTPolicyEnforcer();
ssl_socket_ = factory->CreateSSLClientSocket(
std::move(handle), host_port_pair, ssl_context_helper_->ssl_config(),
ssl_context);
diff --git a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
index aed88230391..0596302ce3a 100644
--- a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
+++ b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
@@ -5,6 +5,8 @@
#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
#include "net/cert/cert_verifier.h"
+#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/multi_log_ct_verifier.h"
#include "net/http/transport_security_state.h"
namespace content {
@@ -25,4 +27,16 @@ net::TransportSecurityState* SSLContextHelper::GetTransportSecurityState() {
return transport_security_state_.get();
}
+net::CTVerifier* SSLContextHelper::GetCertTransparencyVerifier() {
+ if (!cert_transparency_verifier_)
+ cert_transparency_verifier_.reset(new net::MultiLogCTVerifier());
+ return cert_transparency_verifier_.get();
+}
+
+net::CTPolicyEnforcer* SSLContextHelper::GetCTPolicyEnforcer() {
+ if (!ct_policy_enforcer_)
+ ct_policy_enforcer_.reset(new net::CTPolicyEnforcer());
+ return ct_policy_enforcer_.get();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h
index c83afa42331..d2b880ec96e 100644
--- a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h
+++ b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h
@@ -13,6 +13,8 @@
namespace net {
class CertVerifier;
+class CTPolicyEnforcer;
+class CTVerifier;
class TransportSecurityState;
}
@@ -24,6 +26,8 @@ class SSLContextHelper : public base::RefCounted<SSLContextHelper> {
net::CertVerifier* GetCertVerifier();
net::TransportSecurityState* GetTransportSecurityState();
+ net::CTVerifier* GetCertTransparencyVerifier();
+ net::CTPolicyEnforcer* GetCTPolicyEnforcer();
const net::SSLConfig& ssl_config() { return ssl_config_; }
private:
@@ -36,6 +40,12 @@ class SSLContextHelper : public base::RefCounted<SSLContextHelper> {
// This is lazily created. Users should use GetTransportSecurityState to
// retrieve it.
std::unique_ptr<net::TransportSecurityState> transport_security_state_;
+ // This is lazily created. Users should use GetCertTransparencyVerifier to
+ // retrieve it.
+ std::unique_ptr<net::CTVerifier> cert_transparency_verifier_;
+ // This is lazily created. Users should use GetCTPolicyEnforcer to
+ // retrieve it.
+ std::unique_ptr<net::CTPolicyEnforcer> ct_policy_enforcer_;
// The default SSL configuration settings are used, as opposed to Chrome's SSL
// settings.
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index 172a80de0e8..3843d8865b2 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -23,6 +23,7 @@
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
@@ -49,8 +50,6 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/download_manager.h"
-#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
@@ -71,8 +70,6 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/file_type_conversion.h"
-#include "storage/browser/blob/blob_storage_context.h"
-#include "ui/gfx/color_profile.h"
#include "url/gurl.h"
#if defined(OS_MACOSX)
@@ -102,14 +99,6 @@ const uint32_t kFilteredMessageClasses[] = {
ChildProcessMsgStart, RenderProcessMsgStart, ViewMsgStart,
};
-#if defined(OS_WIN)
-// On Windows, |g_color_profile| can run on an arbitrary background thread.
-// We avoid races by using LazyInstance's constructor lock to initialize the
-// object.
-base::LazyInstance<gfx::ColorProfile>::Leaky g_color_profile =
- LAZY_INSTANCE_INITIALIZER;
-#endif
-
#if defined(OS_MACOSX)
void ResizeHelperHandleMsgOnUIThread(int render_process_id,
const IPC::Message& message) {
@@ -127,22 +116,9 @@ void ResizeHelperPostMsgToUIThread(int render_process_id,
}
#endif
-void DownloadUrlOnUIThread(std::unique_ptr<DownloadUrlParameters> parameters) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- RenderProcessHost* render_process_host =
- RenderProcessHost::FromID(parameters->render_process_host_id());
- if (!render_process_host)
- return;
-
- BrowserContext* browser_context = render_process_host->GetBrowserContext();
- DownloadManager* download_manager =
- BrowserContext::GetDownloadManager(browser_context);
- RecordDownloadSource(INITIATED_BY_RENDERER);
- download_manager->DownloadUrl(std::move(parameters));
-}
-
-void NoOpCacheStorageErrorCallback(CacheStorageError error) {}
+void NoOpCacheStorageErrorCallback(
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ CacheStorageError error) {}
} // namespace
@@ -194,9 +170,6 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget)
IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget,
OnCreateFullscreenWidget)
- IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SaveImageFromDataURL,
- OnSaveImageFromDataURL)
#if defined(OS_MACOSX)
// On Mac, the IPCs ViewHostMsg_SwapCompositorFrame, ViewHostMsg_UpdateRect,
// and GpuCommandBufferMsg_SwapBuffersCompleted need to be handled in a
@@ -246,8 +219,6 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
#elif defined(OS_WIN)
IPC_MESSAGE_HANDLER(RenderProcessHostMsg_PreCacheFontCharacters,
OnPreCacheFontCharacters)
- IPC_MESSAGE_HANDLER(RenderProcessHostMsg_GetMonitorColorProfile,
- OnGetMonitorColorProfile)
#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvents, OnMediaLogEvents)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -269,11 +240,6 @@ void RenderMessageFilter::OverrideThreadForMessage(const IPC::Message& message,
base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& message) {
-#if defined(OS_WIN)
- // Windows monitor profile must be read from a file.
- if (message.type() == RenderProcessHostMsg_GetMonitorColorProfile::ID)
- return BrowserThread::GetBlockingPool();
-#endif
// Always query audio device parameters on the audio thread.
if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID)
return audio_manager_->GetTaskRunner();
@@ -412,68 +378,9 @@ void RenderMessageFilter::OnPreCacheFontCharacters(
DeleteEnhMetaFile(metafile);
}
-void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
- *profile = g_color_profile.Get().profile();
-}
#endif // OS_*
-void RenderMessageFilter::DownloadUrl(int render_view_id,
- int render_frame_id,
- const GURL& url,
- const Referrer& referrer,
- const base::string16& suggested_name,
- const bool use_prompt) const {
- if (!resource_context_)
- return;
-
- std::unique_ptr<DownloadUrlParameters> parameters(
- new DownloadUrlParameters(url, render_process_id_, render_view_id,
- render_frame_id, request_context_.get()));
- parameters->set_content_initiated(true);
- parameters->set_suggested_name(suggested_name);
- parameters->set_prompt(use_prompt);
- parameters->set_referrer(referrer);
-
- if (url.SchemeIsBlob()) {
- ChromeBlobStorageContext* blob_context =
- GetChromeBlobStorageContextForResourceContext(resource_context_);
- parameters->set_blob_data_handle(
- blob_context->context()->GetBlobDataFromPublicURL(url));
- // Don't care if the above fails. We are going to let the download go
- // through and allow it to be interrupted so that the embedder can deal.
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadUrlOnUIThread, base::Passed(&parameters)));
-}
-
-void RenderMessageFilter::OnDownloadUrl(int render_view_id,
- int render_frame_id,
- const GURL& url,
- const Referrer& referrer,
- const base::string16& suggested_name) {
- DownloadUrl(render_view_id, render_frame_id, url, referrer, suggested_name,
- false);
-}
-
-void RenderMessageFilter::OnSaveImageFromDataURL(int render_view_id,
- int render_frame_id,
- const std::string& url_str) {
- // Please refer to RenderViewImpl::saveImageFromDataURL().
- if (url_str.length() >= kMaxLengthOfDataURLString)
- return;
-
- GURL data_url(url_str);
- if (!data_url.SchemeIs(url::kDataScheme))
- return;
-
- DownloadUrl(render_view_id, render_frame_id, data_url, Referrer(),
- base::string16(), true);
-}
-
void RenderMessageFilter::AllocateSharedMemoryOnFileThread(
uint32_t buffer_size,
IPC::Message* reply_msg) {
@@ -612,12 +519,16 @@ void RenderMessageFilter::OnCacheStorageOpenCallback(
base::Time expected_response_time,
scoped_refptr<net::IOBuffer> buf,
int buf_len,
- scoped_refptr<CacheStorageCache> cache,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error) {
- if (error != CACHE_STORAGE_OK)
+ if (error != CACHE_STORAGE_OK || !cache_handle || !cache_handle->value())
+ return;
+ CacheStorageCache* cache = cache_handle->value();
+ if (!cache)
return;
- cache->WriteSideData(base::Bind(&NoOpCacheStorageErrorCallback), url,
- expected_response_time, buf, buf_len);
+ cache->WriteSideData(base::Bind(&NoOpCacheStorageErrorCallback,
+ base::Passed(std::move(cache_handle))),
+ url, expected_response_time, buf, buf_len);
}
void RenderMessageFilter::OnKeygen(uint32_t key_size_index,
diff --git a/chromium/content/browser/renderer_host/render_message_filter.h b/chromium/content/browser/renderer_host/render_message_filter.h
index d27bb692611..fa55e944297 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.h
+++ b/chromium/content/browser/renderer_host/render_message_filter.h
@@ -40,7 +40,6 @@
#endif
#if defined(OS_MACOSX)
-#include <IOSurface/IOSurface.h>
#include "content/common/mac/font_loader.h"
#endif
@@ -90,13 +89,12 @@ class Origin;
namespace content {
class BrowserContext;
class CacheStorageContextImpl;
-class CacheStorageCache;
+class CacheStorageCacheHandle;
class DOMStorageContextWrapper;
class MediaInternals;
class RenderWidgetHelper;
class ResourceContext;
class ResourceDispatcherHostImpl;
-struct Referrer;
// This class filters out incoming IPC messages for the renderer process on the
// IPC thread.
@@ -125,14 +123,6 @@ class CONTENT_EXPORT RenderMessageFilter : public BrowserMessageFilter {
protected:
~RenderMessageFilter() override;
- // This method will be overridden by TestSaveImageFromDataURL class for test.
- virtual void DownloadUrl(int render_view_id,
- int render_frame_id,
- const GURL& url,
- const Referrer& referrer,
- const base::string16& suggested_name,
- const bool use_prompt) const;
-
private:
friend class BrowserThread;
friend class base::DeleteHelper<RenderMessageFilter>;
@@ -155,23 +145,10 @@ class CONTENT_EXPORT RenderMessageFilter : public BrowserMessageFilter {
#endif
void OnGenerateRoutingID(int* route_id);
- void OnDownloadUrl(int render_view_id,
- int render_frame_id,
- const GURL& url,
- const Referrer& referrer,
- const base::string16& suggested_name);
- void OnSaveImageFromDataURL(int render_view_id,
- int render_frame_id,
- const std::string& url_str);
void OnGetAudioHardwareConfig(media::AudioParameters* input_params,
media::AudioParameters* output_params);
-#if defined(OS_WIN)
- // Used to look up the monitor color profile.
- void OnGetMonitorColorProfile(std::vector<char>* profile);
-#endif
-
// Message handlers called on the browser IO thread:
void OnEstablishGpuChannel(CauseForGpuLaunch, IPC::Message* reply);
void OnHasGpuProcess(IPC::Message* reply);
@@ -220,12 +197,13 @@ class CONTENT_EXPORT RenderMessageFilter : public BrowserMessageFilter {
const std::vector<char>& data,
const url::Origin& cache_storage_origin,
const std::string& cache_storage_cache_name);
- void OnCacheStorageOpenCallback(const GURL& url,
- base::Time expected_response_time,
- scoped_refptr<net::IOBuffer> buf,
- int buf_len,
- scoped_refptr<CacheStorageCache> cache,
- CacheStorageError error);
+ void OnCacheStorageOpenCallback(
+ const GURL& url,
+ base::Time expected_response_time,
+ scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ CacheStorageError error);
void OnKeygen(uint32_t key_size_index,
const std::string& challenge_string,
const GURL& url,
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 e0c4d27a236..56eaf762b93 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
#include "base/command_line.h"
+#include "base/run_loop.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/child_process_messages.h"
@@ -14,8 +16,11 @@
#include "content/public/common/url_constants.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_mojo_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"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
@@ -42,11 +47,17 @@ class RenderProcessHostTest : public ContentBrowserTest,
RenderProcessHostTest() : process_exits_(0), host_destructions_(0) {}
protected:
+ void set_process_exit_callback(const base::Closure& callback) {
+ process_exit_callback_ = callback;
+ }
+
// RenderProcessHostObserver:
void RenderProcessExited(RenderProcessHost* host,
base::TerminationStatus status,
int exit_code) override {
++process_exits_;
+ if (!process_exit_callback_.is_null())
+ process_exit_callback_.Run();
}
void RenderProcessHostDestroyed(RenderProcessHost* host) override {
++host_destructions_;
@@ -54,6 +65,7 @@ class RenderProcessHostTest : public ContentBrowserTest,
int process_exits_;
int host_destructions_;
+ base::Closure process_exit_callback_;
};
// Sometimes the renderer process's ShutdownRequest (corresponding to the
@@ -198,5 +210,34 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
}
}
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessOnBadMojoMessage) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
+ NavigateToURL(shell(), test_url);
+ RenderProcessHost* rph =
+ shell()->web_contents()->GetRenderViewHost()->GetProcess();
+
+ host_destructions_ = 0;
+ process_exits_ = 0;
+ rph->AddObserver(this);
+
+ mojom::TestMojoServicePtr service;
+ rph->GetRemoteInterfaces()->GetInterface(&service);
+
+ base::RunLoop run_loop;
+ set_process_exit_callback(run_loop.QuitClosure());
+
+ // Should reply with a bad message and cause process death.
+ service->DoSomething(base::Bind(&base::DoNothing));
+
+ run_loop.Run();
+
+ EXPECT_EQ(1, process_exits_);
+ EXPECT_EQ(0, host_destructions_);
+ if (!host_destructions_)
+ rph->RemoveObserver(this);
+}
+
} // namespace
} // namespace content
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 b518f4e6b25..febc934e3db 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -39,19 +39,20 @@
#include "base/sys_info.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "base/tracked_objects.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/scheduler/common/scheduler_switches.h"
-#include "components/tracing/tracing_switches.h"
+#include "components/tracing/common/tracing_switches.h"
+#include "components/webmessaging/broadcast_channel_provider.h"
#include "content/browser/appcache/appcache_dispatcher_host.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/background_sync/background_sync_service_impl.h"
#include "content/browser/bad_message.h"
#include "content/browser/blob_storage/blob_dispatcher_host.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/bluetooth/bluetooth_dispatcher_host.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/browser_main.h"
#include "content/browser/browser_main_loop.h"
@@ -83,11 +84,11 @@
#include "content/browser/media/midi_host.h"
#include "content/browser/memory/memory_message_filter.h"
#include "content/browser/message_port_message_filter.h"
-#include "content/browser/mime_registry_message_filter.h"
+#include "content/browser/mime_registry_impl.h"
#include "content/browser/mojo/constants.h"
-#include "content/browser/mojo/mojo_application_host.h"
#include "content/browser/mojo/mojo_child_connection.h"
#include "content/browser/notifications/notification_message_filter.h"
+#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/permissions/permission_service_impl.h"
#include "content/browser/profiler_message_filter.h"
@@ -102,6 +103,7 @@
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
+#include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
#include "content/browser/renderer_host/render_message_filter.h"
@@ -163,9 +165,9 @@
#include "ipc/attachment_broker.h"
#include "ipc/attachment_broker_privileged.h"
#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_mojo.h"
#include "ipc/ipc_logging.h"
#include "ipc/ipc_switches.h"
-#include "ipc/mojo/ipc_channel_mojo.h"
#include "media/base/media_switches.h"
#include "mojo/edk/embedder/embedder.h"
#include "net/url_request/url_request_context_getter.h"
@@ -231,6 +233,10 @@
#include "content/common/media/media_stream_messages.h"
#endif
+#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
+#include "components/mus/common/switches.h" // nogncheck
+#endif
+
#if defined(OS_WIN)
#define IntToStringType base::IntToString16
#else
@@ -536,7 +542,7 @@ RenderProcessHostImpl::RenderProcessHostImpl(
is_self_deleted_(false),
#endif
pending_views_(0),
- mojo_application_host_(new MojoApplicationHost),
+ child_token_(mojo::edk::GenerateRandomToken()),
visible_widgets_(0),
is_process_backgrounded_(false),
is_initialized_(false),
@@ -556,7 +562,8 @@ RenderProcessHostImpl::RenderProcessHostImpl(
channel_connected_(false),
sent_render_process_ready_(false),
#if defined(OS_ANDROID)
- never_signaled_(true, false),
+ never_signaled_(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
#endif
weak_factory_(this) {
widget_helper_ = new RenderWidgetHelper();
@@ -594,6 +601,29 @@ RenderProcessHostImpl::RenderProcessHostImpl(
IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded();
#endif // defined(OS_MACOSX)
#endif // USE_ATTACHMENT_BROKER
+
+ shell::Connector* connector =
+ BrowserContext::GetShellConnectorFor(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
+ // MojoShellConnection prior to this point. This class of test code doesn't
+ // care about render processes so we can initialize a dummy one.
+ if (!MojoShellConnection::GetForProcess()) {
+ shell::mojom::ShellClientRequest request =
+ mojo::GetProxy(&test_shell_client_);
+ MojoShellConnection::SetForProcess(MojoShellConnection::Create(
+ std::move(request)));
+ }
+ connector = MojoShellConnection::GetForProcess()->GetConnector();
+ }
+ mojo_child_connection_.reset(new MojoChildConnection(
+ kRendererMojoApplicationName,
+ base::StringPrintf("%d_%d", id_, instance_id_++),
+ child_token_,
+ connector));
}
// static
@@ -672,10 +702,6 @@ bool RenderProcessHostImpl::Init() {
if (channel_)
return true;
- mojo_child_connection_.reset(new MojoChildConnection(
- kRendererMojoApplicationName,
- base::StringPrintf("%d_%d", id_, instance_id_++)));
-
base::CommandLine::StringType renderer_prefix;
// A command prefix is something prepended to the command line of the spawned
// process.
@@ -709,7 +735,7 @@ bool RenderProcessHostImpl::Init() {
GetContentClient()->browser()->RenderProcessWillLaunch(this);
CreateMessageFilters();
- RegisterMojoServices();
+ RegisterMojoInterfaces();
if (run_renderer_in_process()) {
DCHECK(g_renderer_main_thread_factory);
@@ -724,7 +750,8 @@ bool RenderProcessHostImpl::Init() {
channel_id,
BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
->task_runner(),
- mojo_channel_token_, mojo_application_host_->GetToken())));
+ mojo_channel_token_,
+ mojo_child_connection_->shell_client_token())));
base::Thread::Options options;
#if defined(OS_WIN) && !defined(OS_MACOSX)
@@ -760,7 +787,10 @@ bool RenderProcessHostImpl::Init() {
// at this stage.
child_process_launcher_.reset(new ChildProcessLauncher(
new RendererSandboxedProcessLauncherDelegate(channel_.get()), cmd_line,
- GetID(), this));
+ GetID(), this, child_token_,
+ base::Bind(&RenderProcessHostImpl::OnMojoError,
+ weak_factory_.GetWeakPtr(),
+ base::ThreadTaskRunnerHandle::Get())));
fast_shutdown_started_ = false;
}
@@ -783,7 +813,7 @@ std::unique_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
mojo_channel_token_ = mojo::edk::GenerateRandomToken();
mojo::ScopedMessagePipeHandle handle =
- mojo::edk::CreateParentMessagePipe(mojo_channel_token_);
+ mojo::edk::CreateParentMessagePipe(mojo_channel_token_, child_token_);
// Do NOT expand ifdef or run time condition checks here! Synchronous
// IPCs from browser process are banned. It is only narrowly allowed
@@ -810,8 +840,6 @@ std::unique_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy(
void RenderProcessHostImpl::CreateMessageFilters() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- const base::CommandLine& browser_command_line =
- *base::CommandLine::ForCurrentProcess();
AddFilter(new ResourceSchedulerFilter(GetID()));
MediaInternals* media_internals = MediaInternals::GetInstance();
media::AudioManager* audio_manager =
@@ -914,11 +942,10 @@ void RenderProcessHostImpl::CreateMessageFilters() {
blob_storage_context.get(), StreamContext::GetFor(browser_context)));
AddFilter(new BlobDispatcherHost(blob_storage_context.get()));
AddFilter(new FileUtilitiesMessageFilter(GetID()));
- AddFilter(new MimeRegistryMessageFilter());
AddFilter(
new DatabaseMessageFilter(storage_partition_impl_->GetDatabaseTracker()));
#if defined(OS_MACOSX)
- AddFilter(new TextInputClientMessageFilter(GetID()));
+ AddFilter(new TextInputClientMessageFilter());
#elif defined(OS_WIN)
AddFilter(new DWriteFontProxyMessageFilter());
@@ -1004,48 +1031,54 @@ void RenderProcessHostImpl::CreateMessageFilters() {
#if defined(OS_ANDROID)
AddFilter(new ScreenOrientationMessageFilterAndroid());
#endif
-
- bool enable_web_bluetooth =
- browser_command_line.HasSwitch(switches::kEnableWebBluetooth);
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
- enable_web_bluetooth = true;
-#endif
-
- if (enable_web_bluetooth) {
- bluetooth_dispatcher_host_ = new BluetoothDispatcherHost(GetID());
- AddFilter(bluetooth_dispatcher_host_.get());
- }
}
-void RenderProcessHostImpl::RegisterMojoServices() {
+void RenderProcessHostImpl::RegisterMojoInterfaces() {
#if !defined(OS_ANDROID)
- mojo_application_host_->service_registry()->AddService(
+ GetInterfaceRegistry()->AddInterface(
base::Bind(&device::BatteryMonitorImpl::Create));
#endif
- mojo_application_host_->service_registry()->AddService(
+ GetInterfaceRegistry()->AddInterface(
base::Bind(&PermissionServiceContext::CreateService,
base::Unretained(permission_service_context_.get())));
// TODO(mcasas): finalize arguments.
- mojo_application_host_->service_registry()->AddService(
+ GetInterfaceRegistry()->AddInterface(
base::Bind(&ImageCaptureImpl::Create));
- mojo_application_host_->service_registry()->AddService(base::Bind(
+ GetInterfaceRegistry()->AddInterface(
+ base::Bind(&OffscreenCanvasSurfaceImpl::Create));
+
+ GetInterfaceRegistry()->AddInterface(base::Bind(
&BackgroundSyncContext::CreateService,
base::Unretained(storage_partition_impl_->GetBackgroundSyncContext())));
- mojo_application_host_->service_registry()->AddService(
+ GetInterfaceRegistry()->AddInterface(base::Bind(
+ &PlatformNotificationContextImpl::CreateService,
+ base::Unretained(
+ storage_partition_impl_->GetPlatformNotificationContext()), GetID()));
+
+ GetInterfaceRegistry()->AddInterface(
base::Bind(&RenderProcessHostImpl::CreateStoragePartitionService,
base::Unretained(this)));
+ GetInterfaceRegistry()->AddInterface(
+ base::Bind(&webmessaging::BroadcastChannelProvider::Connect,
+ base::Unretained(
+ storage_partition_impl_->GetBroadcastChannelProvider())));
+
+ GetInterfaceRegistry()->AddInterface(
+ base::Bind(&MimeRegistryImpl::Create),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
+
#if defined(OS_ANDROID)
ServiceRegistrarAndroid::RegisterProcessHostServices(
- mojo_application_host_->service_registry_android());
+ mojo_child_connection_->service_registry_android());
#endif
- GetContentClient()->browser()->RegisterRenderProcessMojoServices(
- mojo_application_host_->service_registry());
+ GetContentClient()->browser()->ExposeInterfacesToRenderer(
+ GetInterfaceRegistry(), this);
}
void RenderProcessHostImpl::CreateStoragePartitionService(
@@ -1070,9 +1103,12 @@ void RenderProcessHostImpl::NotifyTimezoneChange(const std::string& zone_id) {
Send(new ViewMsg_TimezoneChange(zone_id));
}
-ServiceRegistry* RenderProcessHostImpl::GetServiceRegistry() {
- DCHECK(mojo_application_host_);
- return mojo_application_host_->service_registry();
+shell::InterfaceRegistry* RenderProcessHostImpl::GetInterfaceRegistry() {
+ return GetChildConnection()->GetInterfaceRegistry();
+}
+
+shell::InterfaceProvider* RenderProcessHostImpl::GetRemoteInterfaces() {
+ return GetChildConnection()->GetRemoteInterfaces();
}
shell::Connection* RenderProcessHostImpl::GetChildConnection() {
@@ -1281,8 +1317,7 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
switches::kRendererProcess);
#if defined(OS_WIN)
- if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument())
- command_line->AppendArg(switches::kPrefetchArgumentRenderer);
+ command_line->AppendArg(switches::kPrefetchArgumentRenderer);
#endif // defined(OS_WIN)
// Now send any options from our own command line we want to propagate.
@@ -1314,7 +1349,7 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
mojo_channel_token_);
}
command_line->AppendSwitchASCII(switches::kMojoApplicationChannelToken,
- mojo_application_host_->GetToken());
+ mojo_child_connection_->shell_client_token());
}
void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
@@ -1330,6 +1365,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kAudioBufferSize,
switches::kBlinkPlatformLogChannels,
switches::kBlinkSettings,
+ switches::kCastEncoderUtilHeuristic,
switches::kDefaultTileWidth,
switches::kDefaultTileHeight,
switches::kDisable2dCanvasImageChromium,
@@ -1372,7 +1408,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableTouchDragDrop,
switches::kDisableV8IdleTasks,
switches::kDisableWebGLImageChromium,
- switches::kDisableWheelGestures,
switches::kDomAutomationController,
switches::kEnableBlinkFeatures,
switches::kEnableBrowserSideNavigation,
@@ -1408,13 +1443,14 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableUnsafeES3APIs,
switches::kEnableUseZoomForDSF,
switches::kEnableViewport,
+ switches::kEnableVp9InMp4,
switches::kEnableVtune,
switches::kEnableWebBluetooth,
switches::kEnableWebFontsInterventionTrigger,
+ switches::kEnableWebFontsInterventionV2,
switches::kEnableWebGLDraftExtensions,
switches::kEnableWebGLImageChromium,
switches::kEnableWebVR,
- switches::kEnableWheelGestures,
switches::kExplicitlyAllowedPorts,
switches::kForceDeviceScaleFactor,
switches::kForceDisplayList2dCanvas,
@@ -1518,6 +1554,14 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if defined(OS_CHROMEOS)
switches::kDisableVaapiAcceleratedVideoEncode,
#endif
+#if defined(ENABLE_IPC_FUZZER)
+ switches::kIpcDumpDirectory,
+ switches::kIpcFuzzerTestcase,
+#endif
+#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
+ switches::kUseMusInRenderer,
+ mus::switches::kUseMojoGpuCommandBufferInMus,
+#endif
};
renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
arraysize(kSwitchNames));
@@ -1866,7 +1910,7 @@ void RenderProcessHostImpl::Cleanup() {
#ifndef NDEBUG
is_self_deleted_ = true;
#endif
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
deleting_soon_ = true;
#if USE_ATTACHMENT_BROKER
@@ -1886,14 +1930,6 @@ void RenderProcessHostImpl::Cleanup() {
RemoveUserData(kSessionStorageHolderKey);
- // On shutdown, |this| may not be deleted because the deleter is posted to
- // the current MessageLoop, but MessageLoop deletes all its pending
- // callbacks on shutdown. Since the deleter takes |this| as a raw pointer,
- // deleting the callback doesn't delete |this| resulting in a memory leak.
- // Valgrind complains, so delete |mojo_application_host_| explicitly here to
- // stop valgrind from complaining.
- mojo_application_host_.reset();
-
// Remove ourself from the list of renderer processes so that we can't be
// reused in between now and when the Delete task runs.
UnregisterHost(GetID());
@@ -2389,7 +2425,16 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
// RenderProcessExited observers and RenderProcessGone handlers might
// navigate or perform other actions that require a connection. Ensure that
// there is one before calling them.
- mojo_application_host_.reset(new MojoApplicationHost);
+ child_token_ = mojo::edk::GenerateRandomToken();
+ shell::Connector* connector =
+ BrowserContext::GetShellConnectorFor(browser_context_);
+ if (!connector)
+ connector = MojoShellConnection::GetForProcess()->GetConnector();
+ mojo_child_connection_.reset(new MojoChildConnection(
+ kRendererMojoApplicationName,
+ base::StringPrintf("%d_%d", id_, instance_id_++),
+ child_token_,
+ connector));
within_process_died_observer_ = true;
NotificationService::current()->Notify(
@@ -2749,8 +2794,9 @@ void RenderProcessHostImpl::GetAudioOutputControllers(
audio_renderer_host()->GetOutputControllers(callback);
}
-BluetoothDispatcherHost* RenderProcessHostImpl::GetBluetoothDispatcherHost() {
- return bluetooth_dispatcher_host_.get();
+BluetoothAdapterFactoryWrapper*
+RenderProcessHostImpl::GetBluetoothAdapterFactoryWrapper() {
+ return &bluetooth_adapter_factory_wrapper_;
}
void RenderProcessHostImpl::RecomputeAndUpdateWebKitPreferences() {
@@ -2770,4 +2816,25 @@ void RenderProcessHostImpl::RecomputeAndUpdateWebKitPreferences() {
}
}
+// static
+void RenderProcessHostImpl::OnMojoError(
+ base::WeakPtr<RenderProcessHostImpl> process,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const std::string& error) {
+ if (!task_runner->BelongsToCurrentThread()) {
+ task_runner->PostTask(FROM_HERE,
+ base::Bind(&RenderProcessHostImpl::OnMojoError,
+ process, task_runner, error));
+ }
+ if (!process)
+ return;
+ LOG(ERROR) << "Terminating render process for bad Mojo message: " << error;
+
+ // The ReceivedBadMessage call below will trigger a DumpWithoutCrashing. Alias
+ // enough information here so that we can determine what the bad message was.
+ base::debug::Alias(&error);
+ bad_message::ReceivedBadMessage(process.get(),
+ bad_message::RPH_MOJO_PROCESS_ERROR);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.h b/chromium/content/browser/renderer_host/render_process_host_impl.h
index e46e2c51125..d28ea5a3e63 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -17,17 +17,19 @@
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/process/process.h"
+#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "build/build_config.h"
+#include "content/browser/bluetooth/bluetooth_adapter_factory_wrapper.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/common/content_export.h"
-#include "content/common/mojo/service_registry_impl.h"
#include "content/public/browser/render_process_host.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_platform_file.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "services/shell/public/interfaces/shell_client.mojom.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gl/gpu_switching_observer.h"
@@ -47,12 +49,10 @@ class ChannelMojoHost;
namespace content {
class AudioInputRendererHost;
class AudioRendererHost;
-class BluetoothDispatcherHost;
class BrowserCdmManager;
class BrowserDemuxerAndroid;
class InProcessChildThreadParams;
class MessagePortMessageFilter;
-class MojoApplicationHost;
class MojoChildConnection;
class NotificationMessageFilter;
#if defined(ENABLE_WEBRTC)
@@ -155,7 +155,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
#endif
void ResumeDeferredNavigation(const GlobalRequestID& request_id) override;
void NotifyTimezoneChange(const std::string& timezone) override;
- ServiceRegistry* GetServiceRegistry() override;
+ shell::InterfaceRegistry* GetInterfaceRegistry() override;
+ shell::InterfaceProvider* GetRemoteInterfaces() override;
shell::Connection* GetChildConnection() override;
std::unique_ptr<base::SharedPersistentMemoryAllocator> TakeMetricsAllocator()
override;
@@ -261,7 +262,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
void GetAudioOutputControllers(
const GetAudioOutputControllersCallback& callback) const override;
- BluetoothDispatcherHost* GetBluetoothDispatcherHost();
+ BluetoothAdapterFactoryWrapper* GetBluetoothAdapterFactoryWrapper();
#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
// Launch the zygote early in the browser startup.
@@ -291,8 +292,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
int32_t pending_views_;
private:
- friend class VisitRelayingRenderProcessHost;
friend class ChildProcessLauncherBrowserTest_ChildSpawnFail_Test;
+ friend class VisitRelayingRenderProcessHost;
std::unique_ptr<IPC::ChannelProxy> CreateChannelProxy(
const std::string& channel_id);
@@ -300,8 +301,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Creates and adds the IO thread message filters.
void CreateMessageFilters();
- // Registers Mojo services to be exposed to the renderer.
- void RegisterMojoServices();
+ // Registers Mojo interfaces to be exposed to the renderer.
+ void RegisterMojoInterfaces();
void CreateStoragePartitionService(
mojo::InterfaceRequest<mojom::StoragePartitionService> request);
@@ -362,8 +363,15 @@ class CONTENT_EXPORT RenderProcessHostImpl
base::FilePath GetEventLogFilePathWithExtensions(const base::FilePath& file);
#endif
+ static void OnMojoError(
+ base::WeakPtr<RenderProcessHostImpl> process,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const std::string& error);
+
+ std::string child_token_;
+
std::unique_ptr<MojoChildConnection> mojo_child_connection_;
- std::unique_ptr<MojoApplicationHost> mojo_application_host_;
+ shell::mojom::ShellClientPtr test_shell_client_;
// The registered IPC listener objects. When this list is empty, we should
// delete ourselves.
@@ -467,7 +475,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
scoped_refptr<AudioInputRendererHost> audio_input_renderer_host_;
- scoped_refptr<BluetoothDispatcherHost> bluetooth_dispatcher_host_;
+ BluetoothAdapterFactoryWrapper bluetooth_adapter_factory_wrapper_;
#if defined(OS_ANDROID)
scoped_refptr<BrowserDemuxerAndroid> browser_demuxer_android_;
diff --git a/chromium/content/browser/renderer_host/render_view_host_browsertest.cc b/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
index 5e14d47d460..e593e8f3c9c 100644
--- a/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -108,7 +108,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostTest, BasicRenderFrameHost) {
EXPECT_TRUE(old_root->current_frame_host());
ShellAddedObserver new_shell_observer;
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "window.open();"));
+ EXPECT_TRUE(ExecuteScript(shell(), "window.open();"));
Shell* new_shell = new_shell_observer.GetShell();
FrameTreeNode* new_root = static_cast<WebContentsImpl*>(
new_shell->web_contents())->GetFrameTree()->root();
@@ -126,7 +126,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostTest, IsFocusedElementEditable) {
RenderViewHost* rvh = shell()->web_contents()->GetRenderViewHost();
EXPECT_FALSE(rvh->IsFocusedElementEditable());
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "focus_textfield();"));
+ EXPECT_TRUE(ExecuteScript(shell(), "focus_textfield();"));
EXPECT_TRUE(rvh->IsFocusedElementEditable());
}
@@ -145,7 +145,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostTest, MAYBE_ReleaseSessionOnCloseACK) {
// Make a new Shell, a seperate tab with it's own session namespace and
// have it start loading a url but still be in progress.
ShellAddedObserver new_shell_observer;
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "window.open();"));
+ EXPECT_TRUE(ExecuteScript(shell(), "window.open();"));
Shell* new_shell = new_shell_observer.GetShell();
new_shell->LoadURL(test_url);
RenderViewHost* rvh = new_shell->web_contents()->GetRenderViewHost();
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 984f854b6a7..1743d2f9bf1 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.h
@@ -146,11 +146,6 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// JavaScript window.focus() method).
virtual void Activate() {}
- // Called when a file selection is to be done.
- virtual void RunFileChooser(
- RenderViewHost* render_view_host,
- const FileChooserParams& params) {}
-
// The contents' preferred size changed.
virtual void UpdatePreferredSize(const gfx::Size& pref_size) {}
@@ -198,18 +193,20 @@ class CONTENT_EXPORT RenderViewHostDelegate {
//
// Note: this is not called "ShowWindow" because that will clash with
// the Windows function which is actually a #define.
- virtual void ShowCreatedWindow(int route_id,
+ virtual void ShowCreatedWindow(int process_id,
+ int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) {}
// Show the newly created widget with the specified bounds.
// The widget is identified by the route_id passed to CreateNewWidget.
- virtual void ShowCreatedWidget(int route_id,
+ virtual void ShowCreatedWidget(int process_id,
+ int route_id,
const gfx::Rect& initial_rect) {}
// Show the newly created full screen widget. Similar to above.
- virtual void ShowCreatedFullscreenWidget(int route_id) {}
+ virtual void ShowCreatedFullscreenWidget(int process_id, int route_id) {}
// Returns the SessionStorageNamespace the render view should use. Might
// create the SessionStorageNamespace on the fly.
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate_view.h b/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
index 56bed08ab49..3fdd338b3ea 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
@@ -65,7 +65,7 @@ class CONTENT_EXPORT RenderViewHostDelegateView {
// retrieved by doing a Shift-Tab.
virtual void TakeFocus(bool reverse) {}
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
// Shows a popup menu with the specified items.
// This method should call RenderFrameHost::DidSelectPopupMenuItem[s]() or
// RenderFrameHost::DidCancelPopupMenu() based on the user action.
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 c457e2c339f..bc7c7164a99 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -12,6 +12,7 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/debug/dump_without_crashing.h"
+#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/json/json_reader.h"
#include "base/message_loop/message_loop.h"
@@ -67,6 +68,7 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/common/bindings_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/context_menu_params.h"
#include "content/public/common/drop_data.h"
@@ -80,18 +82,20 @@
#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"
#include "ui/base/touch/touch_enabled.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/animation/animation.h"
+#include "ui/gfx/color_space.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/native_theme/native_theme_switches.h"
#include "url/url_constants.h"
#if defined(OS_WIN)
-#include "base/win/win_util.h"
#include "ui/display/win/dpi.h"
+#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/platform_font_win.h"
#endif
@@ -108,27 +112,6 @@ namespace content {
namespace {
#if defined(OS_WIN)
-
-const int kVirtualKeyboardDisplayWaitTimeoutMs = 100;
-const int kMaxVirtualKeyboardDisplayRetries = 5;
-
-void DismissVirtualKeyboardTask() {
- static int virtual_keyboard_display_retries = 0;
- // If the virtual keyboard is not yet visible, then we execute the task again
- // waiting for it to show up.
- if (!base::win::DismissVirtualKeyboard()) {
- if (virtual_keyboard_display_retries < kMaxVirtualKeyboardDisplayRetries) {
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(base::IgnoreResult(&DismissVirtualKeyboardTask)),
- TimeDelta::FromMilliseconds(kVirtualKeyboardDisplayWaitTimeoutMs));
- ++virtual_keyboard_display_retries;
- } else {
- virtual_keyboard_display_retries = 0;
- }
- }
-}
-
void GetWindowsSpecificPrefs(RendererPreferences* prefs) {
NONCLIENTMETRICS_XP metrics = {0};
base::win::GetNonClientMetrics(&metrics);
@@ -164,6 +147,56 @@ void GetWindowsSpecificPrefs(RendererPreferences* prefs) {
}
#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
// static
@@ -227,7 +260,6 @@ RenderViewHostImpl::RenderViewHostImpl(
is_waiting_for_close_ack_(false),
sudden_termination_allowed_(false),
render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING),
- virtual_keyboard_requested_(false),
is_focused_element_editable_(false),
updating_web_preferences_(false),
render_view_ready_on_process_launch_(false),
@@ -338,6 +370,8 @@ bool RenderViewHostImpl::CreateRenderView(
params.min_size = GetWidget()->min_size_for_auto_resize();
params.max_size = GetWidget()->max_size_for_auto_resize();
params.page_zoom_level = delegate_->GetPendingPageZoomLevel();
+ params.image_decode_color_profile =
+ gfx::ColorSpace::FromBestMonitor().GetICCProfile();
GetWidget()->GetResizeParams(&params.initial_size);
if (!Send(new ViewMsg_New(params)))
@@ -451,6 +485,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();
#endif
// Handle autoplay gesture override experiment.
@@ -537,7 +575,8 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
void RenderViewHostImpl::ClosePage() {
is_waiting_for_close_ack_ = true;
GetWidget()->StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
+ TimeDelta::FromMilliseconds(kUnloadTimeoutMS),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_CLOSE_PAGE);
if (IsRenderViewLive()) {
// Since we are sending an IPC message to the renderer, increase the event
@@ -591,94 +630,17 @@ void RenderViewHostImpl::DragTargetDragEnter(
const gfx::Point& screen_pt,
WebDragOperationsMask operations_allowed,
int key_modifiers) {
- 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 URL could have been cobbled together from any highlighted text string,
- // and can't be interpreted as a capability.
- DropData filtered_data(drop_data);
- GetProcess()->FilterURL(true, &filtered_data.url);
- if (drop_data.did_originate_from_renderer) {
- filtered_data.filenames.clear();
- }
-
- // The filenames vector, on the other hand, does represent a capability to
- // access the given files.
- storage::IsolatedContext::FileInfoSet files;
- for (std::vector<ui::FileInfo>::iterator iter(
- filtered_data.filenames.begin());
- iter != filtered_data.filenames.end();
- ++iter) {
- // 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.
-
- // Make sure we have the same display_name as the one we register.
- if (iter->display_name.empty()) {
- std::string name;
- files.AddPath(iter->path, &name);
- iter->display_name = base::FilePath::FromUTF8Unsafe(name);
- } else {
- files.AddPathWithName(iter->path, iter->display_name.AsUTF8Unsafe());
- }
-
- policy->GrantRequestSpecificFileURL(renderer_id,
- net::FilePathToFileURL(iter->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, iter->path))
- policy->GrantReadFile(renderer_id, iter->path);
- }
-
- storage::IsolatedContext* isolated_context =
- storage::IsolatedContext::GetInstance();
- DCHECK(isolated_context);
- 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);
- }
- filtered_data.filesystem_id = base::UTF8ToUTF16(filesystem_id);
-
- storage::FileSystemContext* file_system_context =
- BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
- GetSiteInstance())
- ->GetFileSystemContext();
- for (size_t i = 0; i < filtered_data.file_system_files.size(); ++i) {
- storage::FileSystemURL file_system_url =
- file_system_context->CrackURL(filtered_data.file_system_files[i].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);
- 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.
- filtered_data.file_system_files[i].url =
- GURL(storage::GetIsolatedFileSystemRootURIString(
- file_system_url.origin(), filesystem_id, std::string())
- .append(register_name));
- }
+ DragTargetDragEnterWithMetaData(DropDataToMetaData(drop_data), client_pt,
+ screen_pt, operations_allowed, key_modifiers);
+}
- Send(new DragMsg_TargetDragEnter(GetRoutingID(), filtered_data, client_pt,
+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));
}
@@ -696,12 +658,25 @@ void RenderViewHostImpl::DragTargetDragLeave() {
Send(new DragMsg_TargetDragLeave(GetRoutingID()));
}
-void RenderViewHostImpl::DragTargetDrop(
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- int key_modifiers) {
- Send(new DragMsg_TargetDrop(GetRoutingID(), client_pt, screen_pt,
- key_modifiers));
+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(
@@ -798,33 +773,6 @@ void RenderViewHostImpl::SetInitialFocus(bool reverse) {
Send(new ViewMsg_SetInitialFocus(GetRoutingID(), reverse));
}
-void RenderViewHostImpl::FilesSelectedInChooser(
- const std::vector<content::FileChooserFileInfo>& files,
- FileChooserParams::Mode permissions) {
- storage::FileSystemContext* const file_system_context =
- BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
- GetSiteInstance())
- ->GetFileSystemContext();
- // Grant the security access requested to the given files.
- for (size_t i = 0; i < files.size(); ++i) {
- const content::FileChooserFileInfo& file = files[i];
- if (permissions == FileChooserParams::Save) {
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantCreateReadWriteFile(
- GetProcess()->GetID(), file.file_path);
- } else {
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
- GetProcess()->GetID(), file.file_path);
- }
- if (file.file_system_url.is_valid()) {
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFileSystem(
- GetProcess()->GetID(),
- file_system_context->CrackURL(file.file_system_url)
- .mount_filesystem_id());
- }
- }
- Send(new ViewMsg_RunFileChooserResponse(GetRoutingID(), files));
-}
-
void RenderViewHostImpl::DirectoryEnumerationFinished(
int request_id,
const std::vector<base::FilePath>& files) {
@@ -912,7 +860,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL, OnDidZoomURL)
- IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser)
IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -968,19 +915,19 @@ void RenderViewHostImpl::OnShowView(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) {
- delegate_->ShowCreatedWindow(route_id, disposition, initial_rect,
- user_gesture);
+ delegate_->ShowCreatedWindow(GetProcess()->GetID(), route_id, disposition,
+ initial_rect, user_gesture);
Send(new ViewMsg_Move_ACK(route_id));
}
void RenderViewHostImpl::OnShowWidget(int route_id,
const gfx::Rect& initial_rect) {
- delegate_->ShowCreatedWidget(route_id, initial_rect);
+ delegate_->ShowCreatedWidget(GetProcess()->GetID(), route_id, initial_rect);
Send(new ViewMsg_Move_ACK(route_id));
}
void RenderViewHostImpl::OnShowFullscreenWidget(int route_id) {
- delegate_->ShowCreatedFullscreenWidget(route_id);
+ delegate_->ShowCreatedFullscreenWidget(GetProcess()->GetID(), route_id);
Send(new ViewMsg_Move_ACK(route_id));
}
@@ -1001,7 +948,9 @@ void RenderViewHostImpl::OnUpdateState(int32_t page_id,
// Without this check, the renderer can trick the browser into using
// filenames it can't access in a future session restore.
- if (!CanAccessFilesOfPageState(state)) {
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ int child_id = GetProcess()->GetID();
+ if (!policy->CanReadAllFiles(child_id, state.GetReferencedFiles())) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RVH_CAN_ACCESS_FILES_OF_PAGE_STATE);
return;
@@ -1127,16 +1076,6 @@ void RenderViewHostImpl::OnFocusedNodeChanged(
is_focused_element_editable_ = is_editable_node;
if (GetWidget()->GetView())
GetWidget()->GetView()->FocusedNodeChanged(is_editable_node);
-#if defined(OS_WIN)
- if (!is_editable_node && virtual_keyboard_requested_) {
- virtual_keyboard_requested_ = false;
- delegate_->SetIsVirtualKeyboardRequested(false);
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(base::IgnoreResult(&DismissVirtualKeyboardTask)),
- TimeDelta::FromMilliseconds(kVirtualKeyboardDisplayWaitTimeoutMs));
- }
-#endif
// None of the rest makes sense without a view.
if (!GetWidget()->GetView())
@@ -1251,14 +1190,6 @@ void RenderViewHostImpl::DisableAutoResize(const gfx::Size& new_size) {
GetWidget()->GetView()->SetSize(new_size);
}
-void RenderViewHostImpl::CopyImageAt(int x, int y) {
- Send(new ViewMsg_CopyImageAt(GetRoutingID(), x, y));
-}
-
-void RenderViewHostImpl::SaveImageAt(int x, int y) {
- Send(new ViewMsg_SaveImageAt(GetRoutingID(), x, y));
-}
-
void RenderViewHostImpl::ExecuteMediaPlayerActionAtLocation(
const gfx::Point& location, const blink::WebMediaPlayerAction& action) {
Send(new ViewMsg_MediaPlayerActionAt(GetRoutingID(), location, action));
@@ -1284,56 +1215,25 @@ void RenderViewHostImpl::OnDidZoomURL(double zoom_level,
net::GetHostOrSpecFromURL(url));
}
-void RenderViewHostImpl::OnRunFileChooser(const FileChooserParams& params) {
- // Do not allow messages with absolute paths in them as this can permit a
- // renderer to coerce the browser to perform I/O on a renderer controlled
- // path.
- if (params.default_file_name != params.default_file_name.BaseName()) {
- bad_message::ReceivedBadMessage(GetProcess(),
- bad_message::RVH_FILE_CHOOSER_PATH);
- return;
- }
-
- delegate_->RunFileChooser(this, params);
-}
-
void RenderViewHostImpl::OnFocusedNodeTouched(bool editable) {
#if defined(OS_WIN)
- if (editable) {
- virtual_keyboard_requested_ = base::win::DisplayVirtualKeyboard();
- delegate_->SetIsVirtualKeyboardRequested(true);
- } else {
- virtual_keyboard_requested_ = false;
- delegate_->SetIsVirtualKeyboardRequested(false);
- base::win::DismissVirtualKeyboard();
- }
+ // 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
}
-bool RenderViewHostImpl::CanAccessFilesOfPageState(
- const PageState& state) const {
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
-
- const std::vector<base::FilePath>& file_paths = state.GetReferencedFiles();
- for (const auto& file : file_paths) {
- if (!policy->CanReadFile(GetProcess()->GetID(), file))
- return false;
- }
- return true;
-}
-
-void RenderViewHostImpl::GrantFileAccessFromPageState(const PageState& state) {
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
-
- const std::vector<base::FilePath>& file_paths = state.GetReferencedFiles();
- for (const auto& file : file_paths) {
- if (!policy->CanReadFile(GetProcess()->GetID(), file))
- policy->GrantReadFile(GetProcess()->GetID(), file);
- }
-}
-
void RenderViewHostImpl::SelectWordAroundCaret() {
Send(new ViewMsg_SelectWordAroundCaret(GetRoutingID()));
}
@@ -1354,4 +1254,88 @@ 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 d54b2d7d573..5f850f244bf 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -98,8 +98,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
void AllowBindings(int binding_flags) override;
void ClearFocusedElement() override;
bool IsFocusedElementEditable() override;
- void CopyImageAt(int x, int y) override;
- void SaveImageAt(int x, int y) override;
void DirectoryEnumerationFinished(
int request_id,
const std::vector<base::FilePath>& files) override;
@@ -110,19 +108,31 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
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;
- void DragTargetDrop(const gfx::Point& client_pt,
+ // |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;
@@ -133,9 +143,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
void ExecutePluginActionAtLocation(
const gfx::Point& location,
const blink::WebPluginAction& action) override;
- void FilesSelectedInChooser(
- const std::vector<FileChooserFileInfo>& files,
- FileChooserParams::Mode permissions) override;
RenderViewHostDelegate* GetDelegate() const override;
int GetEnabledBindings() const override;
SiteInstanceImpl* GetSiteInstance() const override;
@@ -302,7 +309,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
const gfx::Rect& node_bounds_in_viewport);
void OnClosePageACK();
void OnDidZoomURL(double zoom_level, const GURL& url);
- void OnRunFileChooser(const FileChooserParams& params);
void OnFocusedNodeTouched(bool editable);
void OnFocus();
@@ -335,15 +341,11 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// See https://crbug.com/304341.
WebPreferences ComputeWebkitPrefs();
- // Returns whether the current RenderProcessHost has read access to the files
- // reported in |state|.
- bool CanAccessFilesOfPageState(const PageState& state) const;
-
- // Grants the current RenderProcessHost read access to any file listed in
- // |validated_state|. It is important that the PageState has been validated
- // upon receipt from the renderer process to prevent it from forging access to
- // files without the user's consent.
- void GrantFileAccessFromPageState(const PageState& validated_state);
+ // 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_;
@@ -393,9 +395,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// The termination status of the last render view that terminated.
base::TerminationStatus render_view_termination_status_;
- // Set to true if we requested the on screen keyboard to be displayed.
- bool virtual_keyboard_requested_;
-
// True if the current focused element is editable.
bool is_focused_element_editable_;
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 7e3746cea99..6e579595eff 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -9,7 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/renderer_host/render_message_filter.h"
+#include "content/browser/frame_host/render_frame_message_filter.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/common/frame_messages.h"
@@ -173,6 +173,7 @@ 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);
@@ -180,10 +181,11 @@ TEST_F(RenderViewHostTest, DragEnteredFileURLsStillBlocked) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
+ // Permissions are not granted at DragEnter.
EXPECT_FALSE(policy->CanRequestURL(id, highlighted_file_url));
EXPECT_FALSE(policy->CanReadFile(id, highlighted_file_path));
- EXPECT_TRUE(policy->CanRequestURL(id, dragged_file_url));
- EXPECT_TRUE(policy->CanReadFile(id, dragged_file_path));
+ EXPECT_FALSE(policy->CanRequestURL(id, dragged_file_url));
+ EXPECT_FALSE(policy->CanReadFile(id, dragged_file_path));
EXPECT_FALSE(policy->CanRequestURL(id, sensitive_file_url));
EXPECT_FALSE(policy->CanReadFile(id, sensitive_file_path));
}
@@ -242,18 +244,16 @@ TEST_F(RenderViewHostTest, RoutingIdSane) {
EXPECT_NE(test_rvh()->GetRoutingID(), root_rfh->routing_id());
}
-class TestSaveImageFromDataURL : public RenderMessageFilter {
+class TestSaveImageFromDataURL : public RenderFrameMessageFilter {
public:
TestSaveImageFromDataURL(BrowserContext* context)
- : RenderMessageFilter(0,
- context,
- BrowserContext::GetDefaultStoragePartition(context)
- ->GetURLRequestContext(),
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- nullptr) {
+ : RenderFrameMessageFilter(
+ 0,
+ nullptr,
+ context,
+ BrowserContext::GetDefaultStoragePartition(context)
+ ->GetURLRequestContext(),
+ nullptr) {
Reset();
}
@@ -271,7 +271,7 @@ class TestSaveImageFromDataURL : public RenderMessageFilter {
}
void Test(const std::string& url) {
- OnMessageReceived(ViewHostMsg_SaveImageFromDataURL(0, 0, url));
+ OnMessageReceived(FrameHostMsg_SaveImageFromDataURL(0, 0, url));
}
protected:
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 e08c7da3e47..abdf8fae62c 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -53,8 +53,7 @@ gfx::Rect RenderWidgetHostDelegate::GetRootWindowResizerRect(
return gfx::Rect();
};
-bool RenderWidgetHostDelegate::IsFullscreenForCurrentTab(
- RenderWidgetHostImpl* render_widget_host) const {
+bool RenderWidgetHostDelegate::IsFullscreenForCurrentTab() const {
return false;
}
@@ -63,4 +62,13 @@ blink::WebDisplayMode RenderWidgetHostDelegate::GetDisplayMode(
return blink::WebDisplayModeBrowser;
}
+bool RenderWidgetHostDelegate::HasMouseLock(
+ RenderWidgetHostImpl* render_widget_host) {
+ return false;
+}
+
+TextInputManager* RenderWidgetHostDelegate::GetTextInputManager() {
+ return nullptr;
+}
+
} // 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 aa38066ec28..58b52847ef7 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -31,6 +31,7 @@ namespace content {
class BrowserAccessibilityManager;
class RenderWidgetHostImpl;
class RenderWidgetHostInputEventRouter;
+class TextInputManager;
struct NativeWebKeyboardEvent;
//
@@ -132,9 +133,24 @@ 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) {}
+ virtual void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host,
+ RendererUnresponsiveType type) {}
// Notification that a previously unresponsive renderer has become
// responsive again. The delegate can use this notification to end the
@@ -143,10 +159,12 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// Requests to lock the mouse. Once the request is approved or rejected,
// GotResponseToLockMouseRequest() will be called on the requesting render
- // widget host.
+ // widget host. |privileged| means that the request is always granted, used
+ // for Pepper Flash.
virtual void RequestToLockMouse(RenderWidgetHostImpl* render_widget_host,
bool user_gesture,
- bool last_unlocked_by_target) {}
+ bool last_unlocked_by_target,
+ bool privileged) {}
// Return the rect where to display the resize corner, if any, otherwise
// an empty rect.
@@ -154,8 +172,7 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
RenderWidgetHostImpl* render_widget_host) const;
// Returns whether the associated tab is in fullscreen mode.
- virtual bool IsFullscreenForCurrentTab(
- RenderWidgetHostImpl* render_widget_host) const;
+ virtual bool IsFullscreenForCurrentTab() const;
// Returns the display mode for the view.
virtual blink::WebDisplayMode GetDisplayMode(
@@ -167,6 +184,9 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// Notification that the widget has lost the mouse lock.
virtual void LostMouseLock(RenderWidgetHostImpl* render_widget_host) {}
+ // Returns true if |render_widget_host| holds the mouse lock.
+ virtual bool HasMouseLock(RenderWidgetHostImpl* render_widget_host);
+
// Called when the widget has sent a compositor proto. This is used in Btlimp
// mode with the RemoteChannel compositor.
virtual void ForwardCompositorProto(RenderWidgetHostImpl* render_widget_host,
@@ -181,6 +201,14 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// Update the renderer's cache of the screen rect of the view and window.
virtual void SendScreenRects() {}
+ // Notifies that the main frame in the renderer has performed the first paint
+ // after a navigation.
+ virtual void OnFirstPaintAfterLoad(RenderWidgetHostImpl* render_widget_host) {
+ }
+
+ // Returns the TextInputManager tracking text input state.
+ virtual TextInputManager* GetTextInputManager();
+
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 46f640fd5e1..cfaa8b52e1c 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -7,6 +7,7 @@
#include <math.h>
#include <set>
+#include <tuple>
#include <utility>
#include "base/auto_reset.h"
@@ -46,7 +47,6 @@
#include "content/browser/renderer_host/render_process_host_impl.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_delegate.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_owner_delegate.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -75,12 +75,14 @@
#include "third_party/WebKit/public/web/WebCompositionUnderline.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/skbitmap_operations.h"
#include "ui/snapshot/snapshot.h"
#if defined(OS_MACOSX)
+#include "device/power_save_blocker/power_save_blocker.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#endif
@@ -187,7 +189,6 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
is_hidden_(hidden),
repaint_ack_pending_(false),
resize_ack_pending_(false),
- color_profile_out_of_date_(false),
auto_resize_enabled_(false),
waiting_for_screen_rects_ack_(false),
needs_repainting_on_restore_(false),
@@ -210,12 +211,24 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
is_focused_(false),
hung_renderer_delay_(
base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
+ hang_monitor_reason_(
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN),
new_content_rendering_delay_(
base::TimeDelta::FromMilliseconds(kNewContentRenderingDelayMs)),
weak_factory_(this) {
CHECK(delegate_);
CHECK_NE(MSG_ROUTING_NONE, routing_id_);
+#if defined(OS_WIN)
+ // Update the display color profile cache so that it is likely to be up to
+ // date when the renderer process requests the color profile.
+ if (gfx::ColorSpace::CachedProfilesNeedUpdate()) {
+ BrowserThread::PostBlockingPoolTask(
+ FROM_HERE,
+ base::Bind(&gfx::ColorSpace::UpdateCachedProfilesOnBackgroundThread));
+ }
+#endif
+
std::pair<RoutingIDWidgetMap::iterator, bool> result =
g_routing_id_widget_map.Get().insert(std::make_pair(
RenderWidgetHostID(process->GetID(), routing_id_), this));
@@ -526,8 +539,11 @@ void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
// When hidden, timeout monitoring for input events is disabled. Restore it
// now to ensure consistent hang detection.
- if (in_flight_event_count_)
+ if (in_flight_event_count_) {
RestartHangMonitorTimeout();
+ hang_monitor_reason_ =
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_IN_FLIGHT_EVENTS;
+ }
// Always repaint on restore.
bool needs_repainting = true;
@@ -567,7 +583,7 @@ bool RenderWidgetHostImpl::GetResizeParams(ResizeParams* resize_params) {
if (delegate_) {
resize_params->resizer_rect = delegate_->GetRootWindowResizerRect(this);
resize_params->is_fullscreen_granted =
- delegate_->IsFullscreenForCurrentTab(this);
+ delegate_->IsFullscreenForCurrentTab();
resize_params->display_mode = delegate_->GetDisplayMode(this);
} else {
resize_params->is_fullscreen_granted = false;
@@ -623,14 +639,10 @@ void RenderWidgetHostImpl::WasResized() {
// it's web contents is being deleted.
if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
!renderer_initialized_ || auto_resize_enabled_ || !delegate_) {
- if (resize_ack_pending_ && color_profile_out_of_date_)
- DispatchColorProfile();
return;
}
std::unique_ptr<ResizeParams> params(new ResizeParams);
- if (color_profile_out_of_date_)
- DispatchColorProfile();
if (!GetResizeParams(params.get()))
return;
@@ -646,44 +658,6 @@ void RenderWidgetHostImpl::WasResized() {
delegate_->RenderWidgetWasResized(this, width_changed);
}
-void RenderWidgetHostImpl::DispatchColorProfile() {
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
- static bool image_profiles = base::CommandLine::ForCurrentProcess()->
- HasSwitch(switches::kEnableImageColorProfiles);
- if (!image_profiles)
- return;
-#if defined(OS_WIN)
- // Windows will read disk to get the color profile data if needed, so
- // dispatch the SendColorProfile() work off the UI thread.
- BrowserThread::PostBlockingPoolTask(
- FROM_HERE,
- base::Bind(&RenderWidgetHostImpl::SendColorProfile,
- weak_factory_.GetWeakPtr()));
-#elif !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
- // Only support desktop Mac and Linux at this time.
- SendColorProfile();
-#endif
-#endif
-}
-
-void RenderWidgetHostImpl::SendColorProfile() {
- if (!view_ || !delegate_)
- return;
- DCHECK(!view_->GetRequestedRendererSize().IsEmpty());
-#if defined(OS_WIN)
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
-#endif
- std::vector<char> color_profile;
- if (!GetScreenColorProfile(&color_profile))
- return;
- if (!renderer_initialized_ || !process_->HasConnection())
- return;
- if (!Send(new ViewMsg_ColorProfile(routing_id_, color_profile)))
- return;
- color_profile_out_of_date_ = false;
-}
-
void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect& new_rect) {
Send(new ViewMsg_ChangeResizeRect(routing_id_, new_rect));
}
@@ -742,12 +716,14 @@ void RenderWidgetHostImpl::SetActive(bool active) {
}
void RenderWidgetHostImpl::LostMouseLock() {
- Send(new ViewMsg_MouseLockLost(routing_id_));
-
if (delegate_)
delegate_->LostMouseLock(this);
}
+void RenderWidgetHostImpl::SendMouseLockLost() {
+ Send(new ViewMsg_MouseLockLost(routing_id_));
+}
+
void RenderWidgetHostImpl::ViewDestroyed() {
RejectMouseLockOrUnlockIfNecessary();
@@ -905,9 +881,13 @@ bool RenderWidgetHostImpl::ScheduleComposite() {
return true;
}
-void RenderWidgetHostImpl::StartHangMonitorTimeout(base::TimeDelta delay) {
- if (hang_monitor_timeout_)
- hang_monitor_timeout_->Start(delay);
+void RenderWidgetHostImpl::StartHangMonitorTimeout(
+ base::TimeDelta delay,
+ RenderWidgetHostDelegate::RendererUnresponsiveType hang_monitor_reason) {
+ if (!hang_monitor_timeout_)
+ return;
+ hang_monitor_timeout_->Start(delay);
+ hang_monitor_reason_ = hang_monitor_reason;
}
void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
@@ -915,9 +895,17 @@ void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
hang_monitor_timeout_->Restart(hung_renderer_delay_);
}
+void RenderWidgetHostImpl::DisableHangMonitorForTesting() {
+ StopHangMonitorTimeout();
+ hang_monitor_timeout_.reset();
+}
+
void RenderWidgetHostImpl::StopHangMonitorTimeout() {
- if (hang_monitor_timeout_)
+ if (hang_monitor_timeout_) {
hang_monitor_timeout_->Stop();
+ hang_monitor_reason_ =
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN;
+ }
RendererIsResponsive();
}
@@ -939,6 +927,9 @@ void RenderWidgetHostImpl::OnFirstPaintAfterLoad() {
} else {
received_paint_after_load_ = true;
}
+
+ if (delegate_)
+ delegate_->OnFirstPaintAfterLoad(this);
}
void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
@@ -1245,14 +1236,6 @@ void RenderWidgetHostImpl::GetWebScreenInfo(blink::WebScreenInfo* result) {
input_router_->SetDeviceScaleFactor(result->deviceScaleFactor);
}
-bool RenderWidgetHostImpl::GetScreenColorProfile(
- std::vector<char>* color_profile) {
- DCHECK(color_profile->empty());
- if (view_)
- return view_->GetScreenColorProfile(color_profile);
- return false;
-}
-
void RenderWidgetHostImpl::HandleCompositorProto(
const std::vector<uint8_t>& proto) {
DCHECK(!proto.empty());
@@ -1260,8 +1243,6 @@ void RenderWidgetHostImpl::HandleCompositorProto(
}
void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
- color_profile_out_of_date_ = true;
-
if (delegate_)
delegate_->ScreenInfoChanged();
@@ -1274,6 +1255,20 @@ void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
void RenderWidgetHostImpl::GetSnapshotFromBrowser(
const GetSnapshotFromBrowserCallback& callback) {
int id = next_browser_snapshot_id_++;
+
+#if defined(OS_MACOSX)
+ // MacOS version of underlying GrabViewSnapshot() blocks while
+ // display/GPU are in a power-saving mode, so make sure display
+ // does not go to sleep for the duration of reading a snapshot.
+ if (pending_browser_snapshots_.empty()) {
+ DCHECK(!power_save_blocker_);
+ power_save_blocker_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ device::PowerSaveBlocker::kReasonOther, "GetSnapshot",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
+ }
+#endif
pending_browser_snapshots_.insert(std::make_pair(id, callback));
Send(new ViewMsg_ForceRedraw(GetRoutingID(), id));
}
@@ -1460,8 +1455,16 @@ void RenderWidgetHostImpl::RendererIsUnresponsive() {
Source<RenderWidgetHost>(this),
NotificationService::NoDetails());
is_unresponsive_ = true;
+ RenderWidgetHostDelegate::RendererUnresponsiveType reason =
+ hang_monitor_reason_;
+ hang_monitor_reason_ =
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN;
+
if (delegate_)
- delegate_->RendererUnresponsive(this);
+ delegate_->RendererUnresponsive(this, reason);
+
+ // Do not add code after this since the Delegate may delete this
+ // RenderWidgetHostImpl in RendererUnresponsive.
}
void RenderWidgetHostImpl::RendererIsResponsive() {
@@ -1562,20 +1565,19 @@ bool RenderWidgetHostImpl::OnSwapCompositorFrame(
ViewHostMsg_SwapCompositorFrame::Param param;
if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
return false;
- std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
- uint32_t output_surface_id = base::get<0>(param);
- base::get<1>(param).AssignTo(frame.get());
+ cc::CompositorFrame frame(std::move(std::get<1>(param)));
+ uint32_t output_surface_id = std::get<0>(param);
std::vector<IPC::Message> messages_to_deliver_with_frame;
- messages_to_deliver_with_frame.swap(base::get<2>(param));
+ messages_to_deliver_with_frame.swap(std::get<2>(param));
- if (!ui::LatencyInfo::Verify(frame->metadata.latency_info,
+ if (!ui::LatencyInfo::Verify(frame.metadata.latency_info,
"RenderWidgetHostImpl::OnSwapCompositorFrame")) {
- std::vector<ui::LatencyInfo>().swap(frame->metadata.latency_info);
+ std::vector<ui::LatencyInfo>().swap(frame.metadata.latency_info);
}
- latency_tracker_.OnSwapCompositorFrame(&frame->metadata.latency_info);
+ latency_tracker_.OnSwapCompositorFrame(&frame.metadata.latency_info);
- bool is_mobile_optimized = IsMobileOptimizedFrame(frame->metadata);
+ bool is_mobile_optimized = IsMobileOptimizedFrame(frame.metadata);
input_router_->NotifySiteIsMobileOptimized(is_mobile_optimized);
if (touch_emulator_)
touch_emulator_->SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
@@ -1585,13 +1587,11 @@ bool RenderWidgetHostImpl::OnSwapCompositorFrame(
view_->DidReceiveRendererFrame();
} else {
cc::CompositorFrameAck ack;
- if (frame->gl_frame_data) {
- ack.gl_frame_data = std::move(frame->gl_frame_data);
- ack.gl_frame_data->sync_token.Clear();
- } else if (frame->delegated_frame_data) {
+ if (frame.gl_frame_data) {
+ ack.gl_frame_data = std::move(frame.gl_frame_data);
+ } else if (frame.delegated_frame_data) {
cc::TransferableResource::ReturnResources(
- frame->delegated_frame_data->resource_list,
- &ack.resources);
+ frame.delegated_frame_data->resource_list, &ack.resources);
}
SendSwapCompositorFrameAck(routing_id_, output_surface_id,
process_->GetID(), ack);
@@ -1750,22 +1750,19 @@ void RenderWidgetHostImpl::OnLockMouse(bool user_gesture,
Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
return;
}
- if (IsMouseLocked()) {
- Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
+
+ pending_mouse_lock_request_ = true;
+ if (delegate_) {
+ delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target,
+ privileged && allow_privileged_mouse_lock_);
return;
}
- pending_mouse_lock_request_ = true;
if (privileged && allow_privileged_mouse_lock_) {
// Directly approve to lock the mouse.
GotResponseToLockMouseRequest(true);
} else {
- if (delegate_) {
- delegate_->RequestToLockMouse(this, user_gesture,
- last_unlocked_by_target);
- return;
- }
- // If there's no delegate, just reject it.
+ // Otherwise, just reject it.
GotResponseToLockMouseRequest(false);
}
}
@@ -1856,8 +1853,11 @@ InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
void RenderWidgetHostImpl::IncrementInFlightEventCount() {
increment_in_flight_event_count();
- if (!is_hidden_)
- StartHangMonitorTimeout(hung_renderer_delay_);
+ if (!is_hidden_) {
+ StartHangMonitorTimeout(
+ hung_renderer_delay_,
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_IN_FLIGHT_EVENTS);
+ }
}
void RenderWidgetHostImpl::DecrementInFlightEventCount() {
@@ -1866,8 +1866,11 @@ void RenderWidgetHostImpl::DecrementInFlightEventCount() {
StopHangMonitorTimeout();
} else {
// The renderer is responsive, but there are in-flight events to wait for.
- if (!is_hidden_)
+ if (!is_hidden_) {
RestartHangMonitorTimeout();
+ hang_monitor_reason_ =
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_IN_FLIGHT_EVENTS;
+ }
}
}
@@ -1901,12 +1904,13 @@ void RenderWidgetHostImpl::DispatchInputEventWithLatencyInfo(
void RenderWidgetHostImpl::OnKeyboardEventAck(
const NativeWebKeyboardEventWithLatencyInfo& event,
InputEventAckState ack_result) {
- latency_tracker_.OnInputEventAck(event.event, &event.latency);
+ latency_tracker_.OnInputEventAck(event.event, &event.latency, ack_result);
+
+ const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
// We only send unprocessed key event upwards if we are not hidden,
// because the user has moved away from us and no longer expect any effect
// of this key event.
- const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
if (delegate_ && !processed && !is_hidden() && !event.event.skip_in_browser) {
delegate_->HandleKeyboardEvent(event.event);
@@ -1919,13 +1923,15 @@ void RenderWidgetHostImpl::OnKeyboardEventAck(
void RenderWidgetHostImpl::OnMouseEventAck(
const MouseEventWithLatencyInfo& mouse_event,
InputEventAckState ack_result) {
- latency_tracker_.OnInputEventAck(mouse_event.event, &mouse_event.latency);
+ latency_tracker_.OnInputEventAck(mouse_event.event, &mouse_event.latency,
+ ack_result);
}
void RenderWidgetHostImpl::OnWheelEventAck(
const MouseWheelEventWithLatencyInfo& wheel_event,
InputEventAckState ack_result) {
- latency_tracker_.OnInputEventAck(wheel_event.event, &wheel_event.latency);
+ latency_tracker_.OnInputEventAck(wheel_event.event, &wheel_event.latency,
+ ack_result);
if (!is_hidden() && view_) {
if (ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
@@ -1939,7 +1945,7 @@ void RenderWidgetHostImpl::OnWheelEventAck(
void RenderWidgetHostImpl::OnGestureEventAck(
const GestureEventWithLatencyInfo& event,
InputEventAckState ack_result) {
- latency_tracker_.OnInputEventAck(event.event, &event.latency);
+ latency_tracker_.OnInputEventAck(event.event, &event.latency, ack_result);
if (view_)
view_->GestureEventAck(event.event, ack_result);
@@ -1948,7 +1954,7 @@ void RenderWidgetHostImpl::OnGestureEventAck(
void RenderWidgetHostImpl::OnTouchEventAck(
const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) {
- latency_tracker_.OnInputEventAck(event.event, &event.latency);
+ latency_tracker_.OnInputEventAck(event.event, &event.latency, ack_result);
if (touch_emulator_ &&
touch_emulator_->HandleTouchEventAck(event.event, ack_result)) {
@@ -2076,11 +2082,10 @@ void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
// is drawn to the screen, and when the snapshot will actually pick up
// that content. Insert a manual delay of 1/6th of a second (to simulate
// 10 frames at 60 fps) before actually taking the snapshot.
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::Bind(&RenderWidgetHostImpl::WindowSnapshotReachedScreen,
- weak_factory_.GetWeakPtr(),
- sequence_number),
+ weak_factory_.GetWeakPtr(), sequence_number),
base::TimeDelta::FromSecondsD(1. / 6));
#else
WindowSnapshotReachedScreen(sequence_number);
@@ -2130,6 +2135,10 @@ void RenderWidgetHostImpl::OnSnapshotDataReceived(int snapshot_id,
++it;
}
}
+#if defined(OS_MACOSX)
+ if (pending_browser_snapshots_.empty())
+ power_save_blocker_.reset();
+#endif
}
void RenderWidgetHostImpl::OnSnapshotDataReceivedAsync(
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 039b26852be..eb97ebf19ba 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -31,6 +31,7 @@
#include "content/browser/renderer_host/input/render_widget_host_latency_tracker.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/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/input/input_event_ack_state.h"
#include "content/common/input/synthetic_gesture_packet.h"
@@ -68,6 +69,12 @@ namespace cc {
class CompositorFrameAck;
}
+#if defined(OS_MACOSX)
+namespace device {
+class PowerSaveBlocker;
+} // namespace device
+#endif
+
namespace gfx {
class Range;
}
@@ -77,7 +84,6 @@ namespace content {
class BrowserAccessibilityManager;
class InputRouter;
class MockRenderWidgetHost;
-class RenderWidgetHostDelegate;
class RenderWidgetHostOwnerDelegate;
class SyntheticGestureController;
class TimeoutMonitor;
@@ -161,6 +167,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
bool IsLoading() const override;
void ResizeRectChanged(const gfx::Rect& new_rect) override;
void RestartHangMonitorTimeout() override;
+ void DisableHangMonitorForTesting() override;
void SetIgnoreInputEvents(bool ignore_input_events) override;
void WasResized() override;
void AddKeyPressEventCallback(const KeyPressEventCallback& callback) override;
@@ -173,7 +180,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
void RemoveInputEventObserver(
RenderWidgetHost::InputEventObserver* observer) override;
void GetWebScreenInfo(blink::WebScreenInfo* result) override;
- bool GetScreenColorProfile(std::vector<char>* color_profile) override;
void HandleCompositorProto(const std::vector<uint8_t>& proto) override;
// Notification that the screen info has changed.
@@ -248,6 +254,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// Called to notify the RenderWidget that it has lost the mouse lock.
void LostMouseLock();
+ // Notifies the RenderWidget that it lost the mouse lock.
+ void SendMouseLockLost();
+
// Noifies the RenderWidget of the current mouse cursor visibility state.
void SendCursorVisibilityState(bool is_visible);
@@ -278,7 +287,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);
+ void StartHangMonitorTimeout(
+ base::TimeDelta delay,
+ RenderWidgetHostDelegate::RendererUnresponsiveType hang_monitor_reason);
// Stops all existing hang monitor timeouts and assumes the renderer is
// responsive.
@@ -551,10 +562,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// NotifyRendererResponsive.
void RendererIsResponsive();
- // Routines used to send the RenderWidget its screen color profile.
- void DispatchColorProfile();
- void SendColorProfile();
-
// IPC message handlers
void OnRenderProcessGone(int status, int error_code);
void OnClose();
@@ -676,10 +683,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// True when waiting for RESIZE_ACK.
bool resize_ack_pending_;
- // Set if the color profile should fetched and sent to the RenderWidget
- // during the WasResized() resize message flow.
- bool color_profile_out_of_date_;
-
// The current size of the RenderWidget.
gfx::Size current_size_;
@@ -816,10 +819,18 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// This value indicates how long to wait before we consider a renderer hung.
base::TimeDelta hung_renderer_delay_;
+ // Stores the reason the hang_monitor_timeout_ has been started. Used to
+ // report histograms if the renderer is hung.
+ RenderWidgetHostDelegate::RendererUnresponsiveType hang_monitor_reason_;
+
// This value indicates how long to wait for a new compositor frame from a
// renderer process before clearing any previously displayed content.
base::TimeDelta new_content_rendering_delay_;
+#if defined(OS_MACOSX)
+ std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
+#endif
+
base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostImpl);
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 e23fe255e42..d6f8de72a29 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
@@ -39,24 +39,24 @@ void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
}
}
- if (view == touch_target_) {
- touch_target_ = nullptr;
- touch_delta_ = gfx::Vector2d();
+ if (view == touch_target_.target) {
+ touch_target_.target = nullptr;
active_touches_ = 0;
}
// If the target that's being destroyed is in the gesture target queue, we
// replace it with nullptr so that we maintain the 1:1 correspondence between
// queue entries and the touch sequences that underly them.
- for (size_t i = 0; i < gesture_target_queue_.size(); ++i) {
- if (gesture_target_queue_[i].target == view)
- gesture_target_queue_[i].target = nullptr;
+ for (size_t i = 0; i < touchscreen_gesture_target_queue_.size(); ++i) {
+ if (touchscreen_gesture_target_queue_[i].target == view)
+ touchscreen_gesture_target_queue_[i].target = nullptr;
}
- if (view == gesture_target_) {
- gesture_target_ = nullptr;
- gesture_delta_ = gfx::Vector2d();
- }
+ if (view == touchscreen_gesture_target_.target)
+ touchscreen_gesture_target_.target = nullptr;
+
+ if (view == touchpad_gesture_target_.target)
+ touchpad_gesture_target_.target = nullptr;
}
void RenderWidgetHostInputEventRouter::ClearAllObserverRegistrations() {
@@ -89,9 +89,7 @@ bool RenderWidgetHostInputEventRouter::HittestDelegate::AcceptHitTarget(
}
RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter()
- : touch_target_(nullptr),
- gesture_target_(nullptr),
- active_touches_(0) {}
+ : active_touches_(0) {}
RenderWidgetHostInputEventRouter::~RenderWidgetHostInputEventRouter() {
// We may be destroyed before some of the owners in the map, so we must
@@ -142,8 +140,10 @@ void RenderWidgetHostInputEventRouter::RouteMouseEvent(
event->x = transformed_point.x();
event->y = transformed_point.y();
-
- target->ProcessMouseEvent(*event);
+ // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
+ // https://crbug.com/613628
+ ui::LatencyInfo latency_info;
+ target->ProcessMouseEvent(*event, latency_info);
}
void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent(
@@ -157,42 +157,27 @@ void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent(
event->x = transformed_point.x();
event->y = transformed_point.y();
-
- target->ProcessMouseWheelEvent(*event);
+ // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
+ // https://crbug.com/613628
+ ui::LatencyInfo latency_info;
+ target->ProcessMouseWheelEvent(*event, latency_info);
}
void RenderWidgetHostInputEventRouter::RouteGestureEvent(
RenderWidgetHostViewBase* root_view,
blink::WebGestureEvent* event,
const ui::LatencyInfo& latency) {
- // We use GestureTapDown to detect the start of a gesture sequence since there
- // is no WebGestureEvent equivalent for ET_GESTURE_BEGIN. Note that this
- // means the GestureFlingCancel that always comes between ET_GESTURE_BEGIN and
- // GestureTapDown is sent to the previous target, in case it is still in a
- // fling.
- if (event->type == blink::WebInputEvent::GestureTapDown) {
- if (gesture_target_queue_.empty()) {
- LOG(ERROR) << "Gesture sequence start detected with no target available.";
- // Ignore this gesture sequence as no target is available.
- // TODO(wjmaclean): this only happens on Windows, and should not happen.
- // https://crbug.com/595422
- gesture_target_ = nullptr;
- base::debug::DumpWithoutCrashing();
- return;
- }
-
- const GestureTargetData& data = gesture_target_queue_.front();
- gesture_target_ = data.target;
- gesture_delta_ = data.delta;
- gesture_target_queue_.pop_front();
- }
-
- if (!gesture_target_)
- return;
-
- event->x += gesture_delta_.x();
- event->y += gesture_delta_.y();
- gesture_target_->ProcessGestureEvent(*event, latency);
+ switch (event->sourceDevice) {
+ case blink::WebGestureDeviceUninitialized:
+ NOTREACHED() << "Uninitialized device type is not allowed";
+ break;
+ case blink::WebGestureDeviceTouchpad:
+ RouteTouchpadGestureEvent(root_view, event, latency);
+ break;
+ case blink::WebGestureDeviceTouchscreen:
+ RouteTouchscreenGestureEvent(root_view, event, latency);
+ break;
+ };
}
void RenderWidgetHostInputEventRouter::RouteTouchEvent(
@@ -204,50 +189,48 @@ void RenderWidgetHostInputEventRouter::RouteTouchEvent(
if (!active_touches_) {
// Since this is the first touch, it defines the target for the rest
// of this sequence.
- DCHECK(!touch_target_);
+ DCHECK(!touch_target_.target);
gfx::Point transformed_point;
gfx::Point original_point(event->touches[0].position.x,
event->touches[0].position.y);
- touch_target_ =
+ touch_target_.target =
FindEventTarget(root_view, original_point, &transformed_point);
// TODO(wjmaclean): Instead of just computing a delta, we should extract
// the complete transform. We assume it doesn't change for the duration
// of the touch sequence, though this could be wrong; a better approach
- // might be to always transform each point to the touch_target_
+ // might be to always transform each point to the |touch_target_.target|
// for the duration of the sequence.
- touch_delta_ = transformed_point - original_point;
- gesture_target_queue_.emplace_back(touch_target_, touch_delta_);
+ touch_target_.delta = transformed_point - original_point;
+ touchscreen_gesture_target_queue_.push_back(touch_target_);
- if (!touch_target_)
+ if (!touch_target_.target)
return;
}
++active_touches_;
- if (touch_target_) {
- TransformEventTouchPositions(event, touch_delta_);
- touch_target_->ProcessTouchEvent(*event, latency);
+ if (touch_target_.target) {
+ TransformEventTouchPositions(event, touch_target_.delta);
+ touch_target_.target->ProcessTouchEvent(*event, latency);
}
break;
}
case blink::WebInputEvent::TouchMove:
- if (touch_target_) {
- TransformEventTouchPositions(event, touch_delta_);
- touch_target_->ProcessTouchEvent(*event, latency);
+ if (touch_target_.target) {
+ TransformEventTouchPositions(event, touch_target_.delta);
+ touch_target_.target->ProcessTouchEvent(*event, latency);
}
break;
case blink::WebInputEvent::TouchEnd:
case blink::WebInputEvent::TouchCancel:
- if (!touch_target_)
+ if (!touch_target_.target)
break;
DCHECK(active_touches_);
- TransformEventTouchPositions(event, touch_delta_);
- touch_target_->ProcessTouchEvent(*event, latency);
+ TransformEventTouchPositions(event, touch_target_.delta);
+ touch_target_.target->ProcessTouchEvent(*event, latency);
--active_touches_;
- if (!active_touches_) {
- touch_target_ = nullptr;
- touch_delta_ = gfx::Vector2d();
- }
+ if (!active_touches_)
+ touch_target_.target = nullptr;
break;
default:
NOTREACHED();
@@ -273,7 +256,7 @@ void RenderWidgetHostInputEventRouter::RemoveSurfaceIdNamespaceOwner(
}
for (auto it = hittest_data_.begin(); it != hittest_data_.end();) {
- if (cc::SurfaceIdAllocator::NamespaceForId(it->first) == id)
+ if (it->first.id_namespace() == id)
it = hittest_data_.erase(it);
else
++it;
@@ -282,8 +265,7 @@ void RenderWidgetHostInputEventRouter::RemoveSurfaceIdNamespaceOwner(
void RenderWidgetHostInputEventRouter::OnHittestData(
const FrameHostMsg_HittestData_Params& params) {
- if (owner_map_.find(cc::SurfaceIdAllocator::NamespaceForId(
- params.surface_id)) == owner_map_.end()) {
+ if (owner_map_.find(params.surface_id.id_namespace()) == owner_map_.end()) {
return;
}
HittestData data;
@@ -291,4 +273,68 @@ void RenderWidgetHostInputEventRouter::OnHittestData(
hittest_data_[params.surface_id] = data;
}
+void RenderWidgetHostInputEventRouter::RouteTouchscreenGestureEvent(
+ RenderWidgetHostViewBase* root_view,
+ blink::WebGestureEvent* event,
+ const ui::LatencyInfo& latency) {
+ DCHECK_EQ(blink::WebGestureDeviceTouchscreen, event->sourceDevice);
+
+ // We use GestureTapDown to detect the start of a gesture sequence since there
+ // is no WebGestureEvent equivalent for ET_GESTURE_BEGIN. Note that this
+ // means the GestureFlingCancel that always comes between ET_GESTURE_BEGIN and
+ // GestureTapDown is sent to the previous target, in case it is still in a
+ // fling.
+ if (event->type == blink::WebInputEvent::GestureTapDown) {
+ if (touchscreen_gesture_target_queue_.empty()) {
+ LOG(ERROR) << "Gesture sequence start detected with no target available.";
+ // Ignore this gesture sequence as no target is available.
+ // TODO(wjmaclean): this only happens on Windows, and should not happen.
+ // https://crbug.com/595422
+ touchscreen_gesture_target_.target = nullptr;
+ base::debug::DumpWithoutCrashing();
+ return;
+ }
+
+ touchscreen_gesture_target_ = touchscreen_gesture_target_queue_.front();
+ touchscreen_gesture_target_queue_.pop_front();
+ }
+
+ if (!touchscreen_gesture_target_.target)
+ return;
+
+ // TODO(mohsen): Add tests to check event location.
+ event->x += touchscreen_gesture_target_.delta.x();
+ event->y += touchscreen_gesture_target_.delta.y();
+ touchscreen_gesture_target_.target->ProcessGestureEvent(*event, latency);
+}
+
+void RenderWidgetHostInputEventRouter::RouteTouchpadGestureEvent(
+ RenderWidgetHostViewBase* root_view,
+ blink::WebGestureEvent* event,
+ const ui::LatencyInfo& latency) {
+ DCHECK_EQ(blink::WebGestureDeviceTouchpad, event->sourceDevice);
+
+ if (event->type == blink::WebInputEvent::GesturePinchBegin ||
+ event->type == blink::WebInputEvent::GestureFlingStart) {
+ gfx::Point transformed_point;
+ gfx::Point original_point(event->x, event->y);
+ touchpad_gesture_target_.target =
+ FindEventTarget(root_view, original_point, &transformed_point);
+ // TODO(mohsen): Instead of just computing a delta, we should extract the
+ // complete transform. We assume it doesn't change for the duration of the
+ // touchpad gesture sequence, though this could be wrong; a better approach
+ // might be to always transform each point to the
+ // |touchpad_gesture_target_.target| for the duration of the sequence.
+ touchpad_gesture_target_.delta = transformed_point - original_point;
+ }
+
+ if (!touchpad_gesture_target_.target)
+ return;
+
+ // TODO(mohsen): Add tests to check event location.
+ event->x += touchpad_gesture_target_.delta.x();
+ event->y += touchpad_gesture_target_.delta.y();
+ touchpad_gesture_target_.target->ProcessGestureEvent(*event, latency);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
index b4123539c58..387c5c276f9 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
@@ -96,14 +96,13 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
using SurfaceIdNamespaceOwnerMap =
base::hash_map<uint32_t, RenderWidgetHostViewBase*>;
- struct GestureTargetData {
+ struct TargetData {
RenderWidgetHostViewBase* target;
- const gfx::Vector2d delta;
+ gfx::Vector2d delta;
- GestureTargetData(RenderWidgetHostViewBase* target, gfx::Vector2d delta)
- : target(target), delta(delta) {}
+ TargetData() : target(nullptr) {}
};
- using GestureTargetQueue = std::deque<GestureTargetData>;
+ using TargetQueue = std::deque<TargetData>;
void ClearAllObserverRegistrations();
@@ -111,12 +110,18 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
const gfx::Point& point,
gfx::Point* transformed_point);
+ void RouteTouchscreenGestureEvent(RenderWidgetHostViewBase* root_view,
+ blink::WebGestureEvent* event,
+ const ui::LatencyInfo& latency);
+ void RouteTouchpadGestureEvent(RenderWidgetHostViewBase* root_view,
+ blink::WebGestureEvent* event,
+ const ui::LatencyInfo& latency);
+
SurfaceIdNamespaceOwnerMap owner_map_;
- GestureTargetQueue gesture_target_queue_;
- RenderWidgetHostViewBase* touch_target_;
- RenderWidgetHostViewBase* gesture_target_;
- gfx::Vector2d touch_delta_;
- gfx::Vector2d gesture_delta_;
+ TargetQueue touchscreen_gesture_target_queue_;
+ TargetData touch_target_;
+ TargetData touchscreen_gesture_target_;
+ TargetData touchpad_gesture_target_;
int active_touches_;
std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>
hittest_data_;
@@ -124,6 +129,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouter);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
InputEventRouterGestureTargetQueueTest);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ InputEventRouterTouchpadGestureTargetTest);
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
index 8753f01db83..a802282235d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -6,11 +6,13 @@
#include <stdint.h>
#include <memory>
+#include <tuple>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
@@ -67,7 +69,7 @@ std::string GetInputMessageTypes(MockRenderProcessHost* process) {
EXPECT_EQ(InputMsg_HandleInputEvent::ID, message->type());
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
- const WebInputEvent* event = base::get<0>(params);
+ const WebInputEvent* event = std::get<0>(params);
if (i != 0)
result += " ";
result += WebInputEventTraits::GetName(event->type);
@@ -403,7 +405,8 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
return handle_wheel_event_;
}
- void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host) override {
+ void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host,
+ RendererUnresponsiveType type) override {
unresponsive_timer_fired_ = true;
}
@@ -492,7 +495,7 @@ class RenderWidgetHostTest : public testing::Test {
#endif
// Process all pending tasks to avoid leaks.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
void SetInitialRenderSizeParams() {
@@ -587,7 +590,7 @@ class RenderWidgetHostTest : public testing::Test {
}
// Set the timestamp for the touch-event.
- void SetTouchTimestamp(base::TimeDelta timestamp) {
+ void SetTouchTimestamp(base::TimeTicks timestamp) {
touch_event_.SetTimestamp(timestamp);
}
@@ -858,9 +861,9 @@ TEST_F(RenderWidgetHostTest, Background) {
process_->sink().GetUniqueMessageMatching(
ViewMsg_SetBackgroundOpaque::ID);
ASSERT_TRUE(set_background);
- base::Tuple<bool> sent_background;
+ std::tuple<bool> sent_background;
ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
- EXPECT_FALSE(base::get<0>(sent_background));
+ EXPECT_FALSE(std::get<0>(sent_background));
#if defined(USE_AURA)
// See the comment above |InitAsChild(NULL)|.
@@ -895,9 +898,9 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
const IPC::Message* restored = process_->sink().GetUniqueMessageMatching(
ViewMsg_WasShown::ID);
ASSERT_TRUE(restored);
- base::Tuple<bool, ui::LatencyInfo> needs_repaint;
+ std::tuple<bool, ui::LatencyInfo> needs_repaint;
ViewMsg_WasShown::Read(restored, &needs_repaint);
- EXPECT_TRUE(base::get<0>(needs_repaint));
+ EXPECT_TRUE(std::get<0>(needs_repaint));
}
TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
@@ -1068,11 +1071,15 @@ TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
// while one is in progress (see crbug.com/11007).
TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
// Start with a short timeout.
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
+ host_->StartHangMonitorTimeout(
+ TimeDelta::FromMilliseconds(10),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
// Immediately try to add a long 30 second timeout.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
- host_->StartHangMonitorTimeout(TimeDelta::FromSeconds(30));
+ host_->StartHangMonitorTimeout(
+ TimeDelta::FromSeconds(30),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -1086,12 +1093,16 @@ TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
// and then started again.
TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) {
// Start with a short timeout, then stop it.
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
+ host_->StartHangMonitorTimeout(
+ TimeDelta::FromMilliseconds(10),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
host_->StopHangMonitorTimeout();
// Start it again to ensure it still works.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
+ host_->StartHangMonitorTimeout(
+ TimeDelta::FromMilliseconds(10),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -1105,11 +1116,15 @@ TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) {
// updated to a shorter duration.
TEST_F(RenderWidgetHostTest, ShorterDelayHangMonitorTimeout) {
// Start with a timeout.
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(100));
+ host_->StartHangMonitorTimeout(
+ TimeDelta::FromMilliseconds(100),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
// Start it again with shorter delay.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
- host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(20));
+ host_->StartHangMonitorTimeout(
+ TimeDelta::FromMilliseconds(20),
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_UNKNOWN);
// Wait long enough for the second timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -1532,8 +1547,8 @@ void CheckLatencyInfoComponentInMessage(RenderWidgetHostProcess* process,
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
- const WebInputEvent* event = base::get<0>(params);
- ui::LatencyInfo latency_info = base::get<1>(params);
+ const WebInputEvent* event = std::get<0>(params);
+ ui::LatencyInfo latency_info = std::get<1>(params);
EXPECT_TRUE(event->type == expected_type);
EXPECT_TRUE(latency_info.FindLatency(
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 2f4d49c9141..196c18df019 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
@@ -12,13 +12,15 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/threading/worker_pool.h"
#include "cc/layers/layer.h"
#include "cc/layers/surface_layer.h"
@@ -27,7 +29,6 @@
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
#include "cc/output/latency_info_swap_promise.h"
-#include "cc/output/viewport_selection_bound.h"
#include "cc/resources/single_release_callback.h"
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_factory.h"
@@ -51,7 +52,6 @@
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/frame_metadata_util.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
-#include "content/browser/renderer_host/input/ui_touch_selection_helper.h"
#include "content/browser/renderer_host/input/web_input_event_builders_android.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -96,15 +96,15 @@ namespace content {
namespace {
void SatisfyCallback(cc::SurfaceManager* manager,
- cc::SurfaceSequence sequence) {
+ const cc::SurfaceSequence& sequence) {
std::vector<uint32_t> sequences;
sequences.push_back(sequence.sequence);
manager->DidSatisfySequences(sequence.id_namespace, &sequences);
}
void RequireCallback(cc::SurfaceManager* manager,
- cc::SurfaceId id,
- cc::SurfaceSequence sequence) {
+ const cc::SurfaceId& id,
+ const cc::SurfaceSequence& sequence) {
cc::Surface* surface = manager->GetSurfaceForId(id);
if (!surface) {
LOG(ERROR) << "Attempting to require callback on nonexistent surface";
@@ -189,8 +189,7 @@ void GLHelperHolder::Initialize() {
provider_ = new ContextProviderCommandBuffer(
std::move(gpu_channel_host), gpu::GPU_STREAM_DEFAULT,
gpu::GpuStreamPriority::NORMAL, gpu::kNullSurfaceHandle, url,
- gfx::PreferIntegratedGpu, automatic_flushes, support_locking, limits,
- attributes, nullptr,
+ automatic_flushes, support_locking, limits, attributes, nullptr,
command_buffer_metrics::BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
if (!provider_->BindToCurrentThread())
return;
@@ -207,7 +206,7 @@ void GLHelperHolder::Initialize() {
void GLHelperHolder::OnContextLost() {
// Need to post a task because the command buffer client cannot be deleted
// from within this callback.
- base::MessageLoop::current()->PostTask(
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&RenderWidgetHostViewAndroid::OnContextLost));
}
@@ -289,7 +288,7 @@ gfx::RectF GetSelectionRect(const ui::TouchSelectionController& controller) {
RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
uint32_t output_id,
- std::unique_ptr<cc::CompositorFrame> output_frame)
+ cc::CompositorFrame output_frame)
: output_surface_id(output_id), frame(std::move(output_frame)) {}
RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
@@ -608,9 +607,9 @@ gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
gfx::Size RenderWidgetHostViewAndroid::GetVisibleViewportSize() const {
if (!content_view_core_)
- return gfx::Rect(default_size_).size();
+ return default_size_;
- return gfx::Rect(content_view_core_->GetViewSize()).size();
+ return content_view_core_->GetViewSize();
}
gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
@@ -621,12 +620,10 @@ gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
}
bool RenderWidgetHostViewAndroid::DoTopControlsShrinkBlinkSize() const {
- if (!content_view_core_)
- return false;
-
// Whether or not Blink's viewport size should be shrunk by the height of the
// URL-bar.
- return content_view_core_->DoTopControlsShrinkBlinkSize();
+ return content_view_core_ &&
+ content_view_core_->DoTopControlsShrinkBlinkSize();
}
float RenderWidgetHostViewAndroid::GetTopControlsHeight() const {
@@ -705,6 +702,8 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent(
if (!host_)
return false;
+ ComputeEventLatencyOSTouchHistograms(event);
+
// If a browser-based widget consumes the touch event, it's critical that
// touch event interception be disabled. This avoids issues with
// double-handling for embedder-detected gestures like side swipe.
@@ -868,15 +867,16 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
const ReadbackRequestCallback& callback,
const SkColorType preferred_color_type) {
TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
- if (!host_ || host_->is_hidden()) {
+ if (!host_ || host_->is_hidden() || !IsSurfaceAvailableForCopy()) {
callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
return;
}
- base::TimeTicks start_time = base::TimeTicks::Now();
- if (!IsSurfaceAvailableForCopy()) {
- callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
+ if (!content_view_core_ || !(content_view_core_->GetWindowAndroid())) {
+ callback.Run(SkBitmap(), READBACK_FAILED);
return;
}
+
+ base::TimeTicks start_time = base::TimeTicks::Now();
const display::Display& display =
display::Screen::GetScreen()->GetPrimaryDisplay();
float device_scale_factor = display.device_scale_factor();
@@ -893,20 +893,18 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
return;
}
- if (!content_view_core_ || !(content_view_core_->GetWindowAndroid())) {
- callback.Run(SkBitmap(), READBACK_FAILED);
- return;
- }
ui::WindowAndroidCompositor* compositor =
content_view_core_->GetWindowAndroid()->GetCompositor();
DCHECK(compositor);
DCHECK(!surface_id_.is_null());
std::unique_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(
- base::Bind(&PrepareTextureCopyOutputResult, dst_size_in_pixel,
- preferred_color_type, start_time, callback));
+ cc::CopyOutputRequest::CreateRequest(base::Bind(
+ &PrepareTextureCopyOutputResult, weak_ptr_factory_.GetWeakPtr(),
+ dst_size_in_pixel, preferred_color_type, start_time, callback));
if (!src_subrect_in_pixel.IsEmpty())
request->set_area(src_subrect_in_pixel);
+ // Make sure the layer doesn't get deleted until we fulfill the request.
+ LockCompositingSurface();
layer_->RequestCopyOfOutput(std::move(request));
}
@@ -996,7 +994,7 @@ void RenderWidgetHostViewAndroid::CheckOutputSurfaceChanged(
}
void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
- std::unique_ptr<cc::CompositorFrame> frame) {
+ cc::CompositorFrame frame) {
cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
if (!surface_factory_) {
surface_factory_ = base::WrapUnique(new cc::SurfaceFactory(manager, this));
@@ -1004,8 +1002,8 @@ void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
if (surface_id_.is_null() ||
texture_size_in_layer_ != current_surface_size_ ||
location_bar_content_translation_ !=
- frame->metadata.location_bar_content_translation ||
- current_viewport_selection_ != frame->metadata.selection) {
+ frame.metadata.location_bar_content_translation ||
+ current_viewport_selection_ != frame.metadata.selection) {
RemoveLayers();
if (!surface_id_.is_null())
surface_factory_->Destroy(surface_id_);
@@ -1017,8 +1015,8 @@ void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
current_surface_size_ = texture_size_in_layer_;
location_bar_content_translation_ =
- frame->metadata.location_bar_content_translation;
- current_viewport_selection_ = frame->metadata.selection;
+ frame.metadata.location_bar_content_translation;
+ current_viewport_selection_ = frame.metadata.selection;
AttachLayers();
}
@@ -1031,18 +1029,10 @@ void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {
+ cc::CompositorFrame frame) {
CheckOutputSurfaceChanged(output_surface_id);
bool has_content = !texture_size_in_layer_.IsEmpty();
- // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
- // renderer frame, assuming that the browser compositor will scale
- // it back up to device scale. But on Android we put our browser layers in
- // physical pixels and set our browser CC device_scale_factor to 1, so this
- // suppresses the transform. This line may need to be removed when fixing
- // http://crbug.com/384134 or http://crbug.com/310763
- frame->delegated_frame_data->device_scale_factor = 1.0f;
-
base::Closure ack_callback =
base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
weak_ptr_factory_.GetWeakPtr(),
@@ -1068,9 +1058,9 @@ void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {
- last_scroll_offset_ = frame->metadata.root_scroll_offset;
- if (!frame->delegated_frame_data) {
+ cc::CompositorFrame frame) {
+ last_scroll_offset_ = frame.metadata.root_scroll_offset;
+ if (!frame.delegated_frame_data) {
LOG(ERROR) << "Non-delegated renderer path no longer supported";
return;
}
@@ -1083,32 +1073,32 @@ void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
if (!CompositorImpl::GetSurfaceManager() && layer_.get() &&
layer_->layer_tree_host()) {
- for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
+ for (size_t i = 0; i < frame.metadata.latency_info.size(); i++) {
std::unique_ptr<cc::SwapPromise> swap_promise(
- new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
+ new cc::LatencyInfoSwapPromise(frame.metadata.latency_info[i]));
layer_->layer_tree_host()->QueueSwapPromise(std::move(swap_promise));
}
}
- DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
+ DCHECK(!frame.delegated_frame_data->render_pass_list.empty());
cc::RenderPass* root_pass =
- frame->delegated_frame_data->render_pass_list.back().get();
+ frame.delegated_frame_data->render_pass_list.back().get();
texture_size_in_layer_ = root_pass->output_rect.size();
- cc::CompositorFrameMetadata metadata = frame->metadata;
+ cc::CompositorFrameMetadata metadata = frame.metadata.Clone();
SwapDelegatedFrame(output_surface_id, std::move(frame));
frame_evictor_->SwappedFrame(!host_->is_hidden());
// As the metadata update may trigger view invalidation, always call it after
// any potential compositor scheduling.
- OnFrameMetadataUpdated(metadata);
+ OnFrameMetadataUpdated(std::move(metadata));
}
void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {
+ cc::CompositorFrame frame) {
InternalSwapCompositorFrame(output_surface_id, std::move(frame));
}
@@ -1116,9 +1106,8 @@ void RenderWidgetHostViewAndroid::ClearCompositorFrame() {
DestroyDelegatedContent();
}
-void RenderWidgetHostViewAndroid::RetainFrame(
- uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {
+void RenderWidgetHostViewAndroid::RetainFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) {
DCHECK(locks_on_frame_count_);
// Store the incoming frame so that it can be swapped when all the locks have
@@ -1138,19 +1127,14 @@ void RenderWidgetHostViewAndroid::RetainFrame(
new LastFrameInfo(output_surface_id, std::move(frame)));
}
-SynchronousCompositorHost*
-RenderWidgetHostViewAndroid::GetSynchronousCompositor() {
- return sync_compositor_.get();
-}
-
void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
- const cc::CompositorFrameMetadata& frame_metadata) {
+ cc::CompositorFrameMetadata frame_metadata) {
if (!content_view_core_)
return;
// This is a subset of OnSwapCompositorFrame() used in the synchronous
// compositor flow.
- OnFrameMetadataUpdated(frame_metadata);
+ OnFrameMetadataUpdated(frame_metadata.Clone());
// DevTools ScreenCast support for Android WebView.
WebContents* web_contents = content_view_core_->GetWebContents();
@@ -1163,7 +1147,7 @@ void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
base::Bind(
&RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
static_cast<RenderFrameDevToolsAgentHost*>(dtah.get()),
- frame_metadata));
+ base::Passed(&frame_metadata)));
}
}
@@ -1285,8 +1269,7 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
selection_controller_->OnSelectionEmpty(
frame_metadata.selection.is_empty_text_form_control);
selection_controller_->OnSelectionBoundsChanged(
- ConvertSelectionBound(frame_metadata.selection.start),
- ConvertSelectionBound(frame_metadata.selection.end));
+ frame_metadata.selection.start, frame_metadata.selection.end);
// Set parameters for adaptive handle orientation.
gfx::SizeF viewport_size(frame_metadata.scrollable_viewport_size);
@@ -1411,11 +1394,6 @@ void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32_t requests) {
bool should_request_vsync = !outstanding_vsync_requests_ && requests;
outstanding_vsync_requests_ |= requests;
- // If the host has been hidden, defer vsync requests until it is shown
- // again via |Show()|.
- if (!host_ || host_->is_hidden())
- return;
-
// Note that if we're not currently observing the root window, outstanding
// vsync requests will be pushed if/when we resume observing in
// |StartObservingRootWindow()|.
@@ -1433,6 +1411,8 @@ void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
return;
observing_root_window_ = true;
+ if (host_)
+ host_->Send(new ViewMsg_SetBeginFramePaused(host_->GetRoutingID(), false));
content_view_core_->GetWindowAndroid()->AddObserver(this);
// Clear existing vsync requests to allow a request to the new window.
@@ -1454,6 +1434,8 @@ void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
is_window_activity_started_ = true;
is_window_visible_ = true;
observing_root_window_ = false;
+ if (host_)
+ host_->Send(new ViewMsg_SetBeginFramePaused(host_->GetRoutingID(), true));
content_view_core_->GetWindowAndroid()->RemoveObserver(this);
}
@@ -1462,22 +1444,17 @@ void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
"frame_time_us", frame_time.ToInternalValue());
- if (using_browser_compositor_) {
- // TODO(brianderson): Replace this hardcoded deadline after Android
- // switches to Surfaces and the Browser's commit isn't in the critcal path.
- base::TimeTicks deadline = frame_time + (vsync_period * 0.6);
-
- host_->Send(new ViewMsg_BeginFrame(
- host_->GetRoutingID(),
- cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
- vsync_period, cc::BeginFrameArgs::NORMAL)));
- } else if (sync_compositor_) {
- // The synchronous compositor synchronously does it's work in this call.
- // It does not use a deadline.
- sync_compositor_->BeginFrame(cc::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, frame_time, base::TimeTicks(), vsync_period,
- cc::BeginFrameArgs::NORMAL));
- }
+ // Synchronous compositor does not use deadline-based scheduling.
+ // TODO(brianderson): Replace this hardcoded deadline after Android
+ // switches to Surfaces and the Browser's commit isn't in the critcal path.
+ base::TimeTicks deadline =
+ sync_compositor_ ? base::TimeTicks() : frame_time + (vsync_period * 0.6);
+ host_->Send(new ViewMsg_BeginFrame(
+ host_->GetRoutingID(),
+ cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
+ vsync_period, cc::BeginFrameArgs::NORMAL)));
+ if (sync_compositor_)
+ sync_compositor_->DidSendBeginFrame();
}
bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
@@ -1514,13 +1491,6 @@ void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
}
-bool RenderWidgetHostViewAndroid::GetScreenColorProfile(
- std::vector<char>* color_profile) {
- DCHECK(color_profile->empty());
- NOTREACHED();
- return false;
-}
-
// TODO(jrg): Find out the implications and answer correctly here,
// as we are returning the WebView and not root window bounds.
gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
@@ -1599,8 +1569,6 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
shim->Send(new GpuMsg_WakeUpGpu);
}
- if (sync_compositor_)
- return sync_compositor_->HandleInputEvent(input_event);
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
@@ -1698,8 +1666,8 @@ void RenderWidgetHostViewAndroid::OnShowingPastePopup(
// 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.
- ui::SelectionBound insertion_bound;
- insertion_bound.set_type(ui::SelectionBound::CENTER);
+ gfx::SelectionBound insertion_bound;
+ insertion_bound.set_type(gfx::SelectionBound::CENTER);
insertion_bound.set_visible(true);
insertion_bound.SetEdge(point, point);
selection_controller_->HideAndDisallowShowingAutomatically();
@@ -1749,7 +1717,13 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
overscroll_controller_.reset();
selection_controller_.reset();
ReleaseLocksOnSurface();
- resize = true;
+ // TODO(yusufo) : Get rid of the below conditions and have a better handling
+ // for resizing after crbug.com/628302 is handled.
+ bool is_size_initialized = !content_view_core
+ || content_view_core->GetViewportSizeDip().width() != 0
+ || content_view_core->GetViewportSizeDip().height() != 0;
+ if (content_view_core_ || is_size_initialized)
+ resize = true;
if (content_view_core_)
content_view_core_->RemoveObserver(this);
if (content_view_core)
@@ -1792,8 +1766,6 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
sync_compositor_ = SynchronousCompositorHost::Create(
this, content_view_core_->GetWebContents());
}
- if (sync_compositor_)
- sync_compositor_->DidBecomeCurrent();
}
void RenderWidgetHostViewAndroid::RunAckCallbacks(
@@ -1872,7 +1844,7 @@ void RenderWidgetHostViewAndroid::OnDetachCompositor() {
void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
base::TimeDelta vsync_period) {
TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnVSync");
- if (!host_ || host_->is_hidden())
+ if (!host_)
return;
if (outstanding_vsync_requests_ & FLUSH_INPUT) {
@@ -1926,6 +1898,7 @@ void RenderWidgetHostViewAndroid::OnLostResources() {
// static
void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
+ base::WeakPtr<RenderWidgetHostViewAndroid> rwhva,
const gfx::Size& dst_size_in_pixel,
SkColorType color_type,
const base::TimeTicks& start_time,
@@ -1935,9 +1908,21 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
base::Bind(callback, SkBitmap(), READBACK_FAILED));
TRACE_EVENT0("cc",
"RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
-
+ if (rwhva)
+ rwhva->UnlockCompositingSurface();
if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
return;
+ cc::TextureMailbox texture_mailbox;
+ std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+ result->TakeTexture(&texture_mailbox, &release_callback);
+ DCHECK(texture_mailbox.IsTexture());
+ if (!texture_mailbox.IsTexture())
+ return;
+ display_compositor::GLHelper* gl_helper = GetPostReadbackGLHelper();
+ if (!gl_helper)
+ return;
+ if (!gl_helper->IsReadbackConfigSupported(color_type))
+ color_type = kRGBA_8888_SkColorType;
gfx::Size output_size_in_pixel;
if (dst_size_in_pixel.IsEmpty())
@@ -1945,11 +1930,6 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
else
output_size_in_pixel = dst_size_in_pixel;
- display_compositor::GLHelper* gl_helper = GetPostReadbackGLHelper();
- if (!gl_helper)
- return;
- if (!gl_helper->IsReadbackConfigSupported(color_type))
- color_type = kRGBA_8888_SkColorType;
std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
if (!bitmap->tryAllocPixels(SkImageInfo::Make(output_size_in_pixel.width(),
output_size_in_pixel.height(),
@@ -1964,13 +1944,6 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
new SkAutoLockPixels(*bitmap));
uint8_t* pixels = static_cast<uint8_t*>(bitmap->getPixels());
- cc::TextureMailbox texture_mailbox;
- std::unique_ptr<cc::SingleReleaseCallback> release_callback;
- result->TakeTexture(&texture_mailbox, &release_callback);
- DCHECK(texture_mailbox.IsTexture());
- if (!texture_mailbox.IsTexture())
- return;
-
ignore_result(scoped_callback_runner.Release());
gl_helper->CropScaleReadbackAndCleanMailbox(
@@ -2027,4 +2000,27 @@ void RenderWidgetHostViewBase::GetDefaultScreenInfo(
results->isMonochrome = (results->depthPerComponent == 0);
}
+void RenderWidgetHostViewAndroid::ComputeEventLatencyOSTouchHistograms(
+ const ui::MotionEvent& event) {
+ base::TimeTicks event_time = event.GetEventTime();
+ base::TimeDelta delta = base::TimeTicks::Now() - event_time;
+ switch (event.GetAction()) {
+ case ui::MotionEvent::ACTION_DOWN:
+ case ui::MotionEvent::ACTION_POINTER_DOWN:
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.TOUCH_PRESSED",
+ delta.InMicroseconds(), 1, 1000000, 50);
+ return;
+ case ui::MotionEvent::ACTION_MOVE:
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.TOUCH_MOVED",
+ delta.InMicroseconds(), 1, 1000000, 50);
+ return;
+ case ui::MotionEvent::ACTION_UP:
+ case ui::MotionEvent::ACTION_POINTER_UP:
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.TOUCH_RELEASED",
+ delta.InMicroseconds(), 1, 1000000, 50);
+ default:
+ return;
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.h b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
index 34faa32327e..93b76fa28b2 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
@@ -18,6 +18,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
+#include "cc/input/selection.h"
#include "cc/output/begin_frame_args.h"
#include "cc/surfaces/surface_factory_client.h"
#include "cc/surfaces/surface_id.h"
@@ -35,6 +36,7 @@
#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"
namespace cc {
@@ -134,7 +136,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
const base::Callback<void(const gfx::Rect&, bool)>& callback) override;
bool CanCopyToVideoFrame() const override;
void GetScreenInfo(blink::WebScreenInfo* results) override;
- bool GetScreenColorProfile(std::vector<char>* color_profile) override;
gfx::Rect GetBoundsInRootWindow() override;
void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) override;
@@ -147,9 +148,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
bool LockMouse() override;
void UnlockMouse() override;
- void OnSwapCompositorFrame(
- uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) override;
+ void OnSwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) override;
void ClearCompositorFrame() override;
void DidOverscroll(const DidOverscrollParams& params) override;
void DidStopFlinging() override;
@@ -246,9 +246,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void OnShowingPastePopup(const gfx::PointF& point);
void OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip);
- SynchronousCompositorHost* GetSynchronousCompositor();
- void SynchronousFrameMetadata(
- const cc::CompositorFrameMetadata& frame_metadata);
+ void SynchronousFrameMetadata(cc::CompositorFrameMetadata frame_metadata);
void SetOverlayVideoMode(bool enabled);
@@ -265,9 +263,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void DestroyDelegatedContent();
void CheckOutputSurfaceChanged(uint32_t output_surface_id);
- void SubmitCompositorFrame(std::unique_ptr<cc::CompositorFrame> frame_data);
+ void SubmitCompositorFrame(cc::CompositorFrame frame_data);
void SwapDelegatedFrame(uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame_data);
+ cc::CompositorFrame frame_data);
void SendDelegatedFrameAck(uint32_t output_surface_id);
void SendReturnedDelegatedResources(uint32_t output_surface_id);
@@ -284,6 +282,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// Called after async screenshot task completes. Scales and crops the result
// of the copy.
static void PrepareTextureCopyOutputResult(
+ base::WeakPtr<RenderWidgetHostViewAndroid> rwhva,
const gfx::Size& dst_size_in_pixel,
SkColorType color_type,
const base::TimeTicks& start_time,
@@ -303,11 +302,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// Drop any incoming frames from the renderer when there are locks on the
// current frame.
- void RetainFrame(uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame);
+ void RetainFrame(uint32_t output_surface_id, cc::CompositorFrame frame);
void InternalSwapCompositorFrame(uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame);
+ cc::CompositorFrame frame);
void OnLostResources();
enum VSyncRequestType {
@@ -324,11 +322,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
bool SyncCompositorOnMessageReceived(const IPC::Message& message);
+ void ComputeEventLatencyOSTouchHistograms(const ui::MotionEvent& event);
+
// The model object.
RenderWidgetHostImpl* host_;
- bool use_surfaces_;
-
// Used to control action dispatch at the next |OnVSync()| call.
uint32_t outstanding_vsync_requests_;
@@ -354,7 +352,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
gfx::Size current_surface_size_;
cc::ReturnedResourceArray surface_returned_resources_;
gfx::Vector2dF location_bar_content_translation_;
- cc::ViewportSelection current_viewport_selection_;
+ cc::Selection<gfx::SelectionBound> current_viewport_selection_;
// The most recent texture size that was pushed to the texture layer.
gfx::Size texture_size_in_layer_;
@@ -391,11 +389,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
bool observing_root_window_;
struct LastFrameInfo {
- LastFrameInfo(uint32_t output_id,
- std::unique_ptr<cc::CompositorFrame> output_frame);
+ LastFrameInfo(uint32_t output_id, cc::CompositorFrame output_frame);
~LastFrameInfo();
uint32_t output_surface_id;
- std::unique_ptr<cc::CompositorFrame> frame;
+ cc::CompositorFrame frame;
};
std::unique_ptr<LastFrameInfo> last_frame_info_;
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 4bb17af87eb..5a0e703bf9f 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
@@ -34,7 +34,6 @@
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
#include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
-#include "content/browser/renderer_host/input/ui_touch_selection_helper.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
@@ -84,7 +83,6 @@
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/color_profile.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
@@ -97,18 +95,21 @@
#include "ui/wm/public/window_types.h"
#if defined(OS_WIN)
+#include "base/time/time.h"
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "content/browser/renderer_host/legacy_render_widget_host_win.h"
#include "ui/base/win/hidden_window.h"
+#include "ui/base/win/osk_display_manager.h"
+#include "ui/base/win/osk_display_observer.h"
#include "ui/display/win/screen_win.h"
#include "ui/gfx/gdi_util.h"
#endif
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
#include "content/common/input_messages.h"
-#include "ui/events/linux/text_edit_command_auralinux.h"
-#include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
+#include "ui/base/ime/linux/text_edit_command_auralinux.h"
+#include "ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h"
#endif
using gfx::RectToSkIRect;
@@ -212,6 +213,87 @@ void MarkUnchangedTouchPointsAsStationary(
}
}
+#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.
+// It provides functionality to request blink to scroll the input field if it
+// is obscured by the on screen keyboard.
+class WinScreenKeyboardObserver : public ui::OnScreenKeyboardObserver {
+ public:
+ WinScreenKeyboardObserver(RenderWidgetHostImpl* host,
+ const gfx::Point& location_in_screen,
+ float scale_factor,
+ aura::Window* window)
+ : host_(host),
+ location_in_screen_(location_in_screen),
+ device_scale_factor_(scale_factor),
+ window_(window) {
+ host_->GetView()->SetInsets(gfx::Insets());
+ }
+
+ // base::win::OnScreenKeyboardObserver overrides.
+ void OnKeyboardVisible(const gfx::Rect& keyboard_rect_pixels) override {
+ gfx::Point location_in_pixels =
+ gfx::ConvertPointToPixel(device_scale_factor_, location_in_screen_);
+
+ // Restore the viewport.
+ host_->GetView()->SetInsets(gfx::Insets());
+
+ if (keyboard_rect_pixels.Contains(location_in_pixels)) {
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(window_->GetRootWindow());
+ if (!screen_position_client)
+ return;
+
+ DVLOG(1) << "OSK covering focus point.";
+ gfx::Rect keyboard_rect =
+ gfx::ConvertRectToDIP(device_scale_factor_, keyboard_rect_pixels);
+ gfx::Rect bounds_in_screen = window_->GetBoundsInScreen();
+
+ DCHECK(bounds_in_screen.bottom() > keyboard_rect.y());
+
+ // Set the viewport of the window to be just above the on screen
+ // keyboard.
+ int viewport_bottom = bounds_in_screen.bottom() - keyboard_rect.y();
+
+ // If the viewport is bigger than the view, then we cannot handle it
+ // with the current approach. Moving the window above the OSK is one way.
+ // That for a later patchset.
+ if (viewport_bottom > bounds_in_screen.height())
+ return;
+
+ host_->GetView()->SetInsets(gfx::Insets(0, 0, viewport_bottom, 0));
+
+ gfx::Point origin(location_in_screen_);
+ screen_position_client->ConvertPointFromScreen(window_, &origin);
+
+ // 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);
+ host_->ScrollFocusedEditableNodeIntoRect(node_rect);
+ }
+ }
+
+ void OnKeyboardHidden(const gfx::Rect& keyboard_rect_pixels) override {
+ // Restore the viewport.
+ host_->GetView()->SetInsets(gfx::Insets());
+ }
+
+ private:
+ RenderWidgetHostImpl* host_;
+ // The location in DIPs where the touch occurred.
+ gfx::Point location_in_screen_;
+ // The current device scale factor.
+ float device_scale_factor_;
+
+ // The content Window.
+ aura::Window* window_;
+
+ DISALLOW_COPY_AND_ASSIGN(WinScreenKeyboardObserver);
+};
+#endif
+
} // namespace
// We need to watch for mouse events outside a Web Popup or its parent
@@ -370,10 +452,6 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
popup_parent_host_view_(nullptr),
popup_child_host_view_(nullptr),
is_loading_(false),
- text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
- text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
- text_input_flags_(0),
- can_compose_inline_(true),
has_composition_text_(false),
accept_return_character_(false),
begin_frame_source_(nullptr),
@@ -383,6 +461,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
#if defined(OS_WIN)
legacy_render_widget_host_HWND_(nullptr),
legacy_window_destroyed_(false),
+ virtual_keyboard_requested_(false),
#endif
has_snapped_to_boundary_(false),
is_guest_view_hack_(is_guest_view_hack),
@@ -400,6 +479,11 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
GetSurfaceIdNamespace(), this);
}
+ // We should start observing the TextInputManager for IME-related events as
+ // well as monitoring its lifetime.
+ if (GetTextInputManager())
+ GetTextInputManager()->AddObserver(this);
+
bool overscroll_enabled = base::CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
SetOverscrollControllerEnabled(overscroll_enabled);
@@ -779,7 +863,9 @@ bool RenderWidgetHostViewAura::ShouldRouteEvent(const ui::Event* event) const {
// in a similar manner to RenderWidgetHostViewGuest.
bool result = host_->delegate() && host_->delegate()->GetInputEventRouter() &&
!disable_input_event_router_for_testing_;
- if (event->IsMouseEvent())
+ // 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;
}
@@ -854,6 +940,29 @@ void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
}
}
+void RenderWidgetHostViewAura::FocusedNodeTouched(
+ const gfx::Point& location_dips_screen,
+ bool editable) {
+#if defined(OS_WIN)
+ RenderViewHost* rvh = RenderViewHost::From(host_);
+ if (rvh && rvh->GetDelegate())
+ rvh->GetDelegate()->SetIsVirtualKeyboardRequested(editable);
+
+ ui::OnScreenKeyboardDisplayManager* osk_display_manager =
+ ui::OnScreenKeyboardDisplayManager::GetInstance();
+ DCHECK(osk_display_manager);
+ if (editable && host_ && host_->GetView()) {
+ keyboard_observer_.reset(new WinScreenKeyboardObserver(
+ host_, location_dips_screen, device_scale_factor_, window_));
+ virtual_keyboard_requested_ =
+ osk_display_manager->DisplayVirtualKeyboard(keyboard_observer_.get());
+ } else {
+ virtual_keyboard_requested_ = false;
+ osk_display_manager->DismissVirtualKeyboard();
+ }
+#endif
+}
+
void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
current_cursor_ = cursor;
const display::Display display =
@@ -867,31 +976,6 @@ void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
UpdateCursorIfOverSelf();
}
-void RenderWidgetHostViewAura::TextInputStateChanged(
- const TextInputState& params) {
- if (text_input_type_ != params.type ||
- text_input_mode_ != params.mode ||
- can_compose_inline_ != params.can_compose_inline ||
- text_input_flags_ != params.flags) {
- text_input_type_ = params.type;
- text_input_mode_ = params.mode;
- can_compose_inline_ = params.can_compose_inline;
- text_input_flags_ = params.flags;
- if (GetInputMethod())
- GetInputMethod()->OnTextInputTypeChanged(this);
- }
- if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) {
- if (GetInputMethod())
- GetInputMethod()->ShowImeIfNeeded();
- }
-}
-
-void RenderWidgetHostViewAura::ImeCancelComposition() {
- if (GetInputMethod())
- GetInputMethod()->CancelComposition(this);
- has_composition_text_ = false;
-}
-
void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
@@ -959,15 +1043,15 @@ gfx::Size RenderWidgetHostViewAura::GetRequestedRendererSize() const {
void RenderWidgetHostViewAura::SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) {
- ui::SelectionBound anchor_bound, focus_bound;
+ gfx::SelectionBound anchor_bound, focus_bound;
anchor_bound.SetEdge(gfx::PointF(params.anchor_rect.origin()),
gfx::PointF(params.anchor_rect.bottom_left()));
focus_bound.SetEdge(gfx::PointF(params.focus_rect.origin()),
gfx::PointF(params.focus_rect.bottom_left()));
if (params.anchor_rect == params.focus_rect) {
- anchor_bound.set_type(ui::SelectionBound::CENTER);
- focus_bound.set_type(ui::SelectionBound::CENTER);
+ anchor_bound.set_type(gfx::SelectionBound::CENTER);
+ focus_bound.set_type(gfx::SelectionBound::CENTER);
} else {
// Whether text is LTR at the anchor handle.
bool anchor_LTR = params.anchor_dir == blink::WebTextDirectionLeftToRight;
@@ -976,15 +1060,15 @@ void RenderWidgetHostViewAura::SelectionBoundsChanged(
if ((params.is_anchor_first && anchor_LTR) ||
(!params.is_anchor_first && !anchor_LTR)) {
- anchor_bound.set_type(ui::SelectionBound::LEFT);
+ anchor_bound.set_type(gfx::SelectionBound::LEFT);
} else {
- anchor_bound.set_type(ui::SelectionBound::RIGHT);
+ anchor_bound.set_type(gfx::SelectionBound::RIGHT);
}
if ((params.is_anchor_first && focus_LTR) ||
(!params.is_anchor_first && !focus_LTR)) {
- focus_bound.set_type(ui::SelectionBound::RIGHT);
+ focus_bound.set_type(gfx::SelectionBound::RIGHT);
} else {
- focus_bound.set_type(ui::SelectionBound::LEFT);
+ focus_bound.set_type(gfx::SelectionBound::LEFT);
}
}
@@ -1048,27 +1132,34 @@ void RenderWidgetHostViewAura::OnLegacyWindowDestroyed() {
void RenderWidgetHostViewAura::OnSwapCompositorFrame(
uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {
+ cc::CompositorFrame frame) {
TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
- last_scroll_offset_ = frame->metadata.root_scroll_offset;
- if (!frame->delegated_frame_data)
+ last_scroll_offset_ = frame.metadata.root_scroll_offset;
+ if (!frame.delegated_frame_data)
return;
- cc::ViewportSelection selection = frame->metadata.selection;
+ cc::Selection<gfx::SelectionBound> selection = frame.metadata.selection;
if (IsUseZoomForDSFEnabled()) {
float viewportToDIPScale = 1.0f / current_device_scale_factor_;
- selection.start.edge_top.Scale(viewportToDIPScale);
- selection.start.edge_bottom.Scale(viewportToDIPScale);
- selection.end.edge_top.Scale(viewportToDIPScale);
- selection.end.edge_bottom.Scale(viewportToDIPScale);
+ gfx::PointF start_edge_top = selection.start.edge_top();
+ gfx::PointF start_edge_bottom = selection.start.edge_bottom();
+ gfx::PointF end_edge_top = selection.end.edge_top();
+ gfx::PointF end_edge_bottom = selection.end.edge_bottom();
+
+ start_edge_top.Scale(viewportToDIPScale);
+ start_edge_bottom.Scale(viewportToDIPScale);
+ end_edge_top.Scale(viewportToDIPScale);
+ end_edge_bottom.Scale(viewportToDIPScale);
+
+ selection.start.SetEdge(start_edge_top, start_edge_bottom);
+ selection.end.SetEdge(end_edge_top, end_edge_bottom);
}
delegated_frame_host_->SwapDelegatedFrame(output_surface_id,
std::move(frame));
SelectionUpdated(selection.is_editable, selection.is_empty_text_form_control,
- ConvertSelectionBound(selection.start),
- ConvertSelectionBound(selection.end));
+ selection.start, selection.end);
}
void RenderWidgetHostViewAura::ClearCompositorFrame() {
@@ -1091,13 +1182,6 @@ void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
}
-bool RenderWidgetHostViewAura::GetScreenColorProfile(
- std::vector<char>* color_profile) {
- DCHECK(color_profile->empty());
- gfx::Rect bounds(window_->GetToplevelWindow()->GetBoundsInScreen());
- return gfx::GetDisplayColorProfile(bounds, color_profile);
-}
-
gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
aura::Window* top_level = window_->GetToplevelWindow();
gfx::Rect bounds(top_level->GetBoundsInScreen());
@@ -1232,12 +1316,16 @@ InputEventAckState RenderWidgetHostViewAura::FilterInputEvent(
if (WebTouchEvent::isTouchEventType(input_event.type))
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
- // Reporting consumed for a fling suggests that there's now an *active* fling
- // that requires both animation and a fling-end notification. However, the
- // OverscrollController consumes a fling to stop its propagation; it doesn't
- // actually tick a fling animation. Report no consumer to convey this.
- if (consumed && input_event.type == blink::WebInputEvent::GestureFlingStart)
+ if (consumed && input_event.type == blink::WebInputEvent::GestureFlingStart) {
+ // Here we indicate that there was no consumer for this event, as
+ // otherwise the fling animation system will try to run an animation
+ // and will also expect a notification when the fling ends. Since
+ // CrOS just uses the GestureFlingStart with zero-velocity as a means
+ // of indicating that touchpad scroll has ended, we don't actually want
+ // a fling animation. Note: Similar code exists in
+ // RenderWidgetHostViewChildFrame::FilterInputEvent()
return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ }
return consumed ? INPUT_EVENT_ACK_STATE_CONSUMED
: INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
@@ -1342,8 +1430,7 @@ void RenderWidgetHostViewAura::UnlockMouse() {
// RenderWidgetHostViewAura, ui::TextInputClient implementation:
void RenderWidgetHostViewAura::SetCompositionText(
const ui::CompositionText& composition) {
- // TODO(wjmaclean): can host_ ever be null?
- if (!host_)
+ if (!text_input_manager_ || !text_input_manager_->GetActiveWidget())
return;
// TODO(suzhe): convert both renderer_host and renderer to use
@@ -1363,35 +1450,36 @@ void RenderWidgetHostViewAura::SetCompositionText(
// TODO(suzhe): due to a bug of webkit, we can't use selection range with
// composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
- host_->ImeSetComposition(composition.text, underlines,
- gfx::Range::InvalidRange(),
- composition.selection.end(),
- composition.selection.end());
+ text_input_manager_->GetActiveWidget()->ImeSetComposition(
+ composition.text, underlines, gfx::Range::InvalidRange(),
+ composition.selection.end(), composition.selection.end());
has_composition_text_ = !composition.text.empty();
}
void RenderWidgetHostViewAura::ConfirmCompositionText() {
- // TODO(wjmaclean): can host_ ever be null?
- if (host_ && has_composition_text_) {
- host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
- false);
+ if (text_input_manager_ && text_input_manager_->GetActiveWidget() &&
+ has_composition_text_) {
+ text_input_manager_->GetActiveWidget()->ImeConfirmComposition(
+ base::string16(), gfx::Range::InvalidRange(), false);
}
has_composition_text_ = false;
}
void RenderWidgetHostViewAura::ClearCompositionText() {
- // TODO(wjmaclean): can host_ ever be null?
- if (host_ && has_composition_text_)
- host_->ImeCancelComposition();
+ if (text_input_manager_ && text_input_manager_->GetActiveWidget() &&
+ has_composition_text_)
+ text_input_manager_->GetActiveWidget()->ImeCancelComposition();
has_composition_text_ = false;
}
void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
- DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
- // TODO(wjmaclean): can host_ ever be null?
- if (host_)
- host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
+ DCHECK_NE(GetTextInputType(), ui::TEXT_INPUT_TYPE_NONE);
+
+ if (text_input_manager_ && text_input_manager_->GetActiveWidget()) {
+ text_input_manager_->GetActiveWidget()->ImeConfirmComposition(
+ text, gfx::Range::InvalidRange(), false);
+ }
has_composition_text_ = false;
}
@@ -1411,19 +1499,32 @@ void RenderWidgetHostViewAura::InsertChar(const ui::KeyEvent& event) {
}
ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
- return text_input_type_;
+ if (text_input_manager_ && text_input_manager_->GetTextInputState())
+ return text_input_manager_->GetTextInputState()->type;
+ return ui::TEXT_INPUT_TYPE_NONE;
}
ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
- return text_input_mode_;
+ if (text_input_manager_ && text_input_manager_->GetTextInputState())
+ return text_input_manager_->GetTextInputState()->mode;
+ return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
+base::i18n::TextDirection RenderWidgetHostViewAura::GetTextDirection() const {
+ NOTIMPLEMENTED();
+ return base::i18n::UNKNOWN_DIRECTION;
}
int RenderWidgetHostViewAura::GetTextInputFlags() const {
- return text_input_flags_;
+ if (text_input_manager_ && text_input_manager_->GetTextInputState())
+ return text_input_manager_->GetTextInputState()->flags;
+ return 0;
}
bool RenderWidgetHostViewAura::CanComposeInline() const {
- return can_compose_inline_;
+ if (text_input_manager_ && text_input_manager_->GetTextInputState())
+ return text_input_manager_->GetTextInputState()->can_compose_inline;
+ return true;
}
gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
@@ -1468,7 +1569,7 @@ gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
return ConvertRectToScreen(
- ui::RectBetweenSelectionBounds(selection_anchor_, selection_focus_));
+ gfx::RectBetweenSelectionBounds(selection_anchor_, selection_focus_));
}
bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
@@ -1577,12 +1678,13 @@ void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
ConvertRectFromScreen(intersected_rect));
}
-bool RenderWidgetHostViewAura::IsEditCommandEnabled(int command_id) {
+bool RenderWidgetHostViewAura::IsTextEditCommandEnabled(
+ ui::TextEditCommand command) const {
return false;
}
-void RenderWidgetHostViewAura::SetEditCommandForNextKeyEvent(int command_id) {
-}
+void RenderWidgetHostViewAura::SetTextEditCommandForNextKeyEvent(
+ ui::TextEditCommand command) {}
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, display::DisplayObserver implementation:
@@ -1890,7 +1992,7 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
this, &mouse_wheel_event);
} else {
- ProcessMouseWheelEvent(mouse_wheel_event);
+ ProcessMouseWheelEvent(mouse_wheel_event, *event->latency());
}
}
} else {
@@ -1909,7 +2011,7 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
host_->delegate()->GetInputEventRouter()->RouteMouseEvent(this,
&mouse_event);
} else {
- ProcessMouseEvent(mouse_event);
+ ProcessMouseEvent(mouse_event, *event->latency());
}
// Ensure that we get keyboard focus on mouse down as a plugin window may
@@ -1954,17 +2056,19 @@ uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint(
// case we return our current namespace.
if (id.is_null())
return GetSurfaceIdNamespace();
- return cc::SurfaceIdAllocator::NamespaceForId(id);
+ return id.id_namespace();
}
void RenderWidgetHostViewAura::ProcessMouseEvent(
- const blink::WebMouseEvent& event) {
- host_->ForwardMouseEvent(event);
+ const blink::WebMouseEvent& event,
+ const ui::LatencyInfo& latency) {
+ host_->ForwardMouseEventWithLatencyInfo(event, latency);
}
void RenderWidgetHostViewAura::ProcessMouseWheelEvent(
- const blink::WebMouseWheelEvent& event) {
- host_->ForwardWheelEvent(event);
+ const blink::WebMouseWheelEvent& event,
+ const ui::LatencyInfo& latency) {
+ host_->ForwardWheelEventWithLatencyInfo(event, latency);
}
void RenderWidgetHostViewAura::ProcessTouchEvent(
@@ -1993,6 +2097,21 @@ void RenderWidgetHostViewAura::TransformPointToLocalCoordSpace(
gfx::ConvertPointToDIP(device_scale_factor_, *transformed_point);
}
+void RenderWidgetHostViewAura::FocusedNodeChanged(bool editable) {
+#if defined(OS_WIN)
+ if (!editable && virtual_keyboard_requested_) {
+ virtual_keyboard_requested_ = false;
+
+ RenderViewHost* rvh = RenderViewHost::From(host_);
+ if (rvh && rvh->GetDelegate())
+ rvh->GetDelegate()->SetIsVirtualKeyboardRequested(false);
+
+ DCHECK(ui::OnScreenKeyboardDisplayManager::GetInstance());
+ ui::OnScreenKeyboardDisplayManager::GetInstance()->DismissVirtualKeyboard();
+ }
+#endif
+}
+
void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
@@ -2005,15 +2124,33 @@ void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
#endif
blink::WebGestureEvent gesture_event =
MakeWebGestureEventFlingCancel();
- host_->ForwardGestureEvent(gesture_event);
+ // 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 =
MakeWebMouseWheelEvent(*event);
- host_->ForwardWheelEvent(mouse_wheel_event);
+ 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 = MakeWebGestureEvent(*event);
- host_->ForwardGestureEvent(gesture_event);
+ 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"));
}
@@ -2276,7 +2413,18 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
// RenderWidgetHostViewAura::OnWindowDestroying and the pointer should
// be set to NULL.
DCHECK(!legacy_render_widget_host_HWND_);
+ if (virtual_keyboard_requested_) {
+ DCHECK(keyboard_observer_.get());
+ ui::OnScreenKeyboardDisplayManager* osk_display_manager =
+ ui::OnScreenKeyboardDisplayManager::GetInstance();
+ DCHECK(osk_display_manager);
+ osk_display_manager->RemoveObserver(keyboard_observer_.get());
+ }
+
#endif
+
+ if (text_input_manager_)
+ text_input_manager_->RemoveObserver(this);
}
void RenderWidgetHostViewAura::CreateAuraWindow() {
@@ -2304,11 +2452,11 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
gfx::Point cursor_screen_point = screen->GetCursorScreenPoint();
-#if defined(OS_WIN)
+#if !defined(OS_CHROMEOS)
// Ignore cursor update messages if the window under the cursor is not us.
aura::Window* window_at_screen_point = screen->GetWindowAtScreenPoint(
cursor_screen_point);
-
+#if defined(OS_WIN)
// On Windows we may fail to retrieve the aura Window at the current cursor
// position. This is because the WindowFromPoint API may return the legacy
// window which is not associated with an aura Window. In this case we need
@@ -2324,15 +2472,12 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
window_at_screen_point = screen_win->GetNativeWindowFromHWND(
hwnd_at_point);
}
-
+#endif // defined(OS_WIN)
if (!window_at_screen_point ||
(window_at_screen_point->GetRootWindow() != root_window)) {
return;
}
-#elif !defined(OS_CHROMEOS)
- if (!screen->IsWindowUnderCursor(window_))
- return;
-#endif
+#endif // !defined(OS_CHROMEOS)
gfx::Point root_window_point = cursor_screen_point;
aura::client::ScreenPositionClient* screen_position_client =
@@ -2385,10 +2530,10 @@ bool RenderWidgetHostViewAura::NeedsMouseCapture() {
void RenderWidgetHostViewAura::FinishImeCompositionSession() {
if (!has_composition_text_)
return;
- // TODO(wjmaclean): can host_ ever be null?
- if (host_) {
- host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
- false);
+
+ if (!!text_input_manager_ && !!text_input_manager_->GetActiveWidget()) {
+ text_input_manager_->GetActiveWidget()->ImeConfirmComposition(
+ base::string16(), gfx::Range::InvalidRange(), false);
}
ImeCancelComposition();
}
@@ -2627,9 +2772,6 @@ void RenderWidgetHostViewAura::ForwardKeyboardEvent(
// RenderWidgetHosts for OOPIF. See https://crbug.com/549334.
target_host->Send(new InputMsg_SetEditCommandsForNextKeyEvent(
target_host->GetRoutingID(), edit_commands));
-
- NativeWebKeyboardEvent copy_event(event);
- copy_event.match_edit_command = true;
target_host->ForwardKeyboardEvent(event);
return;
}
@@ -2638,10 +2780,11 @@ void RenderWidgetHostViewAura::ForwardKeyboardEvent(
target_host->ForwardKeyboardEvent(event);
}
-void RenderWidgetHostViewAura::SelectionUpdated(bool is_editable,
- bool is_empty_text_form_control,
- const ui::SelectionBound& start,
- const ui::SelectionBound& end) {
+void RenderWidgetHostViewAura::SelectionUpdated(
+ bool is_editable,
+ bool is_empty_text_form_control,
+ const gfx::SelectionBound& start,
+ const gfx::SelectionBound& end) {
selection_controller_->OnSelectionEditable(is_editable);
selection_controller_->OnSelectionEmpty(is_empty_text_form_control);
selection_controller_->OnSelectionBoundsChanged(start, end);
@@ -2664,7 +2807,7 @@ void RenderWidgetHostViewAura::HandleGestureForTouchSelection(
switch (event->type()) {
case ui::ET_GESTURE_LONG_PRESS:
if (selection_controller_->WillHandleLongPressEvent(
- base::TimeTicks() + event->time_stamp(), event->location_f())) {
+ event->time_stamp(), event->location_f())) {
event->SetHandled();
}
break;
@@ -2771,7 +2914,7 @@ SkColor RenderWidgetHostViewAura::DelegatedFrameHostGetGutterColor(
// When making an element on the page fullscreen the element's background
// may not match the page's, so use black as the gutter color to avoid
// flashes of brighter colors during the transition.
- if (host_->delegate() && host_->delegate()->IsFullscreenForCurrentTab(host_))
+ if (host_->delegate() && host_->delegate()->IsFullscreenForCurrentTab())
return SK_ColorBLACK;
return color;
}
@@ -2841,6 +2984,10 @@ void RenderWidgetHostViewAura::SetBeginFrameSource(
begin_frame_source_->AddObserver(this);
}
+bool RenderWidgetHostViewAura::IsAutoResizeEnabled() const {
+ return host_->auto_resize_enabled();
+}
+
void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
ui::GestureRecognizer::Get()->CancelActiveTouches(window_);
}
@@ -2861,6 +3008,37 @@ cc::SurfaceId RenderWidgetHostViewAura::SurfaceIdForTesting() const {
return delegated_frame_host_->SurfaceIdForTesting();
}
+void RenderWidgetHostViewAura::OnUpdateTextInputStateCalled(
+ TextInputManager* text_input_manager,
+ RenderWidgetHostViewBase* updated_view,
+ bool did_update_state) {
+ DCHECK_EQ(text_input_manager_, text_input_manager);
+
+ if (!GetInputMethod())
+ return;
+
+ if (did_update_state)
+ GetInputMethod()->OnTextInputTypeChanged(this);
+
+ const TextInputState* state = text_input_manager_->GetTextInputState();
+
+ if (state && state->show_ime_if_needed &&
+ state->type != ui::TEXT_INPUT_TYPE_NONE)
+ GetInputMethod()->ShowImeIfNeeded();
+}
+
+void RenderWidgetHostViewAura::OnImeCancelComposition(
+ TextInputManager* text_input_manager,
+ RenderWidgetHostViewBase* view) {
+ // |view| is not necessarily the one corresponding to
+ // TextInputManager::GetActiveWidget() as RenderWidgetHostViewAura can call
+ // this method to finish any ongoing composition in response to a mouse down
+ // event.
+ if (GetInputMethod())
+ GetInputMethod()->CancelComposition(this);
+ has_composition_text_ = false;
+}
+
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewBase, public:
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 781bba5686e..dccf55e6098 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
@@ -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/text_input_manager.h"
#include "content/common/content_export.h"
#include "content/common/cursors/webcursor.h"
#include "content/public/common/context_menu_params.h"
@@ -37,11 +38,11 @@
#include "ui/aura/window_tracker.h"
#include "ui/aura/window_tree_host_observer.h"
#include "ui/base/ime/text_input_client.h"
-#include "ui/base/touch/selection_bound.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"
#include "ui/wm/public/activation_delegate.h"
namespace aura {
@@ -59,6 +60,7 @@ class DelegatedFrameData;
namespace gfx {
class Canvas;
class Display;
+class Point;
class Rect;
}
@@ -70,6 +72,9 @@ namespace ui {
class CompositorLock;
class InputMethod;
class LocatedEvent;
+#if defined(OS_WIN)
+class OnScreenKeyboardObserver;
+#endif
class Texture;
class TouchSelectionController;
}
@@ -91,6 +96,7 @@ struct TextInputState;
class CONTENT_EXPORT RenderWidgetHostViewAura
: public RenderWidgetHostViewBase,
public DelegatedFrameHostClient,
+ public TextInputManager::Observer,
public ui::TextInputClient,
public display::DisplayObserver,
public aura::WindowTreeHostObserver,
@@ -126,6 +132,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void SetBackgroundColor(SkColor color) override;
gfx::Size GetVisibleViewportSize() const override;
void SetInsets(const gfx::Insets& insets) override;
+ void FocusedNodeTouched(const gfx::Point& location_dips_screen,
+ bool editable) override;
// Overridden from RenderWidgetHostViewBase:
void InitAsPopup(RenderWidgetHostView* parent_host_view,
@@ -134,8 +142,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void Focus() override;
void UpdateCursor(const WebCursor& cursor) override;
void SetIsLoading(bool is_loading) override;
- void TextInputStateChanged(const TextInputState& params) override;
- void ImeCancelComposition() override;
void ImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) override;
@@ -164,7 +170,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void EndFrameSubscription() override;
bool HasAcceleratedSurface(const gfx::Size& desired_size) override;
void GetScreenInfo(blink::WebScreenInfo* results) override;
- bool GetScreenColorProfile(std::vector<char>* color_profile) override;
gfx::Rect GetBoundsInRootWindow() override;
void WheelEventAck(const blink::WebMouseWheelEvent& event,
InputEventAckState ack_result) override;
@@ -182,9 +187,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
bool LockMouse() override;
void UnlockMouse() override;
- void OnSwapCompositorFrame(
- uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) override;
+ void OnSwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) override;
void ClearCompositorFrame() override;
void DidStopFlinging() override;
void OnDidNavigateMainFrameToNewPage() override;
@@ -194,8 +198,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
uint32_t SurfaceIdNamespaceAtPoint(cc::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) override;
- void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
- void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
+ void ProcessMouseEvent(const blink::WebMouseEvent& event,
+ const ui::LatencyInfo& latency) override;
+ void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event,
+ const ui::LatencyInfo& latency) override;
void ProcessTouchEvent(const blink::WebTouchEvent& event,
const ui::LatencyInfo& latency) override;
void ProcessGestureEvent(const blink::WebGestureEvent& event,
@@ -203,6 +209,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void TransformPointToLocalCoordSpace(const gfx::Point& point,
cc::SurfaceId original_surface,
gfx::Point* transformed_point) override;
+ void FocusedNodeChanged(bool is_editable_node) override;
// Overridden from ui::TextInputClient:
void SetCompositionText(const ui::CompositionText& composition) override;
@@ -212,6 +219,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void InsertChar(const ui::KeyEvent& event) override;
ui::TextInputType GetTextInputType() const override;
ui::TextInputMode GetTextInputMode() const override;
+ base::i18n::TextDirection GetTextDirection() const override;
int GetTextInputFlags() const override;
bool CanComposeInline() const override;
gfx::Rect GetCaretBounds() const override;
@@ -230,8 +238,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
base::i18n::TextDirection direction) override;
void ExtendSelectionAndDelete(size_t before, size_t after) override;
void EnsureCaretInRect(const gfx::Rect& rect) override;
- bool IsEditCommandEnabled(int command_id) override;
- void SetEditCommandForNextKeyEvent(int command_id) override;
+ bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override;
+ void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override;
// Overridden from display::DisplayObserver:
void OnDisplayAdded(const display::Display& new_display) override;
@@ -341,7 +349,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
const ui::MotionEventAura& pointer_state() const { return pointer_state_; }
private:
+ friend class InputMethodResultAuraTest;
friend class RenderWidgetHostViewAuraCopyRequestTest;
+ friend class TestInputMethodObserver;
+ FRIEND_TEST_ALL_PREFIXES(InputMethodResultAuraTest,
+ FinishImeCompositionSession);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
PopupRetainsCaptureAfterMouseRelease);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText);
@@ -456,6 +468,14 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
const base::TimeTicks& timebase,
const base::TimeDelta& interval) override;
void SetBeginFrameSource(cc::BeginFrameSource* source) override;
+ bool IsAutoResizeEnabled() const override;
+
+ // TextInputManager::Observer implementation.
+ void OnUpdateTextInputStateCalled(TextInputManager* text_input_manager,
+ RenderWidgetHostViewBase* updated_view,
+ bool did_update_state) override;
+ void OnImeCancelComposition(TextInputManager* text_input_manager,
+ RenderWidgetHostViewBase* updated_view) override;
// cc::BeginFrameObserver implementation.
void OnBeginFrame(const cc::BeginFrameArgs& args) override;
@@ -506,8 +526,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// received. It will update selection controller.
void SelectionUpdated(bool is_editable,
bool is_empty_text_form_control,
- const ui::SelectionBound& start,
- const ui::SelectionBound& end);
+ const gfx::SelectionBound& start,
+ const gfx::SelectionBound& end);
// Helper function to create a selection controller.
void CreateSelectionController();
@@ -566,17 +586,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// object.
ui::MotionEventAura pointer_state_;
- // The current text input type.
- ui::TextInputType text_input_type_;
- // The current text input mode corresponding to HTML5 inputmode attribute.
- ui::TextInputMode text_input_mode_;
- // The current text input flags.
- int text_input_flags_;
- bool can_compose_inline_;
-
// Bounds for the selection.
- ui::SelectionBound selection_anchor_;
- ui::SelectionBound selection_focus_;
+ gfx::SelectionBound selection_anchor_;
+ gfx::SelectionBound selection_focus_;
// The current composition character bounds.
std::vector<gfx::Rect> composition_character_bounds_;
@@ -643,6 +655,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// 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_;
+
+ // Set to true if we requested the on screen keyboard to be displayed.
+ bool virtual_keyboard_requested_;
+
+ std::unique_ptr<ui::OnScreenKeyboardObserver> keyboard_observer_;
#endif
bool has_snapped_to_boundary_;
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 80b3135f2fb..61b0efcca39 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
@@ -7,16 +7,20 @@
#include <stddef.h>
#include <stdint.h>
+#include <tuple>
#include <utility>
#include "base/command_line.h"
+#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/simple_test_tick_clock.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "cc/output/begin_frame_args.h"
#include "cc/output/compositor_frame.h"
@@ -38,11 +42,12 @@
#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/resize_lock.h"
+#include "content/browser/renderer_host/text_input_manager.h"
#include "content/browser/web_contents/web_contents_view_aura.h"
#include "content/common/host_shared_bitmap_manager.h"
-#include "content/common/input/input_event_utils.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/input_messages.h"
+#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
@@ -52,6 +57,7 @@
#include "content/public/test/test_browser_context.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
+#include "ipc/ipc_message.h"
#include "ipc/ipc_test_sink.h"
#include "media/base/video_frame.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -159,6 +165,9 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
const NativeWebKeyboardEvent* last_event() const { return last_event_.get(); }
void set_widget_host(RenderWidgetHostImpl* rwh) { rwh_ = rwh; }
void set_is_fullscreen(bool is_fullscreen) { is_fullscreen_ = is_fullscreen; }
+ TextInputManager* GetTextInputManager() override {
+ return &text_input_manager_;
+ }
protected:
// RenderWidgetHostDelegate:
@@ -175,15 +184,13 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
if (rwh_)
rwh_->SendScreenRects();
}
- bool IsFullscreenForCurrentTab(
- RenderWidgetHostImpl* render_widget_host) const override {
- return is_fullscreen_;
- }
+ bool IsFullscreenForCurrentTab() const override { return is_fullscreen_; }
private:
std::unique_ptr<NativeWebKeyboardEvent> last_event_;
RenderWidgetHostImpl* rwh_;
bool is_fullscreen_;
+ TextInputManager text_input_manager_;
DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHostDelegate);
};
@@ -529,11 +536,11 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
return;
}
- InputEventDispatchType dispatch_type = base::get<2>(params);
+ InputEventDispatchType dispatch_type = std::get<2>(params);
if (dispatch_type == InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING)
return;
- const blink::WebInputEvent* event = base::get<0>(params);
+ const blink::WebInputEvent* event = std::get<0>(params);
SendTouchEventACK(event->type, ack_result,
WebInputEventTraits::GetUniqueTouchEventId(*event));
}
@@ -543,6 +550,30 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
}
protected:
+ BrowserContext* browser_context() { return browser_context_.get(); }
+
+ // Sets the |view| active in TextInputManager with the given |type|. |type|
+ // cannot be ui::TEXT_INPUT_TYPE_NONE.
+ void ActivateViewForTextInputManager(RenderWidgetHostViewBase* view,
+ ui::TextInputType type) {
+ DCHECK_NE(ui::TEXT_INPUT_TYPE_NONE, type);
+ TextInputManager* manager =
+ static_cast<RenderWidgetHostImpl*>(view->GetRenderWidgetHost())
+ ->delegate()
+ ->GetTextInputManager();
+ if (manager->GetActiveWidget()) {
+ manager->active_view_for_testing()->TextInputStateChanged(
+ TextInputState());
+ }
+
+ if (!view)
+ return;
+
+ TextInputState state_with_type_text;
+ state_with_type_text.type = type;
+ view->TextInputStateChanged(state_with_type_text);
+ }
+
// If true, then calls RWH::Shutdown() instead of deleting RWH.
bool widget_host_uses_shutdown_to_destroy_;
@@ -615,27 +646,12 @@ class RenderWidgetHostViewAuraOverscrollTest
protected:
void SetUpOverscrollEnvironmentWithDebounce(int debounce_interval_in_ms) {
- SetUpOverscrollEnvironmentImpl(debounce_interval_in_ms, false);
+ SetUpOverscrollEnvironmentImpl(debounce_interval_in_ms);
}
- void SetUpOverscrollEnvironmentWithWheelGestures() {
- SetUpOverscrollEnvironmentImpl(0, true);
- }
-
- void SetUpOverscrollEnvironment() {
- SetUpOverscrollEnvironmentImpl(0, false);
- }
-
- void SetUpOverscrollEnvironmentImpl(int debounce_interval_in_ms,
- bool enable_wheel_gestures) {
- CHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableWheelGestures) &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableWheelGestures));
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- enable_wheel_gestures ? switches::kEnableWheelGestures
- : switches::kDisableWheelGestures);
+ void SetUpOverscrollEnvironment() { SetUpOverscrollEnvironmentImpl(0); }
+ void SetUpOverscrollEnvironmentImpl(int debounce_interval_in_ms) {
ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
debounce_interval_in_ms);
@@ -923,8 +939,8 @@ TEST_F(RenderWidgetHostViewAuraTest, ParentMovementUpdatesScreenRect) {
ASSERT_EQ(ViewMsg_UpdateScreenRects::ID, msg->type());
ViewMsg_UpdateScreenRects::Param params;
ViewMsg_UpdateScreenRects::Read(msg, &params);
- EXPECT_EQ(gfx::Rect(24, 24, 100, 100), base::get<0>(params));
- EXPECT_EQ(gfx::Rect(1, 1, 300, 300), base::get<1>(params));
+ EXPECT_EQ(gfx::Rect(24, 24, 100, 100), std::get<0>(params));
+ EXPECT_EQ(gfx::Rect(1, 1, 300, 300), std::get<1>(params));
sink_->ClearMessages();
widget_host_->OnMessageReceived(
ViewHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
@@ -936,8 +952,8 @@ TEST_F(RenderWidgetHostViewAuraTest, ParentMovementUpdatesScreenRect) {
msg = sink_->GetMessageAt(0);
ASSERT_EQ(ViewMsg_UpdateScreenRects::ID, msg->type());
ViewMsg_UpdateScreenRects::Read(msg, &params);
- EXPECT_EQ(gfx::Rect(33, 33, 100, 100), base::get<0>(params));
- EXPECT_EQ(gfx::Rect(10, 10, 300, 300), base::get<1>(params));
+ EXPECT_EQ(gfx::Rect(33, 33, 100, 100), std::get<0>(params));
+ EXPECT_EQ(gfx::Rect(10, 10, 300, 300), std::get<1>(params));
sink_->ClearMessages();
widget_host_->OnMessageReceived(
ViewHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
@@ -1080,6 +1096,7 @@ TEST_F(RenderWidgetHostViewAuraTest, PopupClosesWhenParentLosesFocus) {
TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
view_->InitAsChild(NULL);
view_->Show();
+ ActivateViewForTextInputManager(view_, ui::TEXT_INPUT_TYPE_TEXT);
ui::CompositionText composition_text;
composition_text.text = base::ASCIIToUTF16("|a|b");
@@ -1108,22 +1125,21 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
InputMsg_ImeSetComposition::Param params;
InputMsg_ImeSetComposition::Read(msg, &params);
// composition text
- EXPECT_EQ(composition_text.text, base::get<0>(params));
+ EXPECT_EQ(composition_text.text, std::get<0>(params));
// underlines
- ASSERT_EQ(underlines.size(), base::get<1>(params).size());
+ ASSERT_EQ(underlines.size(), std::get<1>(params).size());
for (size_t i = 0; i < underlines.size(); ++i) {
- EXPECT_EQ(underlines[i].start_offset,
- base::get<1>(params)[i].startOffset);
- EXPECT_EQ(underlines[i].end_offset, base::get<1>(params)[i].endOffset);
- EXPECT_EQ(underlines[i].color, base::get<1>(params)[i].color);
- EXPECT_EQ(underlines[i].thick, base::get<1>(params)[i].thick);
+ EXPECT_EQ(underlines[i].start_offset, std::get<1>(params)[i].startOffset);
+ EXPECT_EQ(underlines[i].end_offset, std::get<1>(params)[i].endOffset);
+ EXPECT_EQ(underlines[i].color, std::get<1>(params)[i].color);
+ EXPECT_EQ(underlines[i].thick, std::get<1>(params)[i].thick);
EXPECT_EQ(underlines[i].background_color,
- base::get<1>(params)[i].backgroundColor);
+ std::get<1>(params)[i].backgroundColor);
}
- EXPECT_EQ(gfx::Range::InvalidRange(), base::get<2>(params));
+ EXPECT_EQ(gfx::Range::InvalidRange(), std::get<2>(params));
// highlighted range
- EXPECT_EQ(4, base::get<3>(params)) << "Should be the same to the caret pos";
- EXPECT_EQ(4, base::get<4>(params)) << "Should be the same to the caret pos";
+ EXPECT_EQ(4, std::get<3>(params)) << "Should be the same to the caret pos";
+ EXPECT_EQ(4, std::get<4>(params)) << "Should be the same to the caret pos";
}
view_->ImeCancelComposition();
@@ -1135,6 +1151,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
TEST_F(RenderWidgetHostViewAuraTest, FinishCompositionByMouse) {
view_->InitAsChild(NULL);
view_->Show();
+ ActivateViewForTextInputManager(view_, ui::TEXT_INPUT_TYPE_TEXT);
ui::CompositionText composition_text;
composition_text.text = base::ASCIIToUTF16("|a|b");
@@ -1242,14 +1259,14 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(20, 20), 0,
- base::Time::NowFromSystemTime() - base::Time());
+ base::TimeTicks::Now());
view_->OnTouchEvent(&move2);
EXPECT_TRUE(press.synchronous_handling_disabled());
EXPECT_EQ(ui::MotionEvent::ACTION_MOVE, pointer_state().GetAction());
EXPECT_EQ(1U, pointer_state().GetPointerCount());
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(20, 20), 0,
- base::Time::NowFromSystemTime() - base::Time());
+ base::TimeTicks::Now());
view_->OnTouchEvent(&release2);
EXPECT_TRUE(press.synchronous_handling_disabled());
EXPECT_EQ(0U, pointer_state().GetPointerCount());
@@ -1395,9 +1412,10 @@ TEST_F(RenderWidgetHostViewAuraTest, PhysicalBackingSizeWithScale) {
EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
ViewMsg_Resize::Param params;
ViewMsg_Resize::Read(msg, &params);
- EXPECT_EQ("100x100", base::get<0>(params).new_size.ToString()); // dip size
- EXPECT_EQ("100x100",
- base::get<0>(params).physical_backing_size.ToString()); // backing size
+ EXPECT_EQ("100x100", std::get<0>(params).new_size.ToString()); // dip size
+ EXPECT_EQ(
+ "100x100",
+ std::get<0>(params).physical_backing_size.ToString()); // backing size
}
widget_host_->ResetSizeAndRepaintPendingFlags();
@@ -1412,10 +1430,11 @@ TEST_F(RenderWidgetHostViewAuraTest, PhysicalBackingSizeWithScale) {
EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
ViewMsg_Resize::Param params;
ViewMsg_Resize::Read(msg, &params);
- EXPECT_EQ(2.0f, base::get<0>(params).screen_info.deviceScaleFactor);
- EXPECT_EQ("100x100", base::get<0>(params).new_size.ToString()); // dip size
- EXPECT_EQ("200x200",
- base::get<0>(params).physical_backing_size.ToString()); // backing size
+ EXPECT_EQ(2.0f, std::get<0>(params).screen_info.deviceScaleFactor);
+ EXPECT_EQ("100x100", std::get<0>(params).new_size.ToString()); // dip size
+ EXPECT_EQ(
+ "200x200",
+ std::get<0>(params).physical_backing_size.ToString()); // backing size
}
widget_host_->ResetSizeAndRepaintPendingFlags();
@@ -1430,10 +1449,11 @@ TEST_F(RenderWidgetHostViewAuraTest, PhysicalBackingSizeWithScale) {
EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
ViewMsg_Resize::Param params;
ViewMsg_Resize::Read(msg, &params);
- EXPECT_EQ(1.0f, base::get<0>(params).screen_info.deviceScaleFactor);
- EXPECT_EQ("100x100", base::get<0>(params).new_size.ToString()); // dip size
- EXPECT_EQ("100x100",
- base::get<0>(params).physical_backing_size.ToString()); // backing size
+ EXPECT_EQ(1.0f, std::get<0>(params).screen_info.deviceScaleFactor);
+ EXPECT_EQ("100x100", std::get<0>(params).new_size.ToString()); // dip size
+ EXPECT_EQ(
+ "100x100",
+ std::get<0>(params).physical_backing_size.ToString()); // backing size
}
}
@@ -1565,17 +1585,17 @@ TEST_F(RenderWidgetHostViewAuraTest, UpdateCursorIfOverSelf) {
EXPECT_EQ(0, cursor_client.calls_to_set_cursor());
}
-std::unique_ptr<cc::CompositorFrame> MakeDelegatedFrame(float scale_factor,
- gfx::Size size,
- gfx::Rect damage) {
- std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
- frame->metadata.device_scale_factor = scale_factor;
- frame->delegated_frame_data.reset(new cc::DelegatedFrameData);
+cc::CompositorFrame MakeDelegatedFrame(float scale_factor,
+ gfx::Size size,
+ gfx::Rect damage) {
+ cc::CompositorFrame frame;
+ frame.metadata.device_scale_factor = scale_factor;
+ frame.delegated_frame_data.reset(new cc::DelegatedFrameData);
std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
pass->SetNew(
cc::RenderPassId(1, 1), gfx::Rect(size), damage, gfx::Transform());
- frame->delegated_frame_data->render_pass_list.push_back(std::move(pass));
+ frame.delegated_frame_data->render_pass_list.push_back(std::move(pass));
return frame;
}
@@ -1597,17 +1617,15 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
ViewMsg_Resize::Param params;
ViewMsg_Resize::Read(msg, &params);
- EXPECT_EQ("0,0 800x600",
- gfx::Rect(
- base::get<0>(params).screen_info.availableRect).ToString());
- EXPECT_EQ("800x600", base::get<0>(params).new_size.ToString());
+ EXPECT_EQ(
+ "0,0 800x600",
+ gfx::Rect(std::get<0>(params).screen_info.availableRect).ToString());
+ EXPECT_EQ("800x600", std::get<0>(params).new_size.ToString());
// Resizes are blocked until we swapped a frame of the correct size, and
// we've committed it.
view_->OnSwapCompositorFrame(
- 0,
- MakeDelegatedFrame(
- 1.f, base::get<0>(params).new_size,
- gfx::Rect(base::get<0>(params).new_size)));
+ 0, MakeDelegatedFrame(1.f, std::get<0>(params).new_size,
+ gfx::Rect(std::get<0>(params).new_size)));
ui::DrawWaiterForTest::WaitForCommit(
root_window->GetHost()->compositor());
}
@@ -1624,15 +1642,13 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
ViewMsg_Resize::Param params;
ViewMsg_Resize::Read(msg, &params);
- EXPECT_EQ("0,0 1600x1200",
- gfx::Rect(
- base::get<0>(params).screen_info.availableRect).ToString());
- EXPECT_EQ("1600x1200", base::get<0>(params).new_size.ToString());
+ EXPECT_EQ(
+ "0,0 1600x1200",
+ gfx::Rect(std::get<0>(params).screen_info.availableRect).ToString());
+ EXPECT_EQ("1600x1200", std::get<0>(params).new_size.ToString());
view_->OnSwapCompositorFrame(
- 0,
- MakeDelegatedFrame(
- 1.f, base::get<0>(params).new_size,
- gfx::Rect(base::get<0>(params).new_size)));
+ 0, MakeDelegatedFrame(1.f, std::get<0>(params).new_size,
+ gfx::Rect(std::get<0>(params).new_size)));
ui::DrawWaiterForTest::WaitForCommit(
root_window->GetHost()->compositor());
}
@@ -1714,9 +1730,9 @@ TEST_F(RenderWidgetHostViewAuraTest, DelegatedFrameGutter) {
gfx::Rect());
view_->SetSize(large_size);
view_->Show();
- std::unique_ptr<cc::CompositorFrame> frame =
+ cc::CompositorFrame frame =
MakeDelegatedFrame(1.f, small_size, gfx::Rect(small_size));
- frame->metadata.root_background_color = SK_ColorRED;
+ frame.metadata.root_background_color = SK_ColorRED;
view_->OnSwapCompositorFrame(0, std::move(frame));
ui::Layer* parent_layer = view_->GetNativeView()->layer();
@@ -1783,7 +1799,7 @@ TEST_F(RenderWidgetHostViewAuraTest, Resize) {
EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
ViewMsg_Resize::Param params;
ViewMsg_Resize::Read(msg, &params);
- EXPECT_EQ(size2.ToString(), base::get<0>(params).new_size.ToString());
+ EXPECT_EQ(size2.ToString(), std::get<0>(params).new_size.ToString());
}
// Send resize ack to observe new Resize messages.
update_params.view_size = size2;
@@ -1838,7 +1854,7 @@ TEST_F(RenderWidgetHostViewAuraTest, Resize) {
// to this extra IPC coming in.
InputMsg_HandleInputEvent::Param params;
InputMsg_HandleInputEvent::Read(msg, &params);
- const blink::WebInputEvent* event = base::get<0>(params);
+ const blink::WebInputEvent* event = std::get<0>(params);
EXPECT_EQ(blink::WebInputEvent::MouseMove, event->type);
break;
}
@@ -1848,7 +1864,7 @@ TEST_F(RenderWidgetHostViewAuraTest, Resize) {
EXPECT_FALSE(has_resize);
ViewMsg_Resize::Param params;
ViewMsg_Resize::Read(msg, &params);
- EXPECT_EQ(size3.ToString(), base::get<0>(params).new_size.ToString());
+ EXPECT_EQ(size3.ToString(), std::get<0>(params).new_size.ToString());
has_resize = true;
break;
}
@@ -2605,7 +2621,7 @@ TEST_F(RenderWidgetHostViewAuraTest, VisibleViewportTest) {
ViewMsg_Resize::Param params;
ViewMsg_Resize::Read(message, &params);
- EXPECT_EQ(60, base::get<0>(params).visible_viewport_size.height());
+ EXPECT_EQ(60, std::get<0>(params).visible_viewport_size.height());
}
// Ensures that touch event positions are never truncated to integers.
@@ -2628,8 +2644,6 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventPositionsArentRounded) {
EXPECT_EQ(kY, pointer_state().GetY(0));
}
-// Tests that scroll ACKs are correctly handled by the overscroll-navigation
-// controller.
TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollEventOverscrolls) {
SetUpOverscrollEnvironment();
@@ -2646,58 +2660,6 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollEventOverscrolls) {
// Receive ACK the first wheel event as not processed.
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Receive ACK for the second (coalesced) event as not processed. This will
- // start a back navigation. However, this will also cause the queued next
- // event to be sent to the renderer. But since overscroll navigation has
- // started, that event will also be included in the overscroll computation
- // instead of being sent to the renderer. So the result will be an overscroll
- // back navigation, and no event will be sent to the renderer.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
- EXPECT_EQ(-81.f, overscroll_delta_x());
- EXPECT_EQ(-31.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
- EXPECT_EQ(0U, sink_->message_count());
-
- // Send a mouse-move event. This should cancel the overscroll navigation.
- SimulateMouseMove(5, 10, 0);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, sink_->message_count());
-}
-
-// Disabled on MacOS because it doesn't support wheel gestures
-// just yet.
-#if defined(OS_MACOSX)
-#define MAYBE_WheelScrollEventOverscrollsWithWheelGestures \
- DISABLED_WheelScrollEventOverscrollsWithWheelGestures
-#else
-#define MAYBE_WheelScrollEventOverscrollsWithWheelGestures \
- WheelScrollEventOverscrollsWithWheelGestures
-#endif
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- MAYBE_WheelScrollEventOverscrollsWithWheelGestures) {
- SetUpOverscrollEnvironmentWithWheelGestures();
-
- // Simulate wheel events.
- SimulateWheelEvent(-5, 0, 0, true); // sent directly
- SimulateWheelEvent(-1, 1, 0, true); // enqueued
- SimulateWheelEvent(-10, -3, 0, true); // coalesced into previous event
- SimulateWheelEvent(-15, -1, 0, true); // coalesced into previous event
- SimulateWheelEvent(-30, -3, 0, true); // coalesced into previous event
- SimulateWheelEvent(-20, 6, 1, true); // enqueued, different modifiers
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Receive ACK the first wheel event as not processed.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
// ScrollBegin, ScrollUpdate, MouseWheel will be queued events
EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
@@ -2753,79 +2715,6 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// Receive ACK the first wheel event as processed.
- SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Receive ACK for the second (coalesced) event as not processed. This should
- // not initiate overscroll, since the beginning of the scroll has been
- // consumed. The queued event with different modifiers should be sent to the
- // renderer.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, sink_->message_count());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
-
- // Indicate the end of the scrolling from the touchpad.
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- blink::WebGestureDeviceTouchscreen);
- SimulateGestureFlingStartEvent(-1200.f, 0.f, blink::WebGestureDeviceTouchpad);
- EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
-
- // Start another scroll. This time, do not consume any scroll events.
- SimulateWheelEvent(0, -5, 0, true); // sent directly
- SimulateWheelEvent(0, -1, 0, true); // enqueued
- SimulateWheelEvent(-10, -3, 0, true); // coalesced into previous event
- SimulateWheelEvent(-15, -1, 0, true); // coalesced into previous event
- SimulateWheelEvent(-30, -3, 0, true); // coalesced into previous event
- SimulateWheelEvent(-20, 6, 1, true); // enqueued, different modifiers
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Receive ACK for the first wheel and the subsequent coalesced event as not
- // processed. This should start a back-overscroll.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
-}
-
-// Tests that if some scroll events are consumed towards the start, then
-// subsequent scrolls do not horizontal overscroll.
-// Disabled on MacOS because it doesn't support wheel gestures
-// just yet.
-#if defined(OS_MACOSX)
-#define MAYBE_WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures \
- DISABLED_WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures
-#else
-#define MAYBE_WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures \
- WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures
-#endif
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- MAYBE_WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures) {
- SetUpOverscrollEnvironmentWithWheelGestures();
-
- // Simulate wheel events.
- SimulateWheelEvent(-5, 0, 0, true); // sent directly
- SimulateWheelEvent(-1, -1, 0, true); // enqueued
- SimulateWheelEvent(-10, -3, 0, true); // coalesced into previous event
- SimulateWheelEvent(-15, -1, 0, true); // coalesced into previous event
- SimulateWheelEvent(-30, -3, 0, true); // coalesced into previous event
- SimulateWheelEvent(-20, 6, 1, true); // enqueued, different modifiers
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Receive ACK the first wheel event as processed.
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
// ScrollBegin, ScrollUpdate, MouseWheel will be queued events
@@ -2866,75 +2755,6 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollOverscrollToggle) {
// Send a wheel event. ACK the event as not processed. This should not
// initiate an overscroll gesture since it doesn't cross the threshold yet.
SimulateWheelEvent(10, 0, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Scroll some more so as to not overscroll.
- SimulateWheelEvent(10, 0, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Scroll some more to initiate an overscroll.
- SimulateWheelEvent(40, 0, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
- EXPECT_EQ(60.f, overscroll_delta_x());
- EXPECT_EQ(10.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Scroll in the reverse direction enough to abort the overscroll.
- SimulateWheelEvent(-20, 0, 0, true);
- EXPECT_EQ(0U, sink_->message_count());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
-
- // Continue to scroll in the reverse direction.
- SimulateWheelEvent(-20, 0, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Continue to scroll in the reverse direction enough to initiate overscroll
- // in that direction.
- SimulateWheelEvent(-55, 0, 0, true);
- EXPECT_EQ(1U, sink_->message_count());
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
- EXPECT_EQ(-75.f, overscroll_delta_x());
- EXPECT_EQ(-25.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
-}
-
-// Tests that wheel-scrolling correctly turns overscroll on and off.
-// Disabled on MacOS because it doesn't support wheel gestures
-// just yet.
-#if defined(OS_MACOSX)
-#define MAYBE_WheelScrollOverscrollToggleWithWheelGestures \
- DISABLED_WheelScrollOverscrollToggleWithWheelGestures
-#else
-#define MAYBE_WheelScrollOverscrollToggleWithWheelGestures \
- WheelScrollOverscrollToggleWithWheelGestures
-#endif
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- MAYBE_WheelScrollOverscrollToggleWithWheelGestures) {
- SetUpOverscrollEnvironmentWithWheelGestures();
-
- // Send a wheel event. ACK the event as not processed. This should not
- // initiate an overscroll gesture since it doesn't cross the threshold yet.
- SimulateWheelEvent(10, 0, 0, true);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
@@ -3014,58 +2834,6 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
// Send a wheel event. ACK the event as not processed. This should not
// initiate an overscroll gesture since it doesn't cross the threshold yet.
SimulateWheelEvent(10, 0, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Scroll some more so as to not overscroll.
- SimulateWheelEvent(20, 0, 0, true);
- EXPECT_EQ(1U, sink_->message_count());
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- sink_->ClearMessages();
-
- // Scroll some more to initiate an overscroll.
- SimulateWheelEvent(30, 0, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
- EXPECT_EQ(60.f, overscroll_delta_x());
- EXPECT_EQ(10.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Send a fling start, but with a small velocity, so that the overscroll is
- // aborted. The fling should proceed to the renderer, through the gesture
- // event filter.
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- blink::WebGestureDeviceTouchscreen);
- SimulateGestureFlingStartEvent(0.f, 0.1f, blink::WebGestureDeviceTouchpad);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(2U, sink_->message_count());
-}
-
-// Disabled on MacOS because it doesn't support wheel gestures
-// just yet.
-#if defined(OS_MACOSX)
-#define MAYBE_ScrollEventsOverscrollWithFlingAndWheelGestures \
- DISABLED_ScrollEventsOverscrollWithFlingAndWheelGestures
-#else
-#define MAYBE_ScrollEventsOverscrollWithFlingAndWheelGestures \
- ScrollEventsOverscrollWithFlingAndWheelGestures
-#endif
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- MAYBE_ScrollEventsOverscrollWithFlingAndWheelGestures) {
- SetUpOverscrollEnvironmentWithWheelGestures();
-
- // Send a wheel event. ACK the event as not processed. This should not
- // initiate an overscroll gesture since it doesn't cross the threshold yet.
- SimulateWheelEvent(10, 0, 0, true);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
@@ -3121,59 +2889,6 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
// Send a wheel event. ACK the event as not processed. This should not
// initiate an overscroll gesture since it doesn't cross the threshold yet.
SimulateWheelEvent(10, 0, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Scroll some more so as to not overscroll.
- SimulateWheelEvent(20, 0, 0, true);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
-
- // Scroll some more to initiate an overscroll.
- SimulateWheelEvent(30, 0, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
- EXPECT_EQ(60.f, overscroll_delta_x());
- EXPECT_EQ(10.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Send a fling start, but with a small velocity, so that the overscroll is
- // aborted. The fling should proceed to the renderer, through the gesture
- // event filter.
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- blink::WebGestureDeviceTouchscreen);
- SimulateGestureFlingStartEvent(10.f, 0.f, blink::WebGestureDeviceTouchpad);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(2U, sink_->message_count());
-}
-
-// Same as ScrollEventsOverscrollWithFling, but with zero velocity. Checks that
-// the zero-velocity fling does not reach the renderer.
-// Disabled on MacOS because it doesn't support wheel gestures
-// just yet.
-#if defined(OS_MACOSX)
-#define MAYBE_ScrollEventsOverscrollWithZeroFlingAndWheelGestures \
- DISABLED_ScrollEventsOverscrollWithZeroFlingAndWheelGestures
-#else
-#define MAYBE_ScrollEventsOverscrollWithZeroFlingAndWheelGestures \
- ScrollEventsOverscrollWithZeroFlingAndWheelGestures
-#endif
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- MAYBE_ScrollEventsOverscrollWithZeroFlingAndWheelGestures) {
- SetUpOverscrollEnvironmentWithWheelGestures();
-
- // Send a wheel event. ACK the event as not processed. This should not
- // initiate an overscroll gesture since it doesn't cross the threshold yet.
- SimulateWheelEvent(10, 0, 0, true);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
@@ -3435,7 +3150,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
// enough overscroll to complete the gesture, the overscroll controller
// will reset the state. The scroll-end should therefore be dispatched to the
// renderer, and the gesture-event-filter should await an ACK for it.
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
base::TimeDelta::FromMilliseconds(15));
base::MessageLoop::current()->Run();
@@ -3542,7 +3257,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) {
SimulateGestureEvent(blink::WebInputEvent::GestureScrollEnd,
blink::WebGestureDeviceTouchscreen);
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
base::TimeDelta::FromMilliseconds(10));
base::MessageLoop::current()->Run();
@@ -3588,7 +3303,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
SimulateGestureEvent(blink::WebInputEvent::GestureScrollEnd,
blink::WebGestureDeviceTouchscreen);
EXPECT_EQ(0U, sink_->message_count());
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
base::TimeDelta::FromMilliseconds(10));
base::MessageLoop::current()->Run();
@@ -3623,7 +3338,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
SimulateGestureEvent(blink::WebInputEvent::GestureScrollEnd,
blink::WebGestureDeviceTouchscreen);
EXPECT_EQ(0U, sink_->message_count());
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
base::TimeDelta::FromMilliseconds(10));
base::MessageLoop::current()->Run();
@@ -3674,42 +3389,6 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
- EXPECT_EQ(0U, sink_->message_count());
-
- // Send another wheel event, but in the reverse direction. The overscroll
- // controller will not consume the event, because it is not triggering
- // gesture-nav.
- SimulateWheelEvent(-260, 0, 0, true);
- EXPECT_EQ(1U, sink_->message_count());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
-
- // Since the overscroll mode has been reset, the next wheel event should reach
- // the renderer.
- SimulateWheelEvent(-20, 0, 0, true);
- EXPECT_EQ(1U, sink_->message_count());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
-}
-
-// Disabled on MacOS because it doesn't support wheel gestures
-// just yet.
-#if defined(OS_MACOSX)
-#define MAYBE_OverscrollDirectionChangeMouseWheelWithWheelGestures \
- DISABLED_OverscrollDirectionChangeMouseWheelWithWheelGestures
-#else
-#define MAYBE_OverscrollDirectionChangeMouseWheelWithWheelGestures \
- OverscrollDirectionChangeMouseWheelWithWheelGestures
-#endif
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- MAYBE_OverscrollDirectionChangeMouseWheelWithWheelGestures) {
- SetUpOverscrollEnvironmentWithWheelGestures();
-
- // Send wheel event and receive ack as not consumed.
- SimulateWheelEvent(125, -5, 0, true);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
// ScrollBegin, ScrollUpdate messages.
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
@@ -3747,8 +3426,6 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
}
-// Tests that if a mouse-move event completes the overscroll gesture, future
-// move events do reach the renderer.
TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollMouseMoveCompletion) {
SetUpOverscrollEnvironment();
@@ -3763,96 +3440,6 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollMouseMoveCompletion) {
// Receive ACK the first wheel event as not processed.
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Receive ACK for the second (coalesced) event as not processed. This will
- // start an overcroll gesture.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
- EXPECT_EQ(0U, sink_->message_count());
-
- // Send a mouse-move event. This should cancel the overscroll navigation
- // (since the amount overscrolled is not above the threshold), and so the
- // mouse-move should reach the renderer.
- SimulateMouseMove(5, 10, 0);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->completed_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- SendInputEventACK(WebInputEvent::MouseMove,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Moving the mouse more should continue to send the events to the renderer.
- SimulateMouseMove(5, 10, 0);
- SendInputEventACK(WebInputEvent::MouseMove,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Now try with gestures.
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- blink::WebGestureDeviceTouchscreen);
- SimulateGestureScrollUpdateEvent(300, -5, 0);
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
- sink_->ClearMessages();
-
- // Overscroll gesture is in progress. Send a mouse-move now. This should
- // complete the gesture (because the amount overscrolled is above the
- // threshold).
- SimulateMouseMove(5, 10, 0);
- EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->completed_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- SendInputEventACK(WebInputEvent::MouseMove,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
- blink::WebGestureDeviceTouchscreen);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Move mouse some more. The mouse-move events should reach the renderer.
- SimulateMouseMove(5, 10, 0);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- SendInputEventACK(WebInputEvent::MouseMove,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-}
-
-// Tests that if a mouse-move event completes the overscroll gesture, future
-// move events do reach the renderer.
-// Disabled on MacOS because it doesn't support wheel gestures
-// just yet.
-#if defined(OS_MACOSX)
-#define MAYBE_OverscrollMouseMoveCompletionWheelGestures \
- DISABLED_OverscrollMouseMoveCompletionWheelGestures
-#else
-#define MAYBE_OverscrollMouseMoveCompletionWheelGestures \
- OverscrollMouseMoveCompletionWheelGestures
-#endif
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- MAYBE_OverscrollMouseMoveCompletionWheelGestures) {
- SetUpOverscrollEnvironmentWithWheelGestures();
-
- SimulateWheelEvent(5, 0, 0, true); // sent directly
- SimulateWheelEvent(-1, 0, 0, true); // enqueued
- SimulateWheelEvent(-10, -3, 0, true); // coalesced into previous event
- SimulateWheelEvent(-15, -1, 0, true); // coalesced into previous event
- SimulateWheelEvent(-30, -3, 0, true); // coalesced into previous event
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Receive ACK the first wheel event as not processed.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
@@ -3936,12 +3523,18 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// The first wheel event is consumed. Dispatches the queued wheel event.
- SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_TRUE(ScrollStateIsContentScrolling());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
// The second wheel event is consumed.
- SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_TRUE(ScrollStateIsContentScrolling());
// Touchpad scroll can end with a zero-velocity fling. But it is not
@@ -3950,7 +3543,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
blink::WebGestureDeviceTouchscreen);
SimulateGestureFlingStartEvent(0.f, 0.f, blink::WebGestureDeviceTouchpad);
EXPECT_TRUE(ScrollStateIsUnknown());
- EXPECT_EQ(1U, sink_->message_count());
+ EXPECT_EQ(3U, sink_->message_count());
// Dropped flings should neither propagate *nor* indicate that they were
// consumed and have triggered a fling animation (as tracked by the router).
@@ -3963,20 +3556,24 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
SimulateWheelEvent(-60, 0, 0, true); // enqueued
SimulateWheelEvent(-100, 0, 0, true); // coalesced into previous event
EXPECT_TRUE(ScrollStateIsUnknown());
- EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(5U, GetSentMessageCountAndResetSink());
// The first wheel scroll did not scroll content. Overscroll should not start
// yet, since enough hasn't been scrolled.
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_TRUE(ScrollStateIsUnknown());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
EXPECT_TRUE(ScrollStateIsOverscrolling());
- EXPECT_EQ(0U, sink_->message_count());
+ EXPECT_EQ(1U, sink_->message_count());
// The GestureScrollBegin will reset the delegate's mode, so check it here.
EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
@@ -3985,7 +3582,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
SimulateGestureFlingStartEvent(0.f, 0.f, blink::WebGestureDeviceTouchpad);
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_TRUE(ScrollStateIsUnknown());
- EXPECT_EQ(1U, sink_->message_count());
+ EXPECT_EQ(3U, sink_->message_count());
EXPECT_FALSE(parent_host_->input_router()->HasPendingEvents());
}
@@ -4105,9 +3702,9 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
GetInputEventFromMessage(*sink_->GetMessageAt(0));
const WebMouseWheelEvent* wheel_event =
static_cast<const WebMouseWheelEvent*>(input_event);
- // Check if the canScroll set to false when ctrl-scroll is generated from
+ // Check if scroll is caused when ctrl-scroll is generated from
// mouse wheel event.
- EXPECT_FALSE(wheel_event->canScroll);
+ EXPECT_FALSE(WebInputEventTraits::CanCauseScroll(*wheel_event));
sink_->ClearMessages();
// Ack'ing the outstanding event should flush the pending event queue.
@@ -4122,9 +3719,9 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
input_event = GetInputEventFromMessage(*sink_->GetMessageAt(0));
wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
- // Check if the canScroll set to true when no modifier is applied to the
+ // Check if scroll is caused when no modifier is applied to the
// mouse wheel event.
- EXPECT_TRUE(wheel_event->canScroll);
+ EXPECT_TRUE(WebInputEventTraits::CanCauseScroll(*wheel_event));
sink_->ClearMessages();
SendInputEventACK(blink::WebInputEvent::MouseWheel,
@@ -4137,9 +3734,9 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
input_event = GetInputEventFromMessage(*sink_->GetMessageAt(0));
wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
- // Check if the canScroll set to true when ctrl-touchpad-scroll is generated
+ // Check if scroll is caused when ctrl-touchpad-scroll is generated
// from scroll event.
- EXPECT_TRUE(wheel_event->canScroll);
+ EXPECT_TRUE(WebInputEventTraits::CanCauseScroll(*wheel_event));
}
// Ensures that the mapping from ui::TouchEvent to blink::WebTouchEvent doesn't
@@ -4171,63 +3768,6 @@ TEST_F(RenderWidgetHostViewAuraTest, CorrectNumberOfAcksAreDispatched) {
TEST_F(RenderWidgetHostViewAuraOverscrollTest, ScrollDeltasResetOnEnd) {
SetUpOverscrollEnvironment();
// Wheel event scroll ending with mouse move.
- SimulateWheelEvent(-30, -10, 0, true); // sent directly
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(-30.f, overscroll_delta_x());
- EXPECT_EQ(-10.f, overscroll_delta_y());
- SimulateMouseMove(5, 10, 0);
- EXPECT_EQ(0.f, overscroll_delta_x());
- EXPECT_EQ(0.f, overscroll_delta_y());
-
- // Scroll gesture.
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- blink::WebGestureDeviceTouchscreen);
- SimulateGestureScrollUpdateEvent(-30, -5, 0);
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(-30.f, overscroll_delta_x());
- EXPECT_EQ(-5.f, overscroll_delta_y());
- SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
- blink::WebGestureDeviceTouchscreen);
- EXPECT_EQ(0.f, overscroll_delta_x());
- EXPECT_EQ(0.f, overscroll_delta_y());
-
- // Wheel event scroll ending with a fling.
- SimulateWheelEvent(5, 0, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- SimulateWheelEvent(10, -5, 0, true);
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
- EXPECT_EQ(15.f, overscroll_delta_x());
- EXPECT_EQ(-5.f, overscroll_delta_y());
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- blink::WebGestureDeviceTouchscreen);
- SimulateGestureFlingStartEvent(0.f, 0.1f, blink::WebGestureDeviceTouchpad);
- EXPECT_EQ(0.f, overscroll_delta_x());
- EXPECT_EQ(0.f, overscroll_delta_y());
-}
-
-// Tests that the scroll deltas stored within the overscroll controller get
-// reset at the end of the overscroll gesture even if the overscroll threshold
-// isn't surpassed and the overscroll mode stays OVERSCROLL_NONE.
-// Disabled on MacOS because it doesn't support wheel gestures
-// just yet.
-#if defined(OS_MACOSX)
-#define MAYBE_ScrollDeltasResetOnEndWithWheelGestures \
- DISABLED_ScrollDeltasResetOnEndWithWheelGestures
-#else
-#define MAYBE_ScrollDeltasResetOnEndWithWheelGestures \
- ScrollDeltasResetOnEndWithWheelGestures
-#endif
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
- MAYBE_ScrollDeltasResetOnEndWithWheelGestures) {
- SetUpOverscrollEnvironmentWithWheelGestures();
- // Wheel event scroll ending with mouse move.
SimulateWheelEvent(-30, -10, 0, true); // sent directly
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
@@ -4333,7 +3873,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SurfaceIdNamespaceInitialized) {
view_->SetSize(size);
view_->OnSwapCompositorFrame(0,
MakeDelegatedFrame(1.f, size, gfx::Rect(size)));
- EXPECT_EQ(view_->GetSurfaceIdNamespace(), base::get<0>(params));
+ EXPECT_EQ(view_->GetSurfaceIdNamespace(), std::get<0>(params));
}
// This class provides functionality to test a RenderWidgetHostViewAura
@@ -4348,9 +3888,6 @@ class RenderWidgetHostViewAuraWithViewHarnessTest
protected:
void SetUp() override {
- ImageTransportFactory::InitializeForUnitTests(
- std::unique_ptr<ImageTransportFactory>(
- new NoTransportImageTransportFactory));
RenderViewHostImplTestHarness::SetUp();
// Delete the current RenderWidgetHostView instance before setting
// the RWHVA as the view.
@@ -4364,7 +3901,6 @@ class RenderWidgetHostViewAuraWithViewHarnessTest
void TearDown() override {
view_->Destroy();
RenderViewHostImplTestHarness::TearDown();
- ImageTransportFactory::Terminate();
}
RenderWidgetHostViewAura* view() {
@@ -4491,4 +4027,210 @@ TEST_F(RenderWidgetHostViewAuraWithViewHarnessTest,
RenderViewHostFactory::set_is_real_render_view_host(false);
}
+// ----------------------------------------------------------------------------
+// TextInputManager and IME-Related Tests
+
+// A group of tests which verify that the IME method results are routed to the
+// right RenderWidget in the OOPIF structure.
+// In each test, 3 views are created where one is in process with main frame and
+// the other two are in distinct processes (this makes a total of 4 RWHVs). Then
+// each test will verify the correctness of routing for one of the IME result
+// methods. The method is called on ui::TextInputClient (i.e., RWHV for the tab
+// in aura) and then the test verifies that the IPC is routed to the
+// RenderWidget corresponding to the active view (i.e., the RenderWidget
+// with focused <input>).
+class InputMethodResultAuraTest : public RenderWidgetHostViewAuraTest {
+ public:
+ InputMethodResultAuraTest() {}
+ ~InputMethodResultAuraTest() override {}
+
+ void SetUp() override {
+ RenderWidgetHostViewAuraTest::SetUp();
+ InitializeAura();
+
+ view_for_first_process_ = CreateViewForProcess(tab_process());
+
+ second_process_host_ = CreateNewProcessHost();
+ view_for_second_process_ = CreateViewForProcess(second_process_host_);
+
+ third_process_host_ = CreateNewProcessHost();
+ view_for_third_process_ = CreateViewForProcess(third_process_host_);
+
+ views_.insert(views_.begin(),
+ {tab_view(), view_for_first_process_,
+ view_for_second_process_, view_for_third_process_});
+ processes_.insert(processes_.begin(),
+ {tab_process(), tab_process(), second_process_host_,
+ third_process_host_});
+ active_view_sequence_.insert(active_view_sequence_.begin(),
+ {0, 1, 2, 1, 1, 3, 0, 3, 1});
+ }
+
+ void TearDown() override {
+ RenderWidgetHost* widget_for_first_process =
+ view_for_first_process_->GetRenderWidgetHost();
+ view_for_first_process_->Destroy();
+ delete widget_for_first_process;
+
+ RenderWidgetHost* widget_for_second_process =
+ view_for_second_process_->GetRenderWidgetHost();
+ view_for_second_process_->Destroy();
+ delete widget_for_second_process;
+
+ RenderWidgetHost* widget_for_third_process =
+ view_for_third_process_->GetRenderWidgetHost();
+ view_for_third_process_->Destroy();
+ delete widget_for_third_process;
+
+ RenderWidgetHostViewAuraTest::TearDown();
+ }
+
+ protected:
+ const IPC::Message* RunAndReturnIPCSent(const base::Closure closure,
+ MockRenderProcessHost* process,
+ int32_t message_id) {
+ process->sink().ClearMessages();
+ closure.Run();
+ return process->sink().GetFirstMessageMatching(message_id);
+ }
+
+ MockRenderWidgetHostDelegate* render_widget_host_delegate() const {
+ return delegates_.back().get();
+ }
+
+ ui::TextInputClient* text_input_client() const { return view_; }
+
+ bool has_composition_text() const {
+ return tab_view()->has_composition_text_;
+ }
+
+ MockRenderProcessHost* CreateNewProcessHost() {
+ MockRenderProcessHost* process_host =
+ new MockRenderProcessHost(browser_context());
+ return process_host;
+ }
+
+ RenderWidgetHostImpl* CreateRenderWidgetHostForProcess(
+ MockRenderProcessHost* process_host) {
+ return new RenderWidgetHostImpl(render_widget_host_delegate(), process_host,
+ process_host->GetNextRoutingID(), false);
+ }
+
+ TestRenderWidgetHostView* CreateViewForProcess(
+ MockRenderProcessHost* process_host) {
+ RenderWidgetHostImpl* host = CreateRenderWidgetHostForProcess(process_host);
+ TestRenderWidgetHostView* view = new TestRenderWidgetHostView(host);
+ host->SetView(view);
+ return view;
+ }
+
+ void SetHasCompositionTextToTrue() {
+ ui::CompositionText composition_text;
+ composition_text.text = base::ASCIIToUTF16("text");
+ tab_view()->SetCompositionText(composition_text);
+ EXPECT_TRUE(has_composition_text());
+ }
+
+ MockRenderProcessHost* tab_process() const { return process_host_; }
+
+ RenderWidgetHostViewAura* tab_view() const { return view_; }
+
+ std::vector<RenderWidgetHostViewBase*> views_;
+ std::vector<MockRenderProcessHost*> processes_;
+ // A sequence of indices in [0, 3] which determines the index of a RWHV in
+ // |views_|. This sequence is used in the tests to sequentially make a RWHV
+ // active for a subsequent IME result method call.
+ std::vector<size_t> active_view_sequence_;
+
+ private:
+ // This will initialize |window_| in RenderWidgetHostViewAura. It is needed
+ // for RenderWidgetHostViewAura::GetInputMethod() to work.
+ void InitializeAura() {
+ view_->InitAsChild(nullptr);
+ view_->Show();
+ }
+
+ TestRenderWidgetHostView* view_for_first_process_;
+ MockRenderProcessHost* second_process_host_;
+ TestRenderWidgetHostView* view_for_second_process_;
+ MockRenderProcessHost* third_process_host_;
+ TestRenderWidgetHostView* view_for_third_process_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputMethodResultAuraTest);
+};
+
+// This test verifies that ui::TextInputClient::SetCompositionText call leads to
+// IPC message InputMsg_ImeSetComposition being sent to the right renderer
+// process.
+TEST_F(InputMethodResultAuraTest, SetCompositionText) {
+ base::Closure ime_call =
+ base::Bind(&ui::TextInputClient::SetCompositionText,
+ base::Unretained(text_input_client()), ui::CompositionText());
+ for (auto index : active_view_sequence_) {
+ ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT);
+ EXPECT_TRUE(!!RunAndReturnIPCSent(ime_call, processes_[index],
+ InputMsg_ImeSetComposition::ID));
+ }
+}
+
+// This test verifies that ui::TextInputClient::ConfirmCompositionText call
+// leads to IPC message InputMsg_ImeConfirmComposition being sent to the right
+// renderer process.
+TEST_F(InputMethodResultAuraTest, ConfirmCompositionText) {
+ base::Closure ime_call =
+ base::Bind(&ui::TextInputClient::ConfirmCompositionText,
+ base::Unretained(text_input_client()));
+ for (auto index : active_view_sequence_) {
+ ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT);
+ SetHasCompositionTextToTrue();
+ EXPECT_TRUE(!!RunAndReturnIPCSent(ime_call, processes_[index],
+ InputMsg_ImeConfirmComposition::ID));
+ }
+}
+
+// This test verifies that ui::TextInputClient::ConfirmCompositionText call
+// leads to IPC message InputMsg_ImeSetComposition being sent to the right
+// renderer process.
+TEST_F(InputMethodResultAuraTest, ClearCompositionText) {
+ base::Closure ime_call =
+ base::Bind(&ui::TextInputClient::ClearCompositionText,
+ base::Unretained(text_input_client()));
+ for (auto index : active_view_sequence_) {
+ ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT);
+ SetHasCompositionTextToTrue();
+ EXPECT_TRUE(!!RunAndReturnIPCSent(ime_call, processes_[index],
+ InputMsg_ImeSetComposition::ID));
+ }
+}
+
+// This test verifies that ui::TextInputClient::InsertText call leads to IPC
+// message InputMsg_ImeSetComposition being sent to the right renderer process.
+TEST_F(InputMethodResultAuraTest, InsertText) {
+ base::Closure ime_call =
+ base::Bind(&ui::TextInputClient::InsertText,
+ base::Unretained(text_input_client()), base::string16());
+ for (auto index : active_view_sequence_) {
+ ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT);
+ EXPECT_TRUE(!!RunAndReturnIPCSent(ime_call, processes_[index],
+ InputMsg_ImeConfirmComposition::ID));
+ }
+}
+
+// This test makes a specific child frame's view active and then forces the
+// tab's view end the current IME composition session by sending out an IME
+// IPC to confirm composition. The test then verifies that the message is sent
+// to the active widget's process.
+TEST_F(InputMethodResultAuraTest, FinishImeCompositionSession) {
+ base::Closure ime_finish_session_call =
+ base::Bind(&RenderWidgetHostViewAura::FinishImeCompositionSession,
+ base::Unretained(tab_view()));
+ for (auto index : active_view_sequence_) {
+ ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT);
+ SetHasCompositionTextToTrue();
+ EXPECT_TRUE(!!RunAndReturnIPCSent(ime_finish_session_call,
+ processes_[index],
+ InputMsg_ImeConfirmComposition::ID));
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
index dd88faea8fa..0b34ce08789 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
@@ -13,6 +13,7 @@
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
+#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/content_switches_internal.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "ui/display/display.h"
@@ -40,6 +41,7 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase()
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) {}
@@ -53,6 +55,10 @@ RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
// NotifyObserversAboutShutdown() twice, as the observers are required to
// de-register on the first call, and so the second call does nothing.
NotifyObserversAboutShutdown();
+ // If we have a live reference to |text_input_manager_|, we should unregister
+ // so that the |text_input_manager_| will free its state.
+ if (text_input_manager_)
+ text_input_manager_->Unregister(this);
}
void RenderWidgetHostViewBase::NotifyObserversAboutShutdown() {
@@ -228,6 +234,13 @@ bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) {
return true;
}
+void RenderWidgetHostViewBase::DidUnregisterFromTextInputManager(
+ TextInputManager* text_input_manager) {
+ DCHECK(text_input_manager && text_input_manager_ == text_input_manager);
+
+ text_input_manager_ = nullptr;
+}
+
base::WeakPtr<RenderWidgetHostViewBase> RenderWidgetHostViewBase::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
@@ -250,6 +263,12 @@ void RenderWidgetHostViewBase::EndFrameSubscription() {
NOTREACHED();
}
+void RenderWidgetHostViewBase::FocusedNodeTouched(
+ const gfx::Point& location_dips_screen,
+ bool editable) {
+ DVLOG(1) << "FocusedNodeTouched: " << editable;
+}
+
uint32_t RenderWidgetHostViewBase::RendererFrameNumber() {
return renderer_frame_number_;
}
@@ -382,6 +401,41 @@ void RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
*transformed_point = point;
}
+void RenderWidgetHostViewBase::TextInputStateChanged(
+ const TextInputState& text_input_state) {
+// TODO(ekaramad): Use TextInputManager code paths for IME on other platforms.
+#if defined(USE_AURA)
+ if (GetTextInputManager())
+ GetTextInputManager()->UpdateTextInputState(this, text_input_state);
+#endif
+}
+
+void RenderWidgetHostViewBase::ImeCancelComposition() {
+// TODO(ekaramad): Use TextInputManager code paths for IME on other platforms.
+#if defined(USE_AURA)
+ if (GetTextInputManager())
+ GetTextInputManager()->ImeCancelComposition(this);
+#endif
+}
+
+TextInputManager* RenderWidgetHostViewBase::GetTextInputManager() {
+ if (text_input_manager_)
+ return text_input_manager_;
+
+ RenderWidgetHostImpl* host =
+ RenderWidgetHostImpl::From(GetRenderWidgetHost());
+ if (!host || !host->delegate())
+ return nullptr;
+
+ // This RWHV needs to be registered with the TextInputManager so that the
+ // TextInputManager starts tracking its state, and observing its lifetime.
+ text_input_manager_ = host->delegate()->GetTextInputManager();
+ if (text_input_manager_)
+ text_input_manager_->Register(this);
+
+ return text_input_manager_;
+}
+
void RenderWidgetHostViewBase::AddObserver(
RenderWidgetHostViewBaseObserver* observer) {
observers_.AddObserver(observer);
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 8eb96897ecc..f6a25c17c6e 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
@@ -29,6 +29,7 @@
#include "third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationType.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/display/display.h"
@@ -66,6 +67,7 @@ class BrowserAccessibilityManager;
class RenderWidgetHostViewBaseObserver;
class SyntheticGesture;
class SyntheticGestureTarget;
+class TextInputManager;
class WebCursor;
struct DidOverscrollParams;
struct NativeWebKeyboardEvent;
@@ -97,6 +99,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
void BeginFrameSubscription(
std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override;
void EndFrameSubscription() override;
+ void FocusedNodeTouched(const gfx::Point& location_dips_screen,
+ bool editable) override;
// This only needs to be overridden by RenderWidgetHostViewBase subclasses
// that handle content embedded within other RenderWidgetHostViews.
@@ -126,6 +130,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// changed since the last time.
bool HasDisplayPropertyChanged(gfx::NativeView view);
+ // Called by the TextInputManager to notify the view about being removed from
+ // the list of registered views, i.e., TextInputManager is no longer tracking
+ // TextInputState from this view. The RWHV should reset |text_input_manager_|
+ // to nullptr.
+ void DidUnregisterFromTextInputManager(TextInputManager* text_input_manager);
+
base::WeakPtr<RenderWidgetHostViewBase> GetWeakPtr();
//----------------------------------------------------------------------------
@@ -187,9 +197,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// Informs that the focused DOM node has changed.
virtual void FocusedNodeChanged(bool is_editable_node) {}
- virtual void OnSwapCompositorFrame(
- uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {}
+ virtual void OnSwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) {}
// This method exists to allow removing of displayed graphics, after a new
// page has been loaded, to prevent the displayed URL from being out of sync
@@ -222,8 +231,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
const gfx::Point& point,
gfx::Point* transformed_point);
virtual void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) {}
- virtual void ProcessMouseEvent(const blink::WebMouseEvent& event) {}
- virtual void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) {}
+ virtual void ProcessMouseEvent(const blink::WebMouseEvent& event,
+ const ui::LatencyInfo& latency) {}
+ virtual void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event,
+ const ui::LatencyInfo& latency) {}
virtual void ProcessTouchEvent(const blink::WebTouchEvent& event,
const ui::LatencyInfo& latency) {}
virtual void ProcessGestureEvent(const blink::WebGestureEvent& event,
@@ -240,6 +251,18 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
cc::SurfaceId original_surface,
gfx::Point* transformed_point);
+ // Updates the state of the input method attached to the view.
+ // TODO(ekaramad): This method will not stay virtual. It will be moved up top
+ // with the other non-virtual methods after TextInputState tracking is fixed
+ // on all platforms (https://crbug.com/578168).
+ virtual void TextInputStateChanged(const TextInputState& text_input_state);
+
+ // Cancel the ongoing composition of the input method attached to the view.
+ // TODO(ekaramad): This method will not stay virtual. It will be moved up top
+ // with the other non-virtual methods after IME is fixed on all platforms.
+ // (https://crbug.com/578168).
+ virtual void ImeCancelComposition();
+
//----------------------------------------------------------------------------
// The following static methods are implemented by each platform.
@@ -265,12 +288,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// Indicates whether the page has finished loading.
virtual void SetIsLoading(bool is_loading) = 0;
- // Updates the state of the input method attached to the view.
- virtual void TextInputStateChanged(const TextInputState& params) = 0;
-
- // Cancel the ongoing composition of the input method attached to the view.
- virtual void ImeCancelComposition() = 0;
-
// Notifies the View that the renderer has ceased to exist.
virtual void RenderProcessGone(base::TerminationStatus status,
int error_code) = 0;
@@ -340,7 +357,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
const display::Display& display);
virtual void GetScreenInfo(blink::WebScreenInfo* results) = 0;
- virtual bool GetScreenColorProfile(std::vector<char>* color_profile) = 0;
// Gets the bounds of the window, in screen coordinates.
virtual gfx::Rect GetBoundsInRootWindow() = 0;
@@ -385,6 +401,18 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
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_|
+ // and this view is registered with it. The RWHV will unregister from the
+ // TextInputManager if it is destroyed or if the TextInputManager itself is
+ // destroyed. The unregistration of the RWHV from TextInputManager is
+ // necessary and must be done by explicitly calling
+ // TextInputManager::Unregister.
+ // It is safer to use this method rather than directly dereferencing
+ // |text_input_manager_|.
+ TextInputManager* GetTextInputManager();
+
// Whether this view is a popup and what kind of popup it is (select,
// autofill...).
blink::WebPopupType popup_type_;
@@ -412,7 +440,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// The current selection range relative to the start of the web page.
gfx::Range selection_range_;
- protected:
// The scale factor of the display the renderer is currently on.
float current_device_scale_factor_;
@@ -423,6 +450,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// 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
+ // destroyed before the RWHV is destroyed.
+ TextInputManager* text_input_manager_;
+
private:
void FlushInput();
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 073afd5ba0b..625346a11cc 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
@@ -22,10 +22,8 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
-#include "cc/scheduler/begin_frame_source.h"
#include "cc/surfaces/surface_id.h"
#include "content/browser/renderer_host/browser_compositor_view_mac.h"
-#include "content/browser/renderer_host/delegated_frame_host.h"
#include "content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
@@ -226,11 +224,10 @@ namespace content {
// RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
class CONTENT_EXPORT RenderWidgetHostViewMac
: public RenderWidgetHostViewBase,
- public DelegatedFrameHostClient,
+ public BrowserCompositorMacClient,
public ui::AcceleratedWidgetMacNSView,
public IPC::Sender,
- public display::DisplayObserver,
- public cc::BeginFrameObserver {
+ public display::DisplayObserver {
public:
// The view will associate itself with the given widget. The native view must
// be hooked up immediately to the view hierarchy, or else when it is
@@ -312,9 +309,8 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override;
void EndFrameSubscription() override;
ui::AcceleratedWidgetMac* GetAcceleratedWidgetMac() const override;
- void OnSwapCompositorFrame(
- uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) override;
+ void OnSwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) override;
void ClearCompositorFrame() override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
@@ -322,15 +318,12 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
bool HasAcceleratedSurface(const gfx::Size& desired_size) override;
void GetScreenInfo(blink::WebScreenInfo* results) override;
- bool GetScreenColorProfile(std::vector<char>* color_profile) override;
gfx::Rect GetBoundsInRootWindow() override;
void LockCompositingSurface() override;
void UnlockCompositingSurface() override;
bool LockMouse() override;
void UnlockMouse() override;
- void WheelEventAck(const blink::WebMouseWheelEvent& event,
- InputEventAckState ack_result) override;
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
@@ -343,8 +336,10 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
gfx::Point* transformed_point) override;
// Returns true when we can do SurfaceHitTesting for the event type.
bool ShouldRouteEvent(const blink::WebInputEvent& event) const;
- void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
- void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
+ void ProcessMouseEvent(const blink::WebMouseEvent& event,
+ const ui::LatencyInfo& latency) override;
+ void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event,
+ const ui::LatencyInfo& latency) override;
void ProcessTouchEvent(const blink::WebTouchEvent& event,
const ui::LatencyInfo& latency) override;
void ProcessGestureEvent(const blink::WebGestureEvent& event,
@@ -417,51 +412,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// The background CoreAnimation layer which is hosted by |cocoa_view_|.
base::scoped_nsobject<CALayer> background_layer_;
- // The state of |delegated_frame_host_| and |browser_compositor_| to
- // manage being visible, hidden, or occluded.
- enum BrowserCompositorViewState {
- // Effects:
- // - |browser_compositor_| exists and |delegated_frame_host_| is
- // visible.
- // Happens when:
- // - |render_widet_host_| is in the visible state (this includes when
- // the tab isn't visible, but tab capture is enabled).
- BrowserCompositorActive,
- // Effects:
- // - |browser_compositor_| exists, but |delegated_frame_host_| has
- // been hidden.
- // Happens when:
- // - The |render_widget_host_| is hidden, but |cocoa_view_| is still in the
- // NSWindow hierarchy.
- // - This happens when |cocoa_view_| is hidden (minimized, on another
- // occluded by other windows, etc). The |browser_compositor_| and
- // its CALayers are kept around so that we will have content to show when
- // we are un-occluded.
- BrowserCompositorSuspended,
- // Effects:
- // - |browser_compositor_| has been destroyed and
- // |delegated_frame_host_| has been hidden.
- // Happens when:
- // - The |render_widget_host_| is hidden or dead, and |cocoa_view_| is not
- // attached to a NSWindow.
- // - This happens for backgrounded tabs.
- BrowserCompositorDestroyed,
- };
- BrowserCompositorViewState browser_compositor_state_;
-
- // Delegated frame management and compositor.
- std::unique_ptr<DelegatedFrameHost> delegated_frame_host_;
- std::unique_ptr<ui::Layer> root_layer_;
-
- // Container for ui::Compositor the CALayer tree drawn by it.
+ // Delegated frame management and compositor interface.
std::unique_ptr<BrowserCompositorMac> browser_compositor_;
- // Placeholder that is allocated while browser_compositor_ is NULL,
- // indicating that a BrowserCompositorViewMac may be allocated. This is to
- // help in recycling the internals of BrowserCompositorViewMac.
- std::unique_ptr<BrowserCompositorMacPlaceholder>
- browser_compositor_placeholder_;
-
// Set when the currently-displayed frame is the minimum scale. Used to
// determine if pinch gestures need to be thresholded.
bool page_at_minimum_scale_;
@@ -490,31 +443,21 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void PauseForPendingResizeOrRepaintsAndDraw();
- // DelegatedFrameHostClient implementation.
- ui::Layer* DelegatedFrameHostGetLayer() const override;
- bool DelegatedFrameHostIsVisible() const override;
- SkColor DelegatedFrameHostGetGutterColor(SkColor color) const override;
- gfx::Size DelegatedFrameHostDesiredSizeInDIP() const override;
- bool DelegatedFrameCanCreateResizeLock() const override;
- std::unique_ptr<ResizeLock> DelegatedFrameHostCreateResizeLock(
- bool defer_compositor_lock) override;
- void DelegatedFrameHostResizeLockWasReleased() override;
- void DelegatedFrameHostSendCompositorSwapAck(
+ // BrowserCompositorMacClient implementation.
+ NSView* BrowserCompositorMacGetNSView() const override;
+ SkColor BrowserCompositorMacGetGutterColor(SkColor color) const override;
+ void BrowserCompositorMacSendCompositorSwapAck(
int output_surface_id,
const cc::CompositorFrameAck& ack) override;
- void DelegatedFrameHostSendReclaimCompositorResources(
+ void BrowserCompositorMacSendReclaimCompositorResources(
int output_surface_id,
const cc::CompositorFrameAck& ack) override;
- void DelegatedFrameHostOnLostCompositorResources() override;
- void DelegatedFrameHostUpdateVSyncParameters(
+ void BrowserCompositorMacOnLostCompositorResources() override;
+ void BrowserCompositorMacUpdateVSyncParameters(
const base::TimeTicks& timebase,
const base::TimeDelta& interval) override;
- void SetBeginFrameSource(cc::BeginFrameSource* source) override;
-
- // cc::BeginFrameObserver implementation.
- void OnBeginFrame(const cc::BeginFrameArgs& args) override;
- const cc::BeginFrameArgs& LastUsedBeginFrameArgs() const override;
- void OnBeginFrameSourcePausedChanged(bool paused) override;
+ void BrowserCompositorMacSendBeginFrame(
+ const cc::BeginFrameArgs& args) override;
// AcceleratedWidgetMacNSView implementation.
NSView* AcceleratedWidgetGetNSView() const override;
@@ -522,10 +465,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
base::TimeTicks* timebase, base::TimeDelta* interval) const override;
void AcceleratedWidgetSwapCompleted() override;
- // Transition from being in the Suspended state to being in the Destroyed
- // state, if appropriate (see BrowserCompositorViewState for details).
- void DestroySuspendedBrowserCompositorViewIfNeeded();
-
// Exposed for testing.
cc::SurfaceId SurfaceIdForTesting() const override;
@@ -539,16 +478,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// invoke it from the message loop.
void ShutdownHost();
- // Tear down all components of the browser compositor in an order that will
- // ensure no dangling references.
- void ShutdownBrowserCompositor();
-
- // The state of the the browser compositor and delegated frame host. See
- // BrowserCompositorViewState for details.
- void EnsureBrowserCompositorView();
- void SuspendBrowserCompositorView();
- void DestroyBrowserCompositorView();
-
// IPC message handlers.
void OnGetRenderedTextCompleted(const std::string& text);
@@ -579,9 +508,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// RenderWidgetHostViewGuest.
bool is_guest_view_hack_;
- // True if gestures are generated for mouse wheel events.
- bool wheel_gestures_enabled_;
-
// selected text on the renderer.
std::string selected_text_;
@@ -602,11 +528,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
base::TimeTicks vsync_timebase_;
base::TimeDelta vsync_interval_;
- // The begin frame source being observed. Null if none.
- cc::BeginFrameSource* begin_frame_source_;
- cc::BeginFrameArgs last_begin_frame_args_;
- bool needs_begin_frames_;
-
// The current composition character range and its bounds.
gfx::Range composition_range_;
std::vector<gfx::Rect> composition_bounds_;
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 86481a97da9..284f4fdd8e0 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
@@ -48,11 +48,9 @@
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h"
-#include "content/browser/renderer_host/resize_lock.h"
#import "content/browser/renderer_host/text_input_client_mac.h"
#include "content/common/accessibility_messages.h"
#include "content/common/edit_command.h"
-#include "content/common/input/input_event_utils.h"
#include "content/common/input_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/text_input_state.h"
@@ -80,8 +78,8 @@
#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
+#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/color_profile.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -404,114 +402,53 @@ blink::WebScreenInfo GetWebScreenInfo(NSView* view) {
namespace content {
////////////////////////////////////////////////////////////////////////////////
-// DelegatedFrameHost, public:
+// BrowserCompositorMacClient, public:
-ui::Layer* RenderWidgetHostViewMac::DelegatedFrameHostGetLayer() const {
- return root_layer_.get();
-}
-
-bool RenderWidgetHostViewMac::DelegatedFrameHostIsVisible() const {
- return !render_widget_host_->is_hidden();
+NSView* RenderWidgetHostViewMac::BrowserCompositorMacGetNSView() const {
+ return cocoa_view_;
}
-SkColor RenderWidgetHostViewMac::DelegatedFrameHostGetGutterColor(
+SkColor RenderWidgetHostViewMac::BrowserCompositorMacGetGutterColor(
SkColor color) const {
// When making an element on the page fullscreen the element's background
// may not match the page's, so use black as the gutter color to avoid
// flashes of brighter colors during the transition.
if (render_widget_host_->delegate() &&
- render_widget_host_->delegate()->IsFullscreenForCurrentTab(
- render_widget_host_)) {
+ render_widget_host_->delegate()->IsFullscreenForCurrentTab()) {
return SK_ColorBLACK;
}
return color;
}
-gfx::Size RenderWidgetHostViewMac::DelegatedFrameHostDesiredSizeInDIP() const {
- return GetViewBounds().size();
-}
-
-bool RenderWidgetHostViewMac::DelegatedFrameCanCreateResizeLock() const {
- // Mac uses the RenderWidgetResizeHelper instead of a resize lock.
- return false;
-}
-
-std::unique_ptr<ResizeLock>
-RenderWidgetHostViewMac::DelegatedFrameHostCreateResizeLock(
- bool defer_compositor_lock) {
- NOTREACHED();
- return std::unique_ptr<ResizeLock>();
-}
-
-void RenderWidgetHostViewMac::DelegatedFrameHostResizeLockWasReleased() {
- NOTREACHED();
-}
-
-void RenderWidgetHostViewMac::DelegatedFrameHostSendCompositorSwapAck(
+void RenderWidgetHostViewMac::BrowserCompositorMacSendCompositorSwapAck(
int output_surface_id,
const cc::CompositorFrameAck& ack) {
render_widget_host_->Send(new ViewMsg_SwapCompositorFrameAck(
render_widget_host_->GetRoutingID(), output_surface_id, ack));
}
-void RenderWidgetHostViewMac::DelegatedFrameHostSendReclaimCompositorResources(
- int output_surface_id,
- const cc::CompositorFrameAck& ack) {
+void RenderWidgetHostViewMac::
+ BrowserCompositorMacSendReclaimCompositorResources(
+ int output_surface_id,
+ const cc::CompositorFrameAck& ack) {
render_widget_host_->Send(new ViewMsg_ReclaimCompositorResources(
render_widget_host_->GetRoutingID(), output_surface_id, ack));
}
-void RenderWidgetHostViewMac::DelegatedFrameHostOnLostCompositorResources() {
+void RenderWidgetHostViewMac::BrowserCompositorMacOnLostCompositorResources() {
render_widget_host_->ScheduleComposite();
}
-void RenderWidgetHostViewMac::DelegatedFrameHostUpdateVSyncParameters(
+void RenderWidgetHostViewMac::BrowserCompositorMacUpdateVSyncParameters(
const base::TimeTicks& timebase,
const base::TimeDelta& interval) {
render_widget_host_->UpdateVSyncParameters(timebase, interval);
}
-void RenderWidgetHostViewMac::SetBeginFrameSource(
- cc::BeginFrameSource* source) {
- if (begin_frame_source_ && needs_begin_frames_)
- begin_frame_source_->RemoveObserver(this);
- begin_frame_source_ = source;
- if (begin_frame_source_ && needs_begin_frames_)
- begin_frame_source_->AddObserver(this);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// cc::BeginFrameSourceBase, public:
-
-void RenderWidgetHostViewMac::OnSetNeedsBeginFrames(bool needs_begin_frames) {
- if (needs_begin_frames_ == needs_begin_frames)
- return;
-
- needs_begin_frames_ = needs_begin_frames;
- if (begin_frame_source_) {
- if (needs_begin_frames_)
- begin_frame_source_->AddObserver(this);
- else
- begin_frame_source_->RemoveObserver(this);
- }
-}
-
-void RenderWidgetHostViewMac::OnBeginFrame(
+void RenderWidgetHostViewMac::BrowserCompositorMacSendBeginFrame(
const cc::BeginFrameArgs& args) {
- delegated_frame_host_->SetVSyncParameters(args.frame_time, args.interval);
render_widget_host_->Send(
new ViewMsg_BeginFrame(render_widget_host_->GetRoutingID(), args));
- last_begin_frame_args_ = args;
-}
-
-const cc::BeginFrameArgs& RenderWidgetHostViewMac::LastUsedBeginFrameArgs()
- const {
- return last_begin_frame_args_;
-}
-
-void RenderWidgetHostViewMac::OnBeginFrameSourcePausedChanged(
- bool paused) {
- // Only used on Android WebView.
}
////////////////////////////////////////////////////////////////////////////////
@@ -552,16 +489,11 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
: render_widget_host_(RenderWidgetHostImpl::From(widget)),
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
can_compose_inline_(true),
- browser_compositor_state_(BrowserCompositorDestroyed),
- browser_compositor_placeholder_(new BrowserCompositorMacPlaceholder),
page_at_minimum_scale_(true),
is_loading_(false),
allow_pause_for_resize_or_repaint_(true),
is_guest_view_hack_(is_guest_view_hack),
- wheel_gestures_enabled_(UseGestureBasedWheelScrolling()),
fullscreen_parent_host_view_(nullptr),
- begin_frame_source_(nullptr),
- needs_begin_frames_(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
@@ -578,8 +510,8 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
[cocoa_view_ setLayer:background_layer_];
[cocoa_view_ setWantsLayer:YES];
- root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
- delegated_frame_host_.reset(new DelegatedFrameHost(this));
+ browser_compositor_.reset(new BrowserCompositorMac(
+ this, this, render_widget_host_->is_hidden(), [cocoa_view_ window]));
display::Screen::GetScreen()->AddObserver(this);
@@ -605,8 +537,7 @@ RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
UnlockMouse();
- // Ensure that the browser compositor is destroyed in a safe order.
- ShutdownBrowserCompositor();
+ browser_compositor_.reset();
// We are owned by RenderWidgetHostViewCocoa, so if we go away before the
// RenderWidgetHost does we need to tell it not to hold a stale pointer to
@@ -630,92 +561,12 @@ void RenderWidgetHostViewMac::SetAllowPauseForResizeOrRepaint(bool allow) {
}
cc::SurfaceId RenderWidgetHostViewMac::SurfaceIdForTesting() const {
- return delegated_frame_host_->SurfaceIdForTesting();
+ return browser_compositor_->GetDelegatedFrameHost()->SurfaceIdForTesting();
}
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewMac, RenderWidgetHostView implementation:
-void RenderWidgetHostViewMac::EnsureBrowserCompositorView() {
- TRACE_EVENT0("browser",
- "RenderWidgetHostViewMac::EnsureBrowserCompositorView");
-
- // Create the view, to transition from Destroyed -> Suspended.
- if (browser_compositor_state_ == BrowserCompositorDestroyed) {
- browser_compositor_ = BrowserCompositorMac::Create();
- browser_compositor_->compositor()->SetRootLayer(root_layer_.get());
- browser_compositor_->compositor()->SetHostHasTransparentBackground(
- !GetBackgroundOpaque());
- browser_compositor_->accelerated_widget_mac()->SetNSView(this);
- browser_compositor_state_ = BrowserCompositorSuspended;
- }
-
- // Show the DelegatedFrameHost to transition from Suspended -> Active.
- if (browser_compositor_state_ == BrowserCompositorSuspended) {
- delegated_frame_host_->SetCompositor(browser_compositor_->compositor());
- delegated_frame_host_->WasShown(ui::LatencyInfo());
- // Unsuspend the browser compositor after showing the delegated frame host.
- // If there is not a saved delegated frame, then the delegated frame host
- // will keep the compositor locked until a delegated frame is swapped.
- float scale_factor = ViewScaleFactor();
- browser_compositor_->compositor()->SetScaleAndSize(
- scale_factor,
- gfx::ConvertSizeToPixel(scale_factor, GetViewBounds().size()));
- browser_compositor_->Unsuspend();
- browser_compositor_state_ = BrowserCompositorActive;
- }
-}
-
-void RenderWidgetHostViewMac::SuspendBrowserCompositorView() {
- TRACE_EVENT0("browser",
- "RenderWidgetHostViewMac::SuspendBrowserCompositorView");
-
- // Hide the DelegatedFrameHost to transition from Active -> Suspended.
- if (browser_compositor_state_ == BrowserCompositorActive) {
- // Ensure that any changes made to the ui::Compositor do not result in new
- // frames being produced.
- browser_compositor_->Suspend();
- // Marking the DelegatedFrameHost as removed from the window hierarchy is
- // necessary to remove all connections to its old ui::Compositor.
- delegated_frame_host_->WasHidden();
- delegated_frame_host_->ResetCompositor();
- browser_compositor_state_ = BrowserCompositorSuspended;
- }
-}
-
-void RenderWidgetHostViewMac::DestroyBrowserCompositorView() {
- TRACE_EVENT0("browser",
- "RenderWidgetHostViewMac::DestroyBrowserCompositorView");
-
- // Transition from Active -> Suspended if need be.
- SuspendBrowserCompositorView();
-
- // Destroy the BrowserCompositorView to transition Suspended -> Destroyed.
- if (browser_compositor_state_ == BrowserCompositorSuspended) {
- browser_compositor_->accelerated_widget_mac()->ResetNSView();
- browser_compositor_->compositor()->SetScaleAndSize(1.0, gfx::Size(0, 0));
- browser_compositor_->compositor()->SetRootLayer(nullptr);
- BrowserCompositorMac::Recycle(std::move(browser_compositor_));
- browser_compositor_state_ = BrowserCompositorDestroyed;
- }
-}
-
-void RenderWidgetHostViewMac::DestroySuspendedBrowserCompositorViewIfNeeded() {
- if (browser_compositor_state_ != BrowserCompositorSuspended)
- return;
-
- // If this view is in a window that is visible, keep around the suspended
- // BrowserCompositorView in case |cocoa_view_| is suddenly revealed (so that
- // we don't flash white).
- NSWindow* window = [cocoa_view_ window];
- if (window)
- return;
-
- // This should only be reached if |render_widget_host_| is hidden, destroyed,
- // or in the process of being destroyed.
- DestroyBrowserCompositorView();
-}
-
bool RenderWidgetHostViewMac::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewMac, message)
@@ -861,10 +712,7 @@ void RenderWidgetHostViewMac::SendVSyncParametersToRenderer() {
return;
}
- if (browser_compositor_) {
- browser_compositor_->compositor()->vsync_manager()->UpdateVSyncParameters(
- vsync_timebase_, vsync_interval_);
- }
+ browser_compositor_->UpdateVSyncParameters(vsync_timebase_, vsync_interval_);
}
void RenderWidgetHostViewMac::SpeakText(const std::string& text) {
@@ -884,16 +732,13 @@ RenderWidgetHost* RenderWidgetHostViewMac::GetRenderWidgetHost() const {
void RenderWidgetHostViewMac::Show() {
ScopedCAActionDisabler disabler;
[cocoa_view_ setHidden:NO];
- if (!render_widget_host_->is_hidden())
- return;
- // Re-create the browser compositor. If the DelegatedFrameHost has a cached
- // frame from the last time it was visible, then it will immediately be
- // drawn. If not, then the compositor will remain locked until a new delegated
- // frame is swapped.
- EnsureBrowserCompositorView();
+ browser_compositor_->SetRenderWidgetHostIsHidden(false);
- WasUnOccluded();
+ ui::LatencyInfo renderer_latency_info;
+ renderer_latency_info.AddLatencyNumber(
+ ui::TAB_SHOW_COMPONENT, render_widget_host_->GetLatencyComponentId(), 0);
+ render_widget_host_->WasShown(renderer_latency_info);
// If there is not a frame being currently drawn, kick one, so that the below
// pause will have a frame to wait on.
@@ -904,35 +749,28 @@ void RenderWidgetHostViewMac::Show() {
void RenderWidgetHostViewMac::Hide() {
ScopedCAActionDisabler disabler;
[cocoa_view_ setHidden:YES];
- WasOccluded();
- DestroySuspendedBrowserCompositorViewIfNeeded();
+
+ render_widget_host_->WasHidden();
+ browser_compositor_->SetRenderWidgetHostIsHidden(true);
}
void RenderWidgetHostViewMac::WasUnOccluded() {
- if (!render_widget_host_->is_hidden())
- return;
-
- ui::LatencyInfo renderer_latency_info;
- renderer_latency_info.AddLatencyNumber(
- ui::TAB_SHOW_COMPONENT,
- render_widget_host_->GetLatencyComponentId(),
- 0);
- render_widget_host_->WasShown(renderer_latency_info);
+ browser_compositor_->SetRenderWidgetHostIsHidden(false);
+ render_widget_host_->WasShown(ui::LatencyInfo());
}
void RenderWidgetHostViewMac::WasOccluded() {
- if (render_widget_host_->is_hidden())
+ // Ignore occlusion when in fullscreen low power mode, because the occlusion
+ // is likely coming from the fullscreen low power window.
+ ui::AcceleratedWidgetMac* accelerated_widget_mac =
+ browser_compositor_->GetAcceleratedWidgetMac();
+ if (accelerated_widget_mac &&
+ accelerated_widget_mac->MightBeInFullscreenLowPowerMode()) {
return;
+ }
- // Note that the following call to WasHidden() can trigger thumbnail
- // generation on behalf of the NTP, and that cannot succeed if the browser
- // compositor view has been suspended. Therefore these two statements must
- // occur in this specific order. However, because thumbnail generation is
- // asychronous, that operation won't run before SuspendBrowserCompositorView()
- // completes. As a result you won't get a thumbnail for the page unless you
- // execute these two statements in this specific order.
render_widget_host_->WasHidden();
- SuspendBrowserCompositorView();
+ browser_compositor_->SetRenderWidgetHostIsHidden(true);
}
void RenderWidgetHostViewMac::SetSize(const gfx::Size& size) {
@@ -1010,8 +848,7 @@ bool RenderWidgetHostViewMac::HasFocus() const {
}
bool RenderWidgetHostViewMac::IsSurfaceAvailableForCopy() const {
- DCHECK(delegated_frame_host_);
- return delegated_frame_host_->CanCopyToBitmap();
+ return browser_compositor_->GetDelegatedFrameHost()->CanCopyToBitmap();
}
bool RenderWidgetHostViewMac::IsShowing() {
@@ -1110,7 +947,7 @@ void RenderWidgetHostViewMac::Destroy() {
// Delete the delegated frame state, which will reach back into
// render_widget_host_.
- ShutdownBrowserCompositor();
+ browser_compositor_.reset();
// Make sure none of our observers send events for us to process after
// we release render_widget_host_.
@@ -1251,8 +1088,7 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurface(
const gfx::Size& dst_size,
const ReadbackRequestCallback& callback,
const SkColorType preferred_color_type) {
- DCHECK(delegated_frame_host_);
- delegated_frame_host_->CopyFromCompositingSurface(
+ browser_compositor_->CopyFromCompositingSurface(
src_subrect, dst_size, callback, preferred_color_type);
}
@@ -1260,32 +1096,27 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
const scoped_refptr<media::VideoFrame>& target,
const base::Callback<void(const gfx::Rect&, bool)>& callback) {
- DCHECK(delegated_frame_host_);
- delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
- src_subrect, target, callback);
+ browser_compositor_->CopyFromCompositingSurfaceToVideoFrame(src_subrect,
+ target, callback);
}
bool RenderWidgetHostViewMac::CanCopyToVideoFrame() const {
- DCHECK(delegated_frame_host_);
- return delegated_frame_host_->CanCopyToVideoFrame();
+ return browser_compositor_->GetDelegatedFrameHost()->CanCopyToVideoFrame();
}
void RenderWidgetHostViewMac::BeginFrameSubscription(
std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
- DCHECK(delegated_frame_host_);
- delegated_frame_host_->BeginFrameSubscription(std::move(subscriber));
+ browser_compositor_->GetDelegatedFrameHost()->BeginFrameSubscription(
+ std::move(subscriber));
}
void RenderWidgetHostViewMac::EndFrameSubscription() {
- DCHECK(delegated_frame_host_);
- delegated_frame_host_->EndFrameSubscription();
+ browser_compositor_->GetDelegatedFrameHost()->EndFrameSubscription();
}
ui::AcceleratedWidgetMac* RenderWidgetHostViewMac::GetAcceleratedWidgetMac()
const {
- if (browser_compositor_)
- return browser_compositor_->accelerated_widget_mac();
- return nullptr;
+ return browser_compositor_->GetAcceleratedWidgetMac();
}
void RenderWidgetHostViewMac::ForwardMouseEvent(const WebMouseEvent& event) {
@@ -1298,6 +1129,10 @@ void RenderWidgetHostViewMac::ForwardMouseEvent(const WebMouseEvent& event) {
}
}
+void RenderWidgetHostViewMac::OnSetNeedsBeginFrames(bool needs_begin_frames) {
+ browser_compositor_->SetNeedsBeginFrames(needs_begin_frames);
+}
+
void RenderWidgetHostViewMac::KillSelf() {
if (!weak_factory_.HasWeakPtrs()) {
[cocoa_view_ setHidden:YES];
@@ -1450,43 +1285,25 @@ bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
bool RenderWidgetHostViewMac::HasAcceleratedSurface(
const gfx::Size& desired_size) {
- if (browser_compositor_) {
- return browser_compositor_->accelerated_widget_mac()->HasFrameOfSize(
- desired_size);
- }
+ ui::AcceleratedWidgetMac* accelerated_widget_mac =
+ browser_compositor_->GetAcceleratedWidgetMac();
+ if (accelerated_widget_mac)
+ return accelerated_widget_mac->HasFrameOfSize(desired_size);
return false;
}
-void RenderWidgetHostViewMac::OnSwapCompositorFrame(
- uint32_t output_surface_id,
- std::unique_ptr<cc::CompositorFrame> frame) {
+void RenderWidgetHostViewMac::OnSwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) {
TRACE_EVENT0("browser", "RenderWidgetHostViewMac::OnSwapCompositorFrame");
- last_scroll_offset_ = frame->metadata.root_scroll_offset;
-
- page_at_minimum_scale_ = frame->metadata.page_scale_factor ==
- frame->metadata.min_page_scale_factor;
-
- if (frame->delegated_frame_data) {
- float scale_factor = frame->metadata.device_scale_factor;
-
- // Compute the frame size based on the root render pass rect size.
- cc::RenderPass* root_pass =
- frame->delegated_frame_data->render_pass_list.back().get();
- gfx::Size pixel_size = root_pass->output_rect.size();
- gfx::Size dip_size = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
-
- root_layer_->SetBounds(gfx::Rect(dip_size));
- if (!render_widget_host_->is_hidden()) {
- EnsureBrowserCompositorView();
- browser_compositor_->compositor()->SetScaleAndSize(
- scale_factor, pixel_size);
- }
+ last_scroll_offset_ = frame.metadata.root_scroll_offset;
+ page_at_minimum_scale_ =
+ frame.metadata.page_scale_factor == frame.metadata.min_page_scale_factor;
+ if (frame.delegated_frame_data) {
+ browser_compositor_->SwapCompositorFrame(output_surface_id,
+ std::move(frame));
SendVSyncParametersToRenderer();
-
- delegated_frame_host_->SwapDelegatedFrame(output_surface_id,
- std::move(frame));
} else {
DLOG(ERROR) << "Received unexpected frame type.";
bad_message::ReceivedBadMessage(render_widget_host_->GetProcess(),
@@ -1495,20 +1312,13 @@ void RenderWidgetHostViewMac::OnSwapCompositorFrame(
}
void RenderWidgetHostViewMac::ClearCompositorFrame() {
- delegated_frame_host_->ClearDelegatedFrame();
+ browser_compositor_->GetDelegatedFrameHost()->ClearDelegatedFrame();
}
void RenderWidgetHostViewMac::GetScreenInfo(blink::WebScreenInfo* results) {
*results = GetWebScreenInfo(GetNativeView());
}
-bool RenderWidgetHostViewMac::GetScreenColorProfile(
- std::vector<char>* color_profile) {
- DCHECK(color_profile->empty());
- NSWindow* window = GetWebContents()->GetTopLevelNativeWindow();
- return gfx::GetDisplayColorProfile(window, color_profile);
-}
-
gfx::Rect RenderWidgetHostViewMac::GetBoundsInRootWindow() {
// TODO(shess): In case of !window, the view has been removed from
// the view hierarchy because the tab isn't main. Could retrieve
@@ -1558,25 +1368,9 @@ void RenderWidgetHostViewMac::UnlockMouse() {
render_widget_host_->LostMouseLock();
}
-void RenderWidgetHostViewMac::WheelEventAck(
- const blink::WebMouseWheelEvent& event,
- InputEventAckState ack_result) {
- // TODO(dtapuska): Remove this handling of the wheel event ack
- // once wheel gestures is enabled for a full release; see crbug.com/598798.
- if (wheel_gestures_enabled_)
- return;
- bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
- // Only record a wheel event as unhandled if JavaScript handlers got a chance
- // to see it (no-op wheel events are ignored by the event dispatcher)
- if (event.deltaX || event.deltaY)
- [cocoa_view_ processedWheelEvent:event consumed:consumed];
-}
-
void RenderWidgetHostViewMac::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
- if (!wheel_gestures_enabled_)
- return;
bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
switch (event.type) {
case blink::WebInputEvent::GestureScrollBegin:
@@ -1598,8 +1392,7 @@ RenderWidgetHostViewMac::CreateSyntheticGestureTarget() {
}
uint32_t RenderWidgetHostViewMac::GetSurfaceIdNamespace() {
- DCHECK(delegated_frame_host_);
- return delegated_frame_host_->GetSurfaceIdNamespace();
+ return browser_compositor_->GetDelegatedFrameHost()->GetSurfaceIdNamespace();
}
uint32_t RenderWidgetHostViewMac::SurfaceIdNamespaceAtPoint(
@@ -1612,15 +1405,16 @@ uint32_t RenderWidgetHostViewMac::SurfaceIdNamespaceAtPoint(
->GetDisplayNearestWindow(cocoa_view_)
.device_scale_factor();
gfx::Point point_in_pixels = gfx::ConvertPointToPixel(scale_factor, point);
- cc::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(
- delegate, point_in_pixels, transformed_point);
+ cc::SurfaceId id =
+ browser_compositor_->GetDelegatedFrameHost()->SurfaceIdAtPoint(
+ delegate, point_in_pixels, transformed_point);
*transformed_point = gfx::ConvertPointToDIP(scale_factor, *transformed_point);
// It is possible that the renderer has not yet produced a surface, in which
// case we return our current namespace.
if (id.is_null())
return GetSurfaceIdNamespace();
- return cc::SurfaceIdAllocator::NamespaceForId(id);
+ return id.id_namespace();
}
bool RenderWidgetHostViewMac::ShouldRouteEvent(
@@ -1636,14 +1430,14 @@ bool RenderWidgetHostViewMac::ShouldRouteEvent(
}
void RenderWidgetHostViewMac::ProcessMouseEvent(
- const blink::WebMouseEvent& event) {
- render_widget_host_->ForwardMouseEvent(event);
+ const blink::WebMouseEvent& event,
+ const ui::LatencyInfo& latency) {
+ render_widget_host_->ForwardMouseEventWithLatencyInfo(event, latency);
}
void RenderWidgetHostViewMac::ProcessMouseWheelEvent(
- const blink::WebMouseWheelEvent& event) {
- ui::LatencyInfo latency_info;
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
- render_widget_host_->ForwardWheelEventWithLatencyInfo(event, latency_info);
+ const blink::WebMouseWheelEvent& event,
+ const ui::LatencyInfo& latency) {
+ render_widget_host_->ForwardWheelEventWithLatencyInfo(event, latency);
}
void RenderWidgetHostViewMac::ProcessTouchEvent(
@@ -1668,7 +1462,7 @@ void RenderWidgetHostViewMac::TransformPointToLocalCoordSpace(
->GetDisplayNearestWindow(cocoa_view_)
.device_scale_factor();
gfx::Point point_in_pixels = gfx::ConvertPointToPixel(scale_factor, point);
- delegated_frame_host_->TransformPointToLocalCoordSpace(
+ browser_compositor_->GetDelegatedFrameHost()->TransformPointToLocalCoordSpace(
point_in_pixels, original_surface, transformed_point);
*transformed_point = gfx::ConvertPointToDIP(scale_factor, *transformed_point);
}
@@ -1686,13 +1480,6 @@ void RenderWidgetHostViewMac::ShutdownHost() {
// Do not touch any members at this point, |this| has been deleted.
}
-void RenderWidgetHostViewMac::ShutdownBrowserCompositor() {
- DestroyBrowserCompositorView();
- delegated_frame_host_.reset();
- root_layer_.reset();
- browser_compositor_placeholder_.reset();
-}
-
void RenderWidgetHostViewMac::SetActive(bool active) {
if (render_widget_host_) {
render_widget_host_->SetActive(active);
@@ -1725,8 +1512,8 @@ void RenderWidgetHostViewMac::SetBackgroundColor(SkColor color) {
render_widget_host_->SetBackgroundOpaque(opaque);
[cocoa_view_ setOpaque:opaque];
- if (browser_compositor_state_ != BrowserCompositorDestroyed)
- browser_compositor_->compositor()->SetHostHasTransparentBackground(!opaque);
+
+ browser_compositor_->SetHasTransparentBackground(!opaque);
ScopedCAActionDisabler disabler;
base::ScopedCFTypeRef<CGColorRef> cg_color(
@@ -1994,7 +1781,10 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
->GetInputEventRouter()
->RouteMouseEvent(renderWidgetHostView_.get(), &enterEvent);
} else {
- renderWidgetHostView_->ProcessMouseEvent(enterEvent);
+ ui::LatencyInfo latency_info;
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
+ 0, 0);
+ renderWidgetHostView_->ProcessMouseEvent(enterEvent, latency_info);
}
}
}
@@ -2029,7 +1819,9 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
->GetInputEventRouter()
->RouteMouseEvent(renderWidgetHostView_.get(), &event);
} else {
- renderWidgetHostView_->ProcessMouseEvent(event);
+ ui::LatencyInfo latency_info;
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ renderWidgetHostView_->ProcessMouseEvent(event, latency_info);
}
}
@@ -2516,6 +2308,9 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
return;
}
+ // Compute Event.Latency.OS.MOUSE_WHEEL histogram.
+ ui::ComputeEventLatencyOS(event);
+
// Use an NSEvent monitor to listen for the wheel-end end. This ensures that
// the event is received even when the mouse cursor is no longer over the view
// when the scrolling ends (e.g. if the tab was switched). This is necessary
@@ -2541,7 +2336,9 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
->GetInputEventRouter()
->RouteMouseWheelEvent(renderWidgetHostView_.get(), &webEvent);
} else {
- renderWidgetHostView_->ProcessMouseWheelEvent(webEvent);
+ ui::LatencyInfo latency_info;
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ renderWidgetHostView_->ProcessMouseWheelEvent(webEvent, latency_info);
}
}
}
@@ -2671,8 +2468,8 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
else
renderWidgetHostView_->render_widget_host_->SendScreenRects();
renderWidgetHostView_->render_widget_host_->WasResized();
- if (renderWidgetHostView_->delegated_frame_host_)
- renderWidgetHostView_->delegated_frame_host_->WasResized();
+ renderWidgetHostView_->browser_compositor_->GetDelegatedFrameHost()
+ ->WasResized();
// Wait for the frame that WasResize might have requested. If the view is
// being made visible at a new size, then this call will have no effect
@@ -2721,7 +2518,7 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
if (!renderWidgetHostView_->render_widget_host_)
return NO;
- renderWidgetHostView_->render_widget_host_->Focus();
+ renderWidgetHostView_->render_widget_host_->GotFocus();
renderWidgetHostView_->SetTextInputActive(true);
// Cancel any onging composition text which was left before we lost focus.
@@ -3242,11 +3039,9 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
- (void)viewDidMoveToWindow {
if ([self window]) {
[self updateScreenProperties];
- } else {
- // If the RenderWidgetHostViewCocoa is being removed from its window, tear
- // down its browser compositor resources, if needed.
- renderWidgetHostView_->DestroySuspendedBrowserCompositorViewIfNeeded();
}
+ renderWidgetHostView_->browser_compositor_->SetNSViewAttachedToWindow(
+ [self window]);
// If we switch windows (or are removed from the view hierarchy), cancel any
// open mouse-downs.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index 5a8cfef1fcd..42275cb527b 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -20,6 +20,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/base/layout.h"
using content::RenderWidgetHostViewMac;
@@ -133,6 +134,10 @@ TEST_F(RenderWidgetHostViewMacEditCommandHelperTest,
base::mac::ScopedNSAutoreleasePool pool;
+ base::MessageLoop message_loop;
+ ui::WindowResizeHelperMac::Get()->Init(
+ base::MessageLoop::current()->task_runner());
+
// Owned by its |cocoa_view()|, i.e. |rwhv_cocoa|.
RenderWidgetHostViewMac* rwhv_mac = new RenderWidgetHostViewMac(
render_widget, false);
@@ -157,11 +162,10 @@ TEST_F(RenderWidgetHostViewMacEditCommandHelperTest,
rwhv_cocoa.reset();
pool.Recycle();
- {
- // The |render_widget|'s process needs to be deleted within |message_loop|.
- base::MessageLoop message_loop;
- delete render_widget;
- }
+ // The |render_widget|'s process needs to be deleted within |message_loop|.
+ delete render_widget;
+
+ ui::WindowResizeHelperMac::Get()->ShutdownForTests();
}
// Test RenderWidgetHostViewMacEditCommandHelper::AddEditingSelectorsToClass
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 26b90a9a4d4..c8cea6ec530 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
@@ -7,12 +7,16 @@
#include <Cocoa/Cocoa.h>
#include <stddef.h>
#include <stdint.h>
+#include <tuple>
#include "base/command_line.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/mac/sdk_forward_declarations.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/histogram_tester.h"
+#include "base/test/simple_test_tick_clock.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
@@ -33,6 +37,7 @@
#include "testing/gtest_mac.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/ocmock_extensions.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/latency_info.h"
#include "ui/events/test/cocoa_test_event_utils.h"
#import "ui/gfx/test/ui_cocoa_test_helper.h"
@@ -110,7 +115,7 @@ std::string GetInputMessageTypes(MockRenderProcessHost* process) {
EXPECT_EQ(InputMsg_HandleInputEvent::ID, message->type());
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
- const blink::WebInputEvent* event = base::get<0>(params);
+ const blink::WebInputEvent* event = std::get<0>(params);
if (i != 0)
result += " ";
result += WebInputEventTraits::GetName(event->type);
@@ -222,6 +227,8 @@ gfx::Rect GetExpectedRect(const gfx::Point& origin,
NSEvent* MockScrollWheelEventWithPhase(SEL mockPhaseSelector, int32_t delta) {
CGEventRef cg_event =
CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitLine, 1, delta, 0);
+ CGEventTimestamp timestamp = 0;
+ CGEventSetTimestamp(cg_event, timestamp);
NSEvent* event = [NSEvent eventWithCGEvent:cg_event];
CFRelease(cg_event);
method_setImplementation(
@@ -234,14 +241,15 @@ NSEvent* MockScrollWheelEventWithPhase(SEL mockPhaseSelector, int32_t delta) {
class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
public:
- RenderWidgetHostViewMacTest() : old_rwhv_(NULL), rwhv_mac_(NULL) {}
+ RenderWidgetHostViewMacTest() : old_rwhv_(NULL), rwhv_mac_(NULL) {
+ std::unique_ptr<base::SimpleTestTickClock> mock_clock(
+ new base::SimpleTestTickClock());
+ mock_clock->Advance(base::TimeDelta::FromMilliseconds(100));
+ ui::SetEventTickClockForTesting(std::move(mock_clock));
+ }
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
- ImageTransportFactory::InitializeForUnitTests(
- std::unique_ptr<ImageTransportFactory>(
- new NoTransportImageTransportFactory));
-
// TestRenderViewHost's destruction assumes that its view is a
// TestRenderWidgetHostView, so store its view and reset it back to the
// stored view in |TearDown()|.
@@ -260,26 +268,12 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
test_rvh()->GetWidget()->SetView(
static_cast<RenderWidgetHostViewBase*>(old_rwhv_));
- ImageTransportFactory::Terminate();
RenderViewHostImplTestHarness::TearDown();
}
- void SetupForWheelGestures(bool enable_wheel_gestures) {
- CHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableWheelGestures));
- CHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableWheelGestures));
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- enable_wheel_gestures ? switches::kEnableWheelGestures
- : switches::kDisableWheelGestures);
- // Owned by its |cocoa_view()|, i.e. |rwhv_cocoa_|.
- rwhv_mac_ = new RenderWidgetHostViewMac(rvh()->GetWidget(), false);
- rwhv_cocoa_.reset([rwhv_mac_->cocoa_view() retain]);
- }
-
void RecycleAndWait() {
pool_.Recycle();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
pool_.Recycle();
}
@@ -924,73 +918,15 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
// render view receives it.
NSEvent* event2 = MockScrollWheelEventWithPhase(@selector(phaseEnded), 0);
[NSApp postEvent:event2 atStart:NO];
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(2U, process_host->sink().message_count());
// Clean up.
host->ShutdownAndDestroyWidget(true);
}
-TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
- SetupForWheelGestures(false);
-
- // 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();
-
- // Add a delegate to the view.
- base::scoped_nsobject<MockRenderWidgetHostViewMacDelegate> view_delegate(
- [[MockRenderWidgetHostViewMacDelegate alloc] init]);
- view->SetDelegate(view_delegate.get());
-
- // Send an initial wheel event for scrolling by 3 lines.
- NSEvent* event1 = MockScrollWheelEventWithPhase(@selector(phaseBegan), 3);
- [view->cocoa_view() scrollWheel:event1];
- ASSERT_EQ(1U, process_host->sink().message_count());
- process_host->sink().ClearMessages();
-
- // Indicate that the wheel event was unhandled.
- InputEventAck unhandled_ack(blink::WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- std::unique_ptr<IPC::Message> response1(
- new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack));
- host->OnMessageReceived(*response1);
-
- // Check that the view delegate got an unhandled wheel event.
- ASSERT_EQ(YES, view_delegate.get().unhandledWheelEventReceived);
- view_delegate.get().unhandledWheelEventReceived = NO;
-
- // Send another wheel event, this time for scrolling by 0 lines (empty event).
- NSEvent* event2 = MockScrollWheelEventWithPhase(@selector(phaseChanged), 0);
- [view->cocoa_view() scrollWheel:event2];
- ASSERT_EQ(1U, process_host->sink().message_count());
-
- // Indicate that the wheel event was also unhandled.
- std::unique_ptr<IPC::Message> response2(
- new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack));
- host->OnMessageReceived(*response2);
-
- // Check that the view delegate ignored the empty unhandled wheel event.
- ASSERT_EQ(NO, view_delegate.get().unhandledWheelEventReceived);
-
- // Clean up.
- host->ShutdownAndDestroyWidget(true);
-}
-
TEST_F(RenderWidgetHostViewMacTest,
IgnoreEmptyUnhandledWheelEventWithWheelGestures) {
- SetupForWheelGestures(true);
-
// Initialize the view associated with a MockRenderWidgetHostImpl, rather than
// the MockRenderProcessHost that is set up by the test harness which mocks
// out |OnMessageReceived()|.
@@ -1120,9 +1056,9 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
set_background = process_host->sink().GetUniqueMessageMatching(
ViewMsg_SetBackgroundOpaque::ID);
ASSERT_TRUE(set_background);
- base::Tuple<bool> sent_background;
+ std::tuple<bool> sent_background;
ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
- EXPECT_FALSE(base::get<0>(sent_background));
+ EXPECT_FALSE(std::get<0>(sent_background));
// Try setting it back.
process_host->sink().ClearMessages();
@@ -1133,7 +1069,7 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
ViewMsg_SetBackgroundOpaque::ID);
ASSERT_TRUE(set_background);
ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
- EXPECT_TRUE(base::get<0>(sent_background));
+ EXPECT_TRUE(std::get<0>(sent_background));
host->ShutdownAndDestroyWidget(true);
}
@@ -1158,11 +1094,11 @@ class RenderWidgetHostViewMacPinchTest : public RenderWidgetHostViewMacTest {
break;
}
DCHECK(message);
- base::Tuple<IPC::WebInputEventPointer, ui::LatencyInfo,
- InputEventDispatchType>
+ std::tuple<IPC::WebInputEventPointer, ui::LatencyInfo,
+ InputEventDispatchType>
data;
InputMsg_HandleInputEvent::Read(message, &data);
- IPC::WebInputEventPointer ipc_event = base::get<0>(data);
+ IPC::WebInputEventPointer ipc_event = std::get<0>(data);
const blink::WebGestureEvent* gesture_event =
static_cast<const blink::WebGestureEvent*>(ipc_event);
return gesture_event->data.pinchUpdate.zoomDisabled;
@@ -1289,5 +1225,31 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
host->ShutdownAndDestroyWidget(true);
}
+TEST_F(RenderWidgetHostViewMacTest, EventLatencyOSMouseWheelHistogram) {
+ base::HistogramTester histogram_tester;
+
+ // 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 an initial wheel event for scrolling by 3 lines.
+ // Verify that Event.Latency.OS.MOUSE_WHEEL histogram is computed properly.
+ NSEvent* wheelEvent = MockScrollWheelEventWithPhase(@selector(phaseBegan),3);
+ [view->cocoa_view() scrollWheel:wheelEvent];
+ histogram_tester.ExpectTotalCount("Event.Latency.OS.MOUSE_WHEEL", 1);
+
+ // Clean up.
+ host->ShutdownAndDestroyWidget(true);
+}
} // 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 846d4f73970..624c26a70e1 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
@@ -7,8 +7,11 @@
#include <utility>
#include "build/build_config.h"
+#include "components/mus/public/cpp/property_type_converters.h"
#include "components/mus/public/cpp/window.h"
-#include "components/mus/public/cpp/window_tree_connection.h"
+#include "components/mus/public/cpp/window_property.h"
+#include "components/mus/public/cpp/window_tree_client.h"
+#include "components/mus/public/interfaces/window_manager_constants.mojom.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/render_widget_window_tree_client_factory.mojom.h"
@@ -29,9 +32,10 @@ RenderWidgetHostViewMus::RenderWidgetHostViewMus(mus::Window* parent_window,
RenderWidgetHostImpl* host)
: host_(host), aura_window_(nullptr) {
DCHECK(parent_window);
- mus::Window* window = parent_window->connection()->NewWindow();
+ mus::Window* window = parent_window->window_tree()->NewWindow();
window->SetVisible(true);
window->SetBounds(gfx::Rect(300, 300));
+ window->set_input_event_handler(this);
parent_window->AddChild(window);
mus_window_.reset(new mus::ScopedWindowPtr(window));
host_->SetView(this);
@@ -44,7 +48,8 @@ RenderWidgetHostViewMus::RenderWidgetHostViewMus(mus::Window* parent_window,
mus::mojom::WindowTreeClientPtr window_tree_client;
factory->CreateWindowTreeClientForRenderWidget(
host_->GetRoutingID(), mojo::GetProxy(&window_tree_client));
- mus_window_->window()->Embed(std::move(window_tree_client));
+ mus_window_->window()->Embed(std::move(window_tree_client),
+ mus::mojom::kEmbedFlagEmbedderInterceptsEvents);
}
RenderWidgetHostViewMus::~RenderWidgetHostViewMus() {}
@@ -252,12 +257,6 @@ void RenderWidgetHostViewMus::GetScreenInfo(blink::WebScreenInfo* results) {
// TODO(fsamuel): Populate screen info from Mus.
}
-bool RenderWidgetHostViewMus::GetScreenColorProfile(
- std::vector<char>* color_profile) {
- // TODO(fsamuel): Implement color profile in Mus.
- return false;
-}
-
gfx::Rect RenderWidgetHostViewMus::GetBoundsInRootWindow() {
aura::Window* top_level = aura_window_->GetToplevelWindow();
gfx::Rect bounds(top_level->GetBoundsInScreen());
@@ -304,4 +303,12 @@ void RenderWidgetHostViewMus::UnlockCompositingSurface() {
NOTIMPLEMENTED();
}
+void RenderWidgetHostViewMus::OnWindowInputEvent(
+ mus::Window* window,
+ const ui::Event& event,
+ std::unique_ptr<base::Callback<void(mus::mojom::EventResult)>>*
+ ack_callback) {
+ // TODO(sad): Dispatch |event| to the RenderWidgetHost.
+}
+
} // namespace content
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 3d786a49e6b..ec440d8bcca 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
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "build/build_config.h"
+#include "components/mus/public/cpp/input_event_handler.h"
#include "components/mus/public/cpp/scoped_window_ptr.h"
#include "components/mus/public/cpp/window.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -30,7 +31,9 @@ struct TextInputState;
// 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
// the renderer from Mus.
-class CONTENT_EXPORT RenderWidgetHostViewMus : public RenderWidgetHostViewBase {
+class CONTENT_EXPORT RenderWidgetHostViewMus
+ : public RenderWidgetHostViewBase,
+ NON_EXPORTED_BASE(public mus::InputEventHandler) {
public:
RenderWidgetHostViewMus(mus::Window* parent_window,
RenderWidgetHostImpl* widget);
@@ -98,7 +101,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMus : public RenderWidgetHostViewBase {
bool LockMouse() override;
void UnlockMouse() override;
void GetScreenInfo(blink::WebScreenInfo* results) override;
- bool GetScreenColorProfile(std::vector<char>* color_profile) override;
gfx::Rect GetBoundsInRootWindow() override;
#if defined(OS_MACOSX)
@@ -115,6 +117,13 @@ class CONTENT_EXPORT RenderWidgetHostViewMus : public RenderWidgetHostViewBase {
void LockCompositingSurface() override;
void UnlockCompositingSurface() override;
+ // mus::InputEventHandler:
+ void OnWindowInputEvent(
+ mus::Window* target,
+ const ui::Event& event,
+ std::unique_ptr<base::Callback<void(mus::mojom::EventResult)>>*
+ ack_callback) override;
+
RenderWidgetHostImpl* host_;
aura::Window* aura_window_;
diff --git a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
index b6ba92d543f..d27a2435547 100644
--- a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
+++ b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
@@ -27,6 +27,7 @@
#include "content/common/set_process_title.h"
#include "content/public/common/content_switches.h"
#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
+#include "skia/ext/skia_utils_base.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#include "ui/gfx/font.h"
#include "ui/gfx/font_fallback_linux.h"
@@ -283,8 +284,8 @@ void SandboxIPCHandler::HandleGetStyleForStrike(
gfx::FontRenderParamsQuery query;
query.families.push_back(family);
query.pixel_size = pixel_size;
- query.style = gfx::Font::NORMAL |
- (bold ? gfx::Font::BOLD : 0) | (italic ? gfx::Font::ITALIC : 0);
+ query.style = italic ? gfx::Font::ITALIC : 0;
+ query.weight = bold ? gfx::Font::Weight::BOLD : gfx::Font::Weight::NORMAL;
const gfx::FontRenderParams params = gfx::GetFontRenderParams(query, NULL);
// These are passed as ints since they're interpreted as tri-state chars in
diff --git a/chromium/content/browser/renderer_host/sandbox_ipc_linux.h b/chromium/content/browser/renderer_host/sandbox_ipc_linux.h
index 2632b163a58..3d9e98de331 100644
--- a/chromium/content/browser/renderer_host/sandbox_ipc_linux.h
+++ b/chromium/content/browser/renderer_host/sandbox_ipc_linux.h
@@ -14,7 +14,8 @@
#include "base/macros.h"
#include "base/pickle.h"
#include "base/threading/simple_thread.h"
-#include "skia/ext/skia_utils_base.h"
+
+class SkString;
namespace content {
diff --git a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
index f12bbc26d86..e953183ddae 100644
--- a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -155,7 +155,7 @@ TEST_F(TextInputClientMacTest, NotFoundCharacterIndex) {
base::Unretained(service()), kPreviousValue));
scoped_refptr<TextInputClientMessageFilter> filter(
- new TextInputClientMessageFilter(widget()->GetProcess()->GetID()));
+ new TextInputClientMessageFilter());
std::unique_ptr<IPC::Message> message(
new TextInputClientReplyMsg_GotCharacterIndexForPoint(
widget()->GetRoutingID(), UINT32_MAX));
diff --git a/chromium/content/browser/renderer_host/text_input_client_message_filter.h b/chromium/content/browser/renderer_host/text_input_client_message_filter.h
index 95780b055d8..e32743b0aa8 100644
--- a/chromium/content/browser/renderer_host/text_input_client_message_filter.h
+++ b/chromium/content/browser/renderer_host/text_input_client_message_filter.h
@@ -25,7 +25,7 @@ namespace content {
class CONTENT_EXPORT TextInputClientMessageFilter
: public BrowserMessageFilter {
public:
- explicit TextInputClientMessageFilter(int child_id);
+ TextInputClientMessageFilter();
// BrowserMessageFilter override:
bool OnMessageReceived(const IPC::Message& message) override;
@@ -44,9 +44,6 @@ class CONTENT_EXPORT TextInputClientMessageFilter
const mac::AttributedStringCoder::EncodedString& string,
const gfx::Point& point);
- // Child process id.
- int child_process_id_;
-
DISALLOW_COPY_AND_ASSIGN(TextInputClientMessageFilter);
};
diff --git a/chromium/content/browser/renderer_host/text_input_client_message_filter.mm b/chromium/content/browser/renderer_host/text_input_client_message_filter.mm
index 56dba28480d..7ab20e407f1 100644
--- a/chromium/content/browser/renderer_host/text_input_client_message_filter.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_message_filter.mm
@@ -15,10 +15,8 @@
namespace content {
-TextInputClientMessageFilter::TextInputClientMessageFilter(int child_id)
- : BrowserMessageFilter(TextInputClientMsgStart),
- child_process_id_(child_id) {
-}
+TextInputClientMessageFilter::TextInputClientMessageFilter()
+ : BrowserMessageFilter(TextInputClientMsgStart) {}
bool TextInputClientMessageFilter::OnMessageReceived(
const IPC::Message& message) {
diff --git a/chromium/content/browser/renderer_host/text_input_manager.cc b/chromium/content/browser/renderer_host/text_input_manager.cc
new file mode 100644
index 00000000000..903c471b20a
--- /dev/null
+++ b/chromium/content/browser/renderer_host/text_input_manager.cc
@@ -0,0 +1,134 @@
+// 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/text_input_manager.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
+
+namespace content {
+
+namespace {
+
+bool AreDifferentTextInputStates(const content::TextInputState& old_state,
+ const content::TextInputState& new_state) {
+#if defined(USE_AURA)
+ return old_state.type != new_state.type || old_state.mode != new_state.mode ||
+ old_state.flags != new_state.flags ||
+ old_state.can_compose_inline != new_state.can_compose_inline;
+#else
+ // TODO(ekaramad): Implement the logic for other platforms (crbug.com/578168).
+ NOTREACHED();
+ return true;
+#endif
+}
+
+} // namespace
+
+TextInputManager::TextInputManager() : active_view_(nullptr) {}
+
+TextInputManager::~TextInputManager() {
+ // If there is an active view, we should unregister it first so that the
+ // the tab's top-level RWHV will be notified about |TextInputState.type|
+ // resetting to none (i.e., we do not have an active RWHV anymore).
+ if (active_view_)
+ Unregister(active_view_);
+
+ // Unregister all the remaining views.
+ std::vector<RenderWidgetHostViewBase*> views;
+ for (auto pair : text_input_state_map_)
+ views.push_back(pair.first);
+
+ for (auto view : views)
+ Unregister(view);
+}
+
+const TextInputState* TextInputManager::GetTextInputState() {
+ return !!active_view_ ? &text_input_state_map_[active_view_] : nullptr;
+}
+
+RenderWidgetHostImpl* TextInputManager::GetActiveWidget() const {
+ return !!active_view_ ? static_cast<RenderWidgetHostImpl*>(
+ active_view_->GetRenderWidgetHost())
+ : nullptr;
+}
+
+void TextInputManager::UpdateTextInputState(
+ RenderWidgetHostViewBase* view,
+ const TextInputState& text_input_state) {
+ DCHECK(IsRegistered(view));
+
+ // Since |view| is registgered, we already have a previous value for its
+ // TextInputState.
+ bool changed = AreDifferentTextInputStates(text_input_state_map_[view],
+ text_input_state);
+
+ text_input_state_map_[view] = text_input_state;
+
+ // |active_view_| is only updated when the state for |view| is not none.
+ if (text_input_state.type != ui::TEXT_INPUT_TYPE_NONE)
+ active_view_ = view;
+
+ // If the state for |active_view_| is none, then we no longer have an
+ // |active_view_|.
+ if (active_view_ == view && text_input_state.type == ui::TEXT_INPUT_TYPE_NONE)
+ active_view_ = nullptr;
+
+ NotifyObserversAboutInputStateUpdate(view, changed);
+}
+
+void TextInputManager::ImeCancelComposition(RenderWidgetHostViewBase* view) {
+ DCHECK(IsRegistered(view));
+ FOR_EACH_OBSERVER(Observer, observer_list_,
+ OnImeCancelComposition(this, view));
+}
+
+void TextInputManager::Register(RenderWidgetHostViewBase* view) {
+ DCHECK(!IsRegistered(view));
+
+ text_input_state_map_[view] = TextInputState();
+}
+
+void TextInputManager::Unregister(RenderWidgetHostViewBase* view) {
+ DCHECK(IsRegistered(view));
+
+ text_input_state_map_.erase(view);
+ if (active_view_ == view) {
+ active_view_ = nullptr;
+ NotifyObserversAboutInputStateUpdate(view, true);
+ }
+ view->DidUnregisterFromTextInputManager(this);
+}
+
+bool TextInputManager::IsRegistered(RenderWidgetHostViewBase* view) const {
+ return text_input_state_map_.count(view) == 1;
+}
+
+void TextInputManager::AddObserver(Observer* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void TextInputManager::RemoveObserver(Observer* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+size_t TextInputManager::GetRegisteredViewsCountForTesting() {
+ return text_input_state_map_.size();
+}
+
+ui::TextInputType TextInputManager::GetTextInputTypeForViewForTesting(
+ RenderWidgetHostViewBase* view) {
+ DCHECK(IsRegistered(view));
+ return text_input_state_map_[view].type;
+}
+
+void TextInputManager::NotifyObserversAboutInputStateUpdate(
+ RenderWidgetHostViewBase* updated_view,
+ bool did_update_state) {
+ FOR_EACH_OBSERVER(
+ Observer, observer_list_,
+ OnUpdateTextInputStateCalled(this, updated_view, did_update_state));
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/renderer_host/text_input_manager.h b/chromium/content/browser/renderer_host/text_input_manager.h
new file mode 100644
index 00000000000..2bb4c16d9e5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/text_input_manager.h
@@ -0,0 +1,120 @@
+// 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_TEXT_INPUT_MANAGER_H__
+#define CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__
+
+#include <unordered_map>
+
+#include "base/observer_list.h"
+#include "content/common/content_export.h"
+#include "content/common/text_input_state.h"
+
+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
+// text input state is updated.
+class CONTENT_EXPORT TextInputManager {
+ public:
+ // The tab's top-level RWHV should be an observer of TextInputManager to get
+ // notifications about changes in TextInputState or other IME related state
+ // for child frames.
+ class CONTENT_EXPORT Observer {
+ public:
+ // Called when a view has called UpdateTextInputState on TextInputManager.
+ // If the call has led to a change in TextInputState, |did_update_state| is
+ // true. In some plaforms, we need this update even when the state has not
+ // changed (e.g., Aura for updating IME).
+ virtual void OnUpdateTextInputStateCalled(
+ TextInputManager* text_input_manager,
+ RenderWidgetHostViewBase* updated_view,
+ bool did_update_state) {}
+ // Called when |updated_view| has called ImeCancelComposition on
+ // TextInputManager.
+ virtual void OnImeCancelComposition(
+ TextInputManager* text_input_manager,
+ RenderWidgetHostViewBase* updated_view) {}
+ };
+
+ TextInputManager();
+ ~TextInputManager();
+
+ // ---------------------------------------------------------------------------
+ // The following methods can be used to obtain information about IME-related
+ // state for the active RenderWidget.
+
+ // Returns the currently active widget, i.e., the RWH which is associated with
+ // |active_view_|.
+ RenderWidgetHostImpl* GetActiveWidget() const;
+
+ // Returns the TextInputState corresponding to |active_view_|.
+ // Users of this method should not hold on to the pointer as it might become
+ // dangling if the TextInputManager or |active_view_| might go away.
+ const TextInputState* GetTextInputState();
+
+ // ---------------------------------------------------------------------------
+ // The following methods are called by RWHVs on the tab to update their IME-
+ // related state.
+
+ // Updates the TextInputState for |view|.
+ void UpdateTextInputState(RenderWidgetHostViewBase* view,
+ const TextInputState& state);
+
+ // The current IME composition has been cancelled on the renderer side for
+ // the widget corresponding to |view|.
+ void ImeCancelComposition(RenderWidgetHostViewBase* view);
+
+ // Registers the given |view| for tracking its TextInputState. This is called
+ // by any view which has updates in its TextInputState (whether tab's RWHV or
+ // that of a child frame). The |view| must unregister itself before being
+ // destroyed (i.e., call TextInputManager::Unregister).
+ void Register(RenderWidgetHostViewBase* view);
+
+ // Clears the TextInputState from the |view|. If |view == active_view_|, this
+ // call will lead to a TextInputState update since the TextInputState.type
+ // should be reset to none.
+ void Unregister(RenderWidgetHostViewBase* view);
+
+ // Returns true if |view| is already registered.
+ bool IsRegistered(RenderWidgetHostViewBase* view) const;
+
+ // Add and remove observers for notifications regarding updates in the
+ // TextInputState. Clients must be sure to remove themselves before they go
+ // away.
+ // Only the tab's RWHV should observer TextInputManager. In tests, however,
+ // in addition to the tab's RWHV, one or more test observers might observe
+ // TextInputManager.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ RenderWidgetHostViewBase* active_view_for_testing() { return active_view_; }
+ size_t GetRegisteredViewsCountForTesting();
+ ui::TextInputType GetTextInputTypeForViewForTesting(
+ RenderWidgetHostViewBase* view);
+
+ private:
+ void NotifyObserversAboutInputStateUpdate(RenderWidgetHostViewBase* view,
+ bool did_update_state);
+
+ // The view with active text input state, i.e., a focused <input> element.
+ // It will be nullptr if no such view exists. Note that the active view
+ // cannot have a |TextInputState.type| of ui::TEXT_INPUT_TYPE_NONE.
+ RenderWidgetHostViewBase* active_view_;
+
+ std::unordered_map<RenderWidgetHostViewBase*, TextInputState>
+ text_input_state_map_;
+
+ base::ObserverList<Observer> observer_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(TextInputManager);
+};
+}
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__ \ No newline at end of file
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index a062303cc07..91838e8ea3b 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -9,7 +9,7 @@
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/common/input/web_touch_event_traits.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/events/blink/blink_event_util.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
@@ -64,8 +64,8 @@ bool MakeUITouchEventsFromWebTouchEvents(
}
int flags = WebEventModifiersToEventFlags(touch.modifiers);
- base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
- static_cast<int64_t>(touch.timeStampSeconds * 1000000));
+ base::TimeTicks timestamp =
+ ui::EventTimeStampFromSeconds(touch.timeStampSeconds);
for (unsigned i = 0; i < touch.touchesLength; ++i) {
const blink::WebTouchPoint& point = touch.touches[i];
if (WebTouchPointStateToEventType(point.state) != type)
@@ -87,11 +87,4 @@ bool MakeUITouchEventsFromWebTouchEvents(
return true;
}
-blink::WebGestureEvent MakeWebGestureEventFromUIEvent(
- const ui::GestureEvent& event) {
- return ui::CreateWebGestureEvent(event.details(), event.time_stamp(),
- event.location_f(), event.root_location_f(),
- event.flags());
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.h b/chromium/content/browser/renderer_host/ui_events_helper.h
index fc57dd7a9e7..dc92483d8a5 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.h
+++ b/chromium/content/browser/renderer_host/ui_events_helper.h
@@ -9,14 +9,7 @@
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/content_export.h"
-namespace blink {
-class WebGestureEvent;
-class WebTouchEvent;
-class WebTouchPoint;
-}
-
namespace ui {
-class GestureEvent;
class TouchEvent;
}
@@ -42,12 +35,6 @@ CONTENT_EXPORT bool MakeUITouchEventsFromWebTouchEvents(
ScopedVector<ui::TouchEvent>* list,
TouchEventCoordinateSystem coordinate_system);
-// Creates a WebGestureEvent from a ui::GestureEvent. Note that it does not
-// populate the event coordinates (i.e. |x|, |y|, |globalX|, and |globalY|). So
-// the caller must populate these fields.
-blink::WebGestureEvent MakeWebGestureEventFromUIEvent(
- const ui::GestureEvent& event);
-
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_UI_EVENTS_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/web_input_event_aura.cc b/chromium/content/browser/renderer_host/web_input_event_aura.cc
index 3ed96dc0fc6..d60ec480670 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.cc
@@ -6,9 +6,9 @@
#include "build/build_config.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
-#include "content/browser/renderer_host/ui_events_helper.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/window.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
@@ -51,30 +51,41 @@ blink::WebPointerProperties::PointerType EventPointerTypeToWebPointerType(
return blink::WebPointerProperties::PointerType::Unknown;
}
+// Creates a WebGestureEvent from a ui::GestureEvent. Note that it does not
+// populate the event coordinates (i.e. |x|, |y|, |globalX|, and |globalY|). So
+// the caller must populate these fields.
+blink::WebGestureEvent MakeWebGestureEventFromUIEvent(
+ const ui::GestureEvent& event) {
+ return ui::CreateWebGestureEvent(
+ event.details(), event.time_stamp(), event.location_f(),
+ event.root_location_f(), event.flags(), event.unique_touch_event_id());
+}
+
} // namespace
#if defined(OS_WIN)
blink::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
const base::NativeEvent& native_event,
- const base::TimeDelta& time_stamp,
+ const base::TimeTicks& time_stamp,
blink::WebPointerProperties::PointerType pointer_type);
blink::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
const base::NativeEvent& native_event,
- const base::TimeDelta& time_stamp,
+ const base::TimeTicks& time_stamp,
blink::WebPointerProperties::PointerType pointer_type);
blink::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
const base::NativeEvent& native_event,
- const base::TimeDelta& time_stamp);
+ const base::TimeTicks& time_stamp);
blink::WebGestureEvent MakeWebGestureEventFromNativeEvent(
const base::NativeEvent& native_event,
- const base::TimeDelta& time_stamp);
+ const base::TimeTicks& time_stamp);
#endif
blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
const ui::KeyEvent& event) {
blink::WebKeyboardEvent webkit_event;
- webkit_event.timeStampSeconds = event.time_stamp().InSecondsF();
+ webkit_event.timeStampSeconds =
+ ui::EventTimeStampToSeconds(event.time_stamp());
webkit_event.modifiers = ui::EventFlagsToWebEventModifiers(event.flags()) |
DomCodeToWebInputEventModifiers(event.code());
@@ -117,7 +128,8 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
webkit_event.type = blink::WebInputEvent::MouseWheel;
webkit_event.button = blink::WebMouseEvent::ButtonNone;
webkit_event.modifiers = ui::EventFlagsToWebEventModifiers(event.flags());
- webkit_event.timeStampSeconds = event.time_stamp().InSecondsF();
+ webkit_event.timeStampSeconds =
+ ui::EventTimeStampToSeconds(event.time_stamp());
webkit_event.hasPreciseScrollingDeltas = true;
float offset_ordinal_x = 0.f;
@@ -168,7 +180,8 @@ blink::WebGestureEvent MakeWebGestureEventFromAuraEvent(
webkit_event.sourceDevice = blink::WebGestureDeviceTouchpad;
webkit_event.modifiers = ui::EventFlagsToWebEventModifiers(event.flags());
- webkit_event.timeStampSeconds = event.time_stamp().InSecondsF();
+ webkit_event.timeStampSeconds =
+ ui::EventTimeStampToSeconds(event.time_stamp());
return webkit_event;
}
@@ -256,14 +269,6 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
webkit_event.globalX = screen_point.x();
webkit_event.globalY = screen_point.y();
- // Scroll events generated from the mouse wheel when the control key is held
- // don't trigger scrolling. Instead, they may cause zooming.
- bool from_mouse_wheel = !webkit_event.hasPreciseScrollingDeltas;
- if ((webkit_event.modifiers & blink::WebInputEvent::ControlKey) &&
- from_mouse_wheel) {
- webkit_event.canScroll = false;
- }
-
return webkit_event;
}
@@ -362,7 +367,8 @@ blink::WebGestureEvent MakeWebGestureEventFlingCancel() {
// All other fields are ignored on a GestureFlingCancel event.
gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
- gesture_event.timeStampSeconds = ui::EventTimeForNow().InSecondsF();
+ gesture_event.timeStampSeconds =
+ ui::EventTimeStampToSeconds(ui::EventTimeForNow());
gesture_event.sourceDevice = blink::WebGestureDeviceTouchpad;
return gesture_event;
}
@@ -372,8 +378,8 @@ blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(
blink::WebMouseEvent webkit_event;
webkit_event.modifiers = ui::EventFlagsToWebEventModifiers(event.flags());
- webkit_event.timeStampSeconds = event.time_stamp().InSecondsF();
-
+ webkit_event.timeStampSeconds =
+ ui::EventTimeStampToSeconds(event.time_stamp());
webkit_event.button = blink::WebMouseEvent::ButtonNone;
int button_flags = event.flags();
if (event.type() == ui::ET_MOUSE_PRESSED ||
@@ -427,7 +433,8 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
webkit_event.type = blink::WebInputEvent::MouseWheel;
webkit_event.button = blink::WebMouseEvent::ButtonNone;
webkit_event.modifiers = ui::EventFlagsToWebEventModifiers(event.flags());
- webkit_event.timeStampSeconds = event.time_stamp().InSecondsF();
+ webkit_event.timeStampSeconds =
+ ui::EventTimeStampToSeconds(event.time_stamp());
if ((event.flags() & ui::EF_SHIFT_DOWN) != 0 && event.x_offset() == 0) {
webkit_event.deltaX = event.y_offset();
diff --git a/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc b/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc
index 412c607eeeb..63143f6767c 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
@@ -253,14 +254,15 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventKeyPadKeyCode) {
TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
{
// Left pressed.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(
ui::ET_MOUSE_PRESSED, gfx::Point(123, 321), gfx::Point(123, 321),
timestamp, ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonLeft, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseDown, webkit_event.type);
EXPECT_EQ(aura_event.GetClickCount(), webkit_event.clickCount);
@@ -271,14 +273,15 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Left released.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(ui::ET_MOUSE_RELEASED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, 0,
ui::EF_LEFT_MOUSE_BUTTON);
blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonLeft, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseUp, webkit_event.type);
EXPECT_EQ(aura_event.GetClickCount(), webkit_event.clickCount);
@@ -289,14 +292,15 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Middle pressed.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(
ui::ET_MOUSE_PRESSED, gfx::Point(123, 321), gfx::Point(123, 321),
timestamp, ui::EF_MIDDLE_MOUSE_BUTTON, ui::EF_MIDDLE_MOUSE_BUTTON);
blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonMiddle, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseDown, webkit_event.type);
EXPECT_EQ(aura_event.GetClickCount(), webkit_event.clickCount);
@@ -307,14 +311,15 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Middle released.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(ui::ET_MOUSE_RELEASED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, 0,
ui::EF_MIDDLE_MOUSE_BUTTON);
blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonMiddle, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseUp, webkit_event.type);
EXPECT_EQ(aura_event.GetClickCount(), webkit_event.clickCount);
@@ -325,14 +330,15 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Right pressed.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(
ui::ET_MOUSE_PRESSED, gfx::Point(123, 321), gfx::Point(123, 321),
timestamp, ui::EF_RIGHT_MOUSE_BUTTON, ui::EF_RIGHT_MOUSE_BUTTON);
blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonRight, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseDown, webkit_event.type);
EXPECT_EQ(aura_event.GetClickCount(), webkit_event.clickCount);
@@ -343,14 +349,15 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Right released.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(ui::ET_MOUSE_RELEASED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, 0,
ui::EF_RIGHT_MOUSE_BUTTON);
blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonRight, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseUp, webkit_event.type);
EXPECT_EQ(aura_event.GetClickCount(), webkit_event.clickCount);
@@ -361,13 +368,14 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Moved
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(ui::ET_MOUSE_MOVED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, 0, 0);
blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonNone, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseMove, webkit_event.type);
EXPECT_EQ(aura_event.GetClickCount(), webkit_event.clickCount);
@@ -378,14 +386,15 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Moved with left down
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(ui::ET_MOUSE_MOVED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp,
ui::EF_LEFT_MOUSE_BUTTON, 0);
blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonLeft, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseMove, webkit_event.type);
EXPECT_EQ(aura_event.GetClickCount(), webkit_event.clickCount);
@@ -396,7 +405,7 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Left with shift pressed.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(ui::ET_MOUSE_PRESSED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp,
ui::EF_LEFT_MOUSE_BUTTON | ui::EF_SHIFT_DOWN,
@@ -404,7 +413,8 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
blink::WebMouseEvent webkit_event = MakeWebMouseEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonLeft, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseDown, webkit_event.type);
EXPECT_EQ(aura_event.GetClickCount(), webkit_event.clickCount);
@@ -415,7 +425,7 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Default values for PointerDetails.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(
ui::ET_MOUSE_PRESSED, gfx::Point(123, 321), gfx::Point(123, 321),
timestamp, ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
@@ -433,7 +443,7 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
}
{
// Stylus values for PointerDetails.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseEvent aura_event(
ui::ET_MOUSE_PRESSED, gfx::Point(123, 321), gfx::Point(123, 321),
timestamp, ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
@@ -461,7 +471,7 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
TEST(WebInputEventAuraTest, TestMakeWebMouseWheelEvent) {
{
// Mouse wheel.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseWheelEvent aura_event(
gfx::Vector2d(ui::MouseWheelEvent::kWheelDelta * 2,
-ui::MouseWheelEvent::kWheelDelta * 2),
@@ -469,7 +479,8 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseWheelEvent) {
blink::WebMouseWheelEvent webkit_event = MakeWebMouseWheelEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonNone, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseWheel, webkit_event.type);
EXPECT_FLOAT_EQ(aura_event.x_offset() / 53.0f, webkit_event.wheelTicksX);
@@ -486,7 +497,7 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseWheelEvent) {
}
{
// Mouse wheel with shift and no x offset.
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::MouseWheelEvent aura_event(
gfx::Vector2d(0, -ui::MouseWheelEvent::kWheelDelta * 2),
gfx::Point(123, 321), gfx::Point(123, 321), timestamp,
@@ -494,7 +505,8 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseWheelEvent) {
blink::WebMouseWheelEvent webkit_event = MakeWebMouseWheelEvent(aura_event);
EXPECT_EQ(ui::EventFlagsToWebEventModifiers(aura_event.flags()),
webkit_event.modifiers);
- EXPECT_FLOAT_EQ(timestamp.InSecondsF(), webkit_event.timeStampSeconds);
+ EXPECT_FLOAT_EQ(ui::EventTimeStampToSeconds(timestamp),
+ webkit_event.timeStampSeconds);
EXPECT_EQ(blink::WebMouseEvent::ButtonNone, webkit_event.button);
EXPECT_EQ(blink::WebInputEvent::MouseWheel, webkit_event.type);
EXPECT_FLOAT_EQ(aura_event.y_offset() / 53.0f, webkit_event.wheelTicksX);
diff --git a/chromium/content/browser/renderer_host/web_input_event_aurawin.cc b/chromium/content/browser/renderer_host/web_input_event_aurawin.cc
index 0cb36dff27a..6b3260a59d9 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aurawin.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aurawin.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/time/time.h"
#include "content/browser/renderer_host/input/web_input_event_builders_win.h"
+#include "ui/events/base_event_utils.h"
namespace content {
@@ -16,33 +17,35 @@ namespace content {
blink::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
const base::NativeEvent& native_event,
- const base::TimeDelta& time_stamp,
+ const base::TimeTicks& time_stamp,
blink::WebPointerProperties::PointerType pointer_type) {
return WebMouseEventBuilder::Build(native_event.hwnd, native_event.message,
native_event.wParam, native_event.lParam,
- time_stamp.InSecondsF(), pointer_type);
+ ui::EventTimeStampToSeconds(time_stamp),
+ pointer_type);
}
blink::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
const base::NativeEvent& native_event,
- const base::TimeDelta& time_stamp,
+ const base::TimeTicks& time_stamp,
blink::WebPointerProperties::PointerType pointer_type) {
return WebMouseWheelEventBuilder::Build(
native_event.hwnd, native_event.message, native_event.wParam,
- native_event.lParam, time_stamp.InSecondsF(), pointer_type);
+ native_event.lParam, ui::EventTimeStampToSeconds(time_stamp),
+ pointer_type);
}
blink::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
const base::NativeEvent& native_event,
- const base::TimeDelta& time_stamp) {
+ const base::TimeTicks& time_stamp) {
return WebKeyboardEventBuilder::Build(
native_event.hwnd, native_event.message, native_event.wParam,
- native_event.lParam, time_stamp.InSecondsF());
+ native_event.lParam, ui::EventTimeStampToSeconds(time_stamp));
}
blink::WebGestureEvent MakeWebGestureEventFromNativeEvent(
const base::NativeEvent& native_event,
- const base::TimeDelta& time_stamp) {
+ const base::TimeTicks& time_stamp) {
// TODO: Create gestures from native event.
NOTIMPLEMENTED();
return blink::WebGestureEvent();
diff --git a/chromium/content/browser/renderer_host/websocket_blob_sender_unittest.cc b/chromium/content/browser/renderer_host/websocket_blob_sender_unittest.cc
index a35efeee44c..f3b44dd014f 100644
--- a/chromium/content/browser/renderer_host/websocket_blob_sender_unittest.cc
+++ b/chromium/content/browser/renderer_host/websocket_blob_sender_unittest.cc
@@ -18,7 +18,9 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
#include "base/task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/public/browser/blob_handle.h"
@@ -71,7 +73,7 @@ class FakeChannel : public WebSocketBlobSender::Channel {
EXPECT_LE(data.size(), current_send_quota_);
message_.insert(message_.end(), data.begin(), data.end());
current_send_quota_ -= data.size();
- base::MessageLoop::current()->PostTask(
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&FakeChannel::RefreshQuota, weak_factory_.GetWeakPtr()));
return net::WebSocketEventInterface::CHANNEL_ALIVE;
diff --git a/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
index d00d43f36f4..4fd1f5c385e 100644
--- a/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
@@ -117,19 +117,17 @@ class WebSocketDispatcherHostTest : public ::testing::Test {
protected:
// Adds |n| connections. Returns true if succeeded.
bool AddMultipleChannels(int number_of_channels) {
- GURL socket_url("ws://example.com/test");
- std::vector<std::string> requested_protocols;
- url::Origin origin(GURL("http://example.com"));
- int render_frame_id = -3;
-
for (int i = 0; i < number_of_channels; ++i) {
int routing_id = next_routing_id_++;
- WebSocketHostMsg_AddChannelRequest message(
- routing_id,
- socket_url,
- requested_protocols,
- origin,
- render_frame_id);
+
+ WebSocketHostMsg_AddChannelRequest_Params params;
+ params.socket_url = GURL("ws://example.com/test");
+ params.origin = url::Origin(GURL("http://example.com"));
+ params.first_party_for_cookies = GURL("http://example.com");
+ params.user_agent_override = "";
+ params.render_frame_id = -3;
+
+ WebSocketHostMsg_AddChannelRequest message(routing_id, params);
if (!dispatcher_host_->OnMessageReceived(message))
return false;
}
@@ -139,19 +137,18 @@ class WebSocketDispatcherHostTest : public ::testing::Test {
// Adds and cancels |n| connections. Returns true if succeeded.
bool AddAndCancelMultipleChannels(int number_of_channels) {
- GURL socket_url("ws://example.com/test");
- std::vector<std::string> requested_protocols;
- url::Origin origin(GURL("http://example.com"));
- int render_frame_id = -3;
-
for (int i = 0; i < number_of_channels; ++i) {
int routing_id = next_routing_id_++;
+
+ WebSocketHostMsg_AddChannelRequest_Params params;
+ params.socket_url = GURL("ws://example.com/test");
+ params.origin = url::Origin(GURL("http://example.com"));
+ params.first_party_for_cookies = GURL("http://example.com");
+ params.user_agent_override = "";
+ params.render_frame_id = -3;
+
WebSocketHostMsg_AddChannelRequest messageAddChannelRequest(
- routing_id,
- socket_url,
- requested_protocols,
- origin,
- render_frame_id);
+ routing_id, params);
if (!dispatcher_host_->OnMessageReceived(messageAddChannelRequest))
return false;
@@ -220,13 +217,18 @@ TEST_F(WebSocketDispatcherHostTest, RenderProcessIdGetter) {
TEST_F(WebSocketDispatcherHostTest, AddChannelRequest) {
int routing_id = 123;
- GURL socket_url("ws://example.com/test");
std::vector<std::string> requested_protocols;
requested_protocols.push_back("hello");
- url::Origin origin(GURL("http://example.com"));
- int render_frame_id = -2;
- WebSocketHostMsg_AddChannelRequest message(
- routing_id, socket_url, requested_protocols, origin, render_frame_id);
+
+ WebSocketHostMsg_AddChannelRequest_Params params;
+ params.socket_url = GURL("ws://example.com/test");
+ params.requested_protocols = requested_protocols;
+ params.origin = url::Origin(GURL("http://example.com"));
+ params.first_party_for_cookies = GURL("http://example.com");
+ params.user_agent_override = "";
+ params.render_frame_id = -2;
+
+ WebSocketHostMsg_AddChannelRequest message(routing_id, params);
ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message));
@@ -254,13 +256,18 @@ TEST_F(WebSocketDispatcherHostTest, SendFrameButNoHostYet) {
TEST_F(WebSocketDispatcherHostTest, SendFrame) {
int routing_id = 123;
- GURL socket_url("ws://example.com/test");
std::vector<std::string> requested_protocols;
requested_protocols.push_back("hello");
- url::Origin origin(GURL("http://example.com"));
- int render_frame_id = -2;
- WebSocketHostMsg_AddChannelRequest add_channel_message(
- routing_id, socket_url, requested_protocols, origin, render_frame_id);
+
+ WebSocketHostMsg_AddChannelRequest_Params params;
+ params.socket_url = GURL("ws://example.com/test");
+ params.requested_protocols = requested_protocols;
+ params.origin = url::Origin(GURL("http://example.com"));
+ params.first_party_for_cookies = GURL("http://example.com");
+ params.user_agent_override = "";
+ params.render_frame_id = -2;
+
+ WebSocketHostMsg_AddChannelRequest add_channel_message(routing_id, params);
ASSERT_TRUE(dispatcher_host_->OnMessageReceived(add_channel_message));
@@ -287,12 +294,25 @@ TEST_F(WebSocketDispatcherHostTest, SendFrame) {
}
TEST_F(WebSocketDispatcherHostTest, Destruct) {
- WebSocketHostMsg_AddChannelRequest message1(
- 123, GURL("ws://example.com/test"), std::vector<std::string>(),
- url::Origin(GURL("http://example.com")), -1);
- WebSocketHostMsg_AddChannelRequest message2(
- 456, GURL("ws://example.com/test2"), std::vector<std::string>(),
- url::Origin(GURL("http://example.com")), -1);
+ WebSocketHostMsg_AddChannelRequest_Params params1;
+ params1.socket_url = GURL("ws://example.com/test");
+ params1.requested_protocols = std::vector<std::string>();
+ params1.origin = url::Origin(GURL("http://example.com"));
+ params1.first_party_for_cookies = GURL("http://example.com");
+ params1.user_agent_override = "";
+ params1.render_frame_id = -1;
+
+ WebSocketHostMsg_AddChannelRequest message1(123, params1);
+
+ WebSocketHostMsg_AddChannelRequest_Params params2;
+ params2.socket_url = GURL("ws://example.com/test2");
+ params2.requested_protocols = std::vector<std::string>();
+ params2.origin = url::Origin(GURL("http://example.com"));
+ params2.first_party_for_cookies = GURL("http://example.com");
+ params2.user_agent_override = "";
+ params2.render_frame_id = -1;
+
+ WebSocketHostMsg_AddChannelRequest message2(456, params2);
ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message1));
ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message2));
@@ -413,13 +433,19 @@ TEST_F(WebSocketDispatcherHostTest, NotRejectedAfter255FailedConnections) {
// This is a regression test for https://crrev.com/998173003/.
TEST_F(WebSocketDispatcherHostTest, InvalidScheme) {
int routing_id = 123;
- GURL socket_url("http://example.com/test");
+
std::vector<std::string> requested_protocols;
requested_protocols.push_back("hello");
- url::Origin origin(GURL("http://example.com"));
- int render_frame_id = -2;
- WebSocketHostMsg_AddChannelRequest message(
- routing_id, socket_url, requested_protocols, origin, render_frame_id);
+
+ WebSocketHostMsg_AddChannelRequest_Params params;
+ params.socket_url = GURL("http://example.com/test");
+ params.requested_protocols = requested_protocols;
+ params.origin = url::Origin(GURL("http://example.com"));
+ params.first_party_for_cookies = GURL("http://example.com");
+ params.user_agent_override = "";
+ params.render_frame_id = -2;
+
+ WebSocketHostMsg_AddChannelRequest message(routing_id, params);
ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message));
diff --git a/chromium/content/browser/renderer_host/websocket_host.cc b/chromium/content/browser/renderer_host/websocket_host.cc
index cce4485b3d4..53dfd35d4bb 100644
--- a/chromium/content/browser/renderer_host/websocket_host.cc
+++ b/chromium/content/browser/renderer_host/websocket_host.cc
@@ -396,25 +396,31 @@ bool WebSocketHost::OnMessageReceived(const IPC::Message& message) {
}
void WebSocketHost::OnAddChannelRequest(
- const GURL& socket_url,
- const std::vector<std::string>& requested_protocols,
- const url::Origin& origin,
- int render_frame_id) {
+ const WebSocketHostMsg_AddChannelRequest_Params& params) {
DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
- << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
- << "\" requested_protocols=\""
- << base::JoinString(requested_protocols, ", ") << "\" origin=\""
- << origin << "\"";
+ << " routing_id=" << routing_id_ << " socket_url=\""
+ << params.socket_url << "\" requested_protocols=\""
+ << base::JoinString(params.requested_protocols, ", ")
+ << "\" origin=\"" << params.origin
+ << "\" first_party_for_cookies=\""
+ << params.first_party_for_cookies << "\" user_agent_override=\""
+ << params.user_agent_override
+ << "\"";
DCHECK(!channel_);
if (delay_ > base::TimeDelta()) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::Bind(&WebSocketHost::AddChannel, weak_ptr_factory_.GetWeakPtr(),
- socket_url, requested_protocols, origin, render_frame_id),
+ params.socket_url, params.requested_protocols,
+ params.origin, params.first_party_for_cookies,
+ params.user_agent_override, params.render_frame_id),
delay_);
} else {
- AddChannel(socket_url, requested_protocols, origin, render_frame_id);
+ AddChannel(
+ params.socket_url, params.requested_protocols, params.origin,
+ params.first_party_for_cookies, params.user_agent_override,
+ params.render_frame_id);
}
// |this| may have been deleted here.
}
@@ -423,12 +429,16 @@ void WebSocketHost::AddChannel(
const GURL& socket_url,
const std::vector<std::string>& requested_protocols,
const url::Origin& origin,
+ const GURL& first_party_for_cookies,
+ const std::string& user_agent_override,
int render_frame_id) {
DVLOG(3) << "WebSocketHost::AddChannel"
<< " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
<< "\" requested_protocols=\""
<< base::JoinString(requested_protocols, ", ") << "\" origin=\""
- << origin << "\"";
+ << origin << "\" first_party_for_cookies=\""
+ << first_party_for_cookies << "\" user_agent_override=\""
+ << user_agent_override << "\"";
DCHECK(!channel_);
@@ -451,7 +461,20 @@ void WebSocketHost::AddChannel(
pending_flow_control_quota_ = 0;
}
- channel_->SendAddChannelRequest(socket_url, requested_protocols, origin);
+ std::string additional_headers;
+ if (user_agent_override != "") {
+ if (!net::HttpUtil::IsValidHeaderValue(user_agent_override)) {
+ bad_message::ReceivedBadMessage(
+ dispatcher_, bad_message::WSH_INVALID_HEADER_VALUE);
+ return;
+ }
+ additional_headers = base::StringPrintf("%s:%s",
+ net::HttpRequestHeaders::kUserAgent,
+ user_agent_override.c_str());
+ }
+ channel_->SendAddChannelRequest(
+ socket_url, requested_protocols, origin, first_party_for_cookies,
+ additional_headers);
// |this| may have been deleted here.
}
diff --git a/chromium/content/browser/renderer_host/websocket_host.h b/chromium/content/browser/renderer_host/websocket_host.h
index 626f6bea76e..3488ef06b52 100644
--- a/chromium/content/browser/renderer_host/websocket_host.h
+++ b/chromium/content/browser/renderer_host/websocket_host.h
@@ -18,6 +18,7 @@
#include "content/common/websocket.h"
class GURL;
+struct WebSocketHostMsg_AddChannelRequest_Params;
namespace url {
class Origin;
@@ -66,14 +67,14 @@ class CONTENT_EXPORT WebSocketHost {
// Handlers for each message type, dispatched by OnMessageReceived(), as
// defined in content/common/websocket_messages.h
- void OnAddChannelRequest(const GURL& socket_url,
- const std::vector<std::string>& requested_protocols,
- const url::Origin& origin,
- int render_frame_id);
+ void OnAddChannelRequest(
+ const WebSocketHostMsg_AddChannelRequest_Params& request);
void AddChannel(const GURL& socket_url,
const std::vector<std::string>& requested_protocols,
const url::Origin& origin,
+ const GURL& first_party_for_cookies,
+ const std::string& user_agent_override,
int render_frame_id);
void OnSendBlob(const std::string& uuid, uint64_t expected_size);
diff --git a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
index 43656c2a4e6..1a196086837 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
+++ b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -4,6 +4,8 @@
#include "content/browser/resolve_proxy_msg_helper.h"
+#include <tuple>
+
#include "base/memory/ptr_util.h"
#include "content/browser/browser_thread_impl.h"
#include "content/common/view_messages.h"
@@ -95,7 +97,7 @@ class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
EXPECT_TRUE(ViewHostMsg_ResolveProxy::ReadReplyParam(&msg, &reply_data));
DCHECK(!pending_result_.get());
pending_result_.reset(
- new PendingResult(base::get<0>(reply_data), base::get<1>(reply_data)));
+ new PendingResult(std::get<0>(reply_data), std::get<1>(reply_data)));
test_sink_.ClearMessages();
return true;
}
diff --git a/chromium/content/browser/resource_context_impl.cc b/chromium/content/browser/resource_context_impl.cc
index e7aa29b9570..cd1b684f13c 100644
--- a/chromium/content/browser/resource_context_impl.cc
+++ b/chromium/content/browser/resource_context_impl.cc
@@ -6,9 +6,11 @@
#include <stdint.h>
+#include "base/base64.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/rand_util.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -17,54 +19,27 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/keygen_handler.h"
-#include "net/ssl/client_cert_store.h"
using base::UserDataAdapter;
namespace content {
-namespace {
-
// Key names on ResourceContext.
const char kBlobStorageContextKeyName[] = "content_blob_storage_context";
const char kStreamContextKeyName[] = "content_stream_context";
const char kURLDataManagerBackendKeyName[] = "url_data_manager_backend";
-// Used by the default implementation of GetMediaDeviceIDSalt, below.
-std::string ReturnEmptySalt() {
- return std::string();
-}
-
-} // namespace
-
-
-ResourceContext::ResourceContext() {
- ResourceDispatcherHostImpl* rdhi = ResourceDispatcherHostImpl::Get();
- if (rdhi) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::AddResourceContext,
- base::Unretained(rdhi), this));
- }
+ResourceContext::ResourceContext()
+ : media_device_id_salt_(CreateRandomMediaDeviceIDSalt()) {
}
ResourceContext::~ResourceContext() {
- ResourceDispatcherHostImpl* rdhi = ResourceDispatcherHostImpl::Get();
- if (rdhi) {
- rdhi->CancelRequestsForContext(this);
- rdhi->RemoveResourceContext(this);
- }
-
- // In some tests this object is destructed on UI thread.
- DetachUserDataThread();
-}
-
-ResourceContext::SaltCallback ResourceContext::GetMediaDeviceIDSalt() {
- return base::Bind(&ReturnEmptySalt);
+ if (ResourceDispatcherHostImpl::Get())
+ ResourceDispatcherHostImpl::Get()->CancelRequestsForContext(this);
}
-std::unique_ptr<net::ClientCertStore> ResourceContext::CreateClientCertStore() {
- return std::unique_ptr<net::ClientCertStore>();
+std::string ResourceContext::GetMediaDeviceIDSalt() {
+ return media_device_id_salt_;
}
void ResourceContext::CreateKeygenHandler(
@@ -76,6 +51,14 @@ void ResourceContext::CreateKeygenHandler(
new net::KeygenHandler(key_size_in_bits, challenge_string, url)));
}
+// static
+std::string ResourceContext::CreateRandomMediaDeviceIDSalt() {
+ std::string salt;
+ base::Base64Encode(base::RandBytesAsString(16), &salt);
+ DCHECK(!salt.empty());
+ return salt;
+}
+
ChromeBlobStorageContext* GetChromeBlobStorageContextForResourceContext(
const ResourceContext* resource_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chromium/content/browser/resource_loading_browsertest.cc b/chromium/content/browser/resource_loading_browsertest.cc
index c68d577c958..b245ac16717 100644
--- a/chromium/content/browser/resource_loading_browsertest.cc
+++ b/chromium/content/browser/resource_loading_browsertest.cc
@@ -24,8 +24,8 @@ IN_PROC_BROWSER_TEST_F(ResourceLoadingBrowserTest,
GURL url = embedded_test_server()->GetURL(kResourceLoadingNonMobilePage);
NavigateToURL(shell(), url);
int data = -1;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(shell()->web_contents(),
- "getResourceNumber()", &data));
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractInt(shell(), "getResourceNumber()", &data));
EXPECT_EQ(2, data);
}
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
index 45710af63c2..cd6b6d21cc7 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
@@ -237,7 +237,7 @@ IN_PROC_BROWSER_TEST_F(ScreenOrientationLockDisabledBrowserTest,
navigation_observer.Wait();
{
- ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "run();"));
+ ASSERT_TRUE(ExecuteScript(shell(), "run();"));
TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
navigation_observer.Wait();
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index e225045e0a0..f9d6d7f935e 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -72,8 +72,7 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
// Open another window, so we generate some more routing ids.
ShellAddedObserver shell2_observer;
- EXPECT_TRUE(ExecuteScript(
- shell->web_contents(), "window.open(document.URL + '#2');"));
+ EXPECT_TRUE(ExecuteScript(shell, "window.open(document.URL + '#2');"));
Shell* shell2 = shell2_observer.GetShell();
// The new window must be in the same process, but have a new routing id.
@@ -88,8 +87,8 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
GURL extension_url("https://bar.com/simple_page.html");
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents());
wc->GetFrameTree()->root()->navigator()->RequestOpenURL(
- wc->GetFrameTree()->root()->current_frame_host(), extension_url, nullptr,
- Referrer(), CURRENT_TAB, false, true);
+ wc->GetFrameTree()->root()->current_frame_host(), extension_url, false,
+ nullptr, nullptr, Referrer(), 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
@@ -196,7 +195,7 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
}
protected:
- // Tests that a given file path sent in a ViewHostMsg_RunFileChooser will
+ // Tests that a given file path sent in a FrameHostMsg_RunFileChooser will
// cause renderer to be killed.
void TestFileChooserWithPath(const base::FilePath& path);
};
@@ -207,8 +206,8 @@ void SecurityExploitBrowserTest::TestFileChooserWithPath(
NavigateToURL(shell(), foo);
EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());
- RenderViewHost* compromised_renderer =
- shell()->web_contents()->GetRenderViewHost();
+ RenderFrameHost* compromised_renderer =
+ shell()->web_contents()->GetMainFrame();
RenderProcessHostWatcher terminated(
shell()->web_contents(),
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
@@ -216,7 +215,8 @@ void SecurityExploitBrowserTest::TestFileChooserWithPath(
FileChooserParams params;
params.default_file_name = path;
- ViewHostMsg_RunFileChooser evil(compromised_renderer->GetRoutingID(), params);
+ FrameHostMsg_RunFileChooser evil(compromised_renderer->GetRoutingID(),
+ params);
IpcSecurityTestUtil::PwnMessageReceived(
compromised_renderer->GetProcess()->GetChannel(), evil);
@@ -296,7 +296,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
}
// This is a test for crbug.com/444198. It tries to send a
-// ViewHostMsg_RunFileChooser containing an invalid path. The browser should
+// FrameHostMsg_RunFileChooser containing an invalid path. The browser should
// correctly terminate the renderer in these cases.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, AttemptRunFileChoosers) {
TestFileChooserWithPath(base::FilePath(FILE_PATH_LITERAL("../../*.txt")));
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index f6f46388362..a0c48cd25fc 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -14,9 +14,9 @@
#include "base/trace_event/trace_event.h"
#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/common/content_switches_internal.h"
-#include "content/common/mojo/service_registry_impl.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/embedded_worker_settings.h"
#include "content/common/service_worker/embedded_worker_setup.mojom.h"
@@ -26,6 +26,8 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/common/child_process_host.h"
#include "ipc/ipc_message.h"
+#include "services/shell/public/cpp/interface_provider.h"
+#include "services/shell/public/cpp/interface_registry.h"
#include "url/gurl.h"
namespace content {
@@ -102,17 +104,17 @@ void RegisterToWorkerDevToolsManagerOnUI(
void SetupMojoOnUIThread(
int process_id,
int thread_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtrInfo exposed_services) {
+ shell::mojom::InterfaceProviderRequest remote_interfaces,
+ shell::mojom::InterfaceProviderPtrInfo exposed_interfaces) {
RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
- // |rph| or its ServiceRegistry may be NULL in unit tests.
- if (!rph || !rph->GetServiceRegistry())
+ // |rph| or its InterfaceProvider may be NULL in unit tests.
+ if (!rph || !rph->GetRemoteInterfaces())
return;
mojom::EmbeddedWorkerSetupPtr setup;
- rph->GetServiceRegistry()->ConnectToRemoteService(mojo::GetProxy(&setup));
+ rph->GetRemoteInterfaces()->GetInterface(&setup);
setup->ExchangeInterfaceProviders(
- thread_id, std::move(services),
- mojo::MakeProxy(std::move(exposed_services)));
+ thread_id, std::move(remote_interfaces),
+ mojo::MakeProxy(std::move(exposed_interfaces)));
}
} // namespace
@@ -216,7 +218,7 @@ class EmbeddedWorkerInstance::StartTask {
: instance_(instance),
state_(ProcessAllocationState::NOT_ALLOCATED),
is_installed_(false),
- start_situation_(ServiceWorkerMetrics::StartSituation::UNKNOWN),
+ started_during_browser_startup_(false),
weak_factory_(this) {
TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "EmbeddedWorkerInstance::Start",
this, "Script", script_url.spec());
@@ -263,7 +265,7 @@ class EmbeddedWorkerInstance::StartTask {
is_installed_ = params->is_installed;
if (!GetContentClient()->browser()->IsBrowserStartupComplete())
- start_situation_ = ServiceWorkerMetrics::StartSituation::DURING_STARTUP;
+ started_during_browser_startup_ = true;
GURL scope(params->scope);
GURL script_url(params->script_url);
@@ -288,9 +290,6 @@ class EmbeddedWorkerInstance::StartTask {
}
bool is_installed() const { return is_installed_; }
- ServiceWorkerMetrics::StartSituation start_situation() const {
- return start_situation_;
- }
private:
void OnProcessAllocated(
@@ -319,19 +318,22 @@ class EmbeddedWorkerInstance::StartTask {
if (is_installed_)
ServiceWorkerMetrics::RecordProcessCreated(is_new_process);
- if (start_situation_ == ServiceWorkerMetrics::StartSituation::UNKNOWN) {
- if (is_new_process)
- start_situation_ = ServiceWorkerMetrics::StartSituation::NEW_PROCESS;
- else
- start_situation_ =
- ServiceWorkerMetrics::StartSituation::EXISTING_PROCESS;
- }
+ ServiceWorkerMetrics::StartSituation start_situation =
+ ServiceWorkerMetrics::StartSituation::UNKNOWN;
+ if (started_during_browser_startup_)
+ start_situation = ServiceWorkerMetrics::StartSituation::DURING_STARTUP;
+ else if (is_new_process)
+ start_situation = ServiceWorkerMetrics::StartSituation::NEW_PROCESS;
+ else
+ start_situation = ServiceWorkerMetrics::StartSituation::EXISTING_PROCESS;
// Notify the instance that a process is allocated.
state_ = ProcessAllocationState::ALLOCATED;
- instance_->OnProcessAllocated(base::WrapUnique(new WorkerProcessHandle(
- instance_->context_, instance_->embedded_worker_id(), process_id,
- is_new_process)));
+ instance_->OnProcessAllocated(
+ base::WrapUnique(new WorkerProcessHandle(
+ instance_->context_, instance_->embedded_worker_id(), process_id,
+ is_new_process)),
+ start_situation);
// TODO(bengr): Support changes to this setting while the worker
// is running.
@@ -399,7 +401,7 @@ class EmbeddedWorkerInstance::StartTask {
// Used for UMA.
bool is_installed_;
- ServiceWorkerMetrics::StartSituation start_situation_;
+ bool started_during_browser_startup_;
base::WeakPtrFactory<StartTask> weak_factory_;
@@ -412,7 +414,9 @@ bool EmbeddedWorkerInstance::Listener::OnMessageReceived(
}
EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
- DCHECK(status_ == STOPPING || status_ == STOPPED) << status_;
+ DCHECK(status_ == EmbeddedWorkerStatus::STOPPING ||
+ status_ == EmbeddedWorkerStatus::STOPPED)
+ << static_cast<int>(status_);
devtools_proxy_.reset();
if (registry_->GetWorker(embedded_worker_id_))
registry_->RemoveWorker(process_id(), embedded_worker_id_);
@@ -427,15 +431,16 @@ void EmbeddedWorkerInstance::Start(
// |this| may be destroyed by the callback.
return;
}
- DCHECK(status_ == STOPPED);
+ DCHECK(status_ == EmbeddedWorkerStatus::STOPPED);
DCHECK(!params->pause_after_download || !params->is_installed);
DCHECK_NE(kInvalidServiceWorkerVersionId, params->service_worker_version_id);
step_time_ = base::TimeTicks::Now();
- status_ = STARTING;
+ status_ = EmbeddedWorkerStatus::STARTING;
starting_phase_ = ALLOCATING_PROCESS;
network_accessed_for_script_ = false;
- service_registry_.reset(new ServiceRegistryImpl());
+ interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+ remote_interfaces_.reset(new shell::InterfaceProvider);
FOR_EACH_OBSERVER(Listener, listener_list_, OnStarting());
params->embedded_worker_id = embedded_worker_id_;
@@ -448,7 +453,9 @@ void EmbeddedWorkerInstance::Start(
}
ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() {
- DCHECK(status_ == STARTING || status_ == RUNNING) << status_;
+ DCHECK(status_ == EmbeddedWorkerStatus::STARTING ||
+ status_ == EmbeddedWorkerStatus::RUNNING)
+ << static_cast<int>(status_);
// Abort an inflight start task.
inflight_start_task_.reset();
@@ -464,7 +471,7 @@ ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() {
return status;
}
- status_ = STOPPING;
+ status_ = EmbeddedWorkerStatus::STOPPING;
FOR_EACH_OBSERVER(Listener, listener_list_, OnStopping());
return status;
}
@@ -481,23 +488,36 @@ void EmbeddedWorkerInstance::StopIfIdle() {
ServiceWorkerStatusCode EmbeddedWorkerInstance::SendMessage(
const IPC::Message& message) {
DCHECK_NE(kInvalidEmbeddedWorkerThreadId, thread_id_);
- if (status_ != RUNNING && status_ != STARTING)
+ if (status_ != EmbeddedWorkerStatus::RUNNING &&
+ status_ != EmbeddedWorkerStatus::STARTING) {
return SERVICE_WORKER_ERROR_IPC_FAILED;
+ }
return registry_->Send(process_id(),
new EmbeddedWorkerContextMsg_MessageToWorker(
thread_id_, embedded_worker_id_, message));
}
void EmbeddedWorkerInstance::ResumeAfterDownload() {
- if (process_id() == ChildProcessHost::kInvalidUniqueID || status_ != STARTING)
+ if (process_id() == ChildProcessHost::kInvalidUniqueID ||
+ status_ != EmbeddedWorkerStatus::STARTING) {
return;
+ }
registry_->Send(process_id(), new EmbeddedWorkerMsg_ResumeAfterDownload(
embedded_worker_id_));
}
-ServiceRegistry* EmbeddedWorkerInstance::GetServiceRegistry() {
- DCHECK(status_ == STARTING || status_ == RUNNING) << status_;
- return service_registry_.get();
+shell::InterfaceRegistry* EmbeddedWorkerInstance::GetInterfaceRegistry() {
+ DCHECK(status_ == EmbeddedWorkerStatus::STARTING ||
+ status_ == EmbeddedWorkerStatus::RUNNING)
+ << static_cast<int>(status_);
+ return interface_registry_.get();
+}
+
+shell::InterfaceProvider* EmbeddedWorkerInstance::GetRemoteInterfaces() {
+ DCHECK(status_ == EmbeddedWorkerStatus::STARTING ||
+ status_ == EmbeddedWorkerStatus::RUNNING)
+ << static_cast<int>(status_);
+ return remote_interfaces_.get();
}
EmbeddedWorkerInstance::EmbeddedWorkerInstance(
@@ -506,7 +526,7 @@ EmbeddedWorkerInstance::EmbeddedWorkerInstance(
: context_(context),
registry_(context->embedded_worker_registry()),
embedded_worker_id_(embedded_worker_id),
- status_(STOPPED),
+ status_(EmbeddedWorkerStatus::STOPPED),
starting_phase_(NOT_STARTING),
thread_id_(kInvalidEmbeddedWorkerThreadId),
devtools_attached_(false),
@@ -514,12 +534,14 @@ EmbeddedWorkerInstance::EmbeddedWorkerInstance(
weak_factory_(this) {}
void EmbeddedWorkerInstance::OnProcessAllocated(
- std::unique_ptr<WorkerProcessHandle> handle) {
- DCHECK_EQ(STARTING, status_);
+ std::unique_ptr<WorkerProcessHandle> handle,
+ ServiceWorkerMetrics::StartSituation start_situation) {
+ DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status_);
DCHECK(!process_handle_);
process_handle_ = std::move(handle);
starting_phase_ = REGISTERING_TO_DEVTOOLS;
+ start_situation_ = start_situation;
FOR_EACH_OBSERVER(Listener, listener_list_, OnProcessAllocated());
}
@@ -543,8 +565,8 @@ void EmbeddedWorkerInstance::OnStartWorkerMessageSent() {
if (!step_time_.is_null()) {
base::TimeDelta duration = UpdateStepTime();
if (inflight_start_task_->is_installed()) {
- ServiceWorkerMetrics::RecordTimeToSendStartWorker(
- duration, inflight_start_task_->start_situation());
+ ServiceWorkerMetrics::RecordTimeToSendStartWorker(duration,
+ start_situation_);
}
}
@@ -586,8 +608,7 @@ void EmbeddedWorkerInstance::OnScriptLoaded() {
if (!step_time_.is_null()) {
base::TimeDelta duration = UpdateStepTime();
- ServiceWorkerMetrics::RecordTimeToLoad(
- duration, source, inflight_start_task_->start_situation());
+ ServiceWorkerMetrics::RecordTimeToLoad(duration, source, start_situation_);
}
starting_phase_ = SCRIPT_LOADED;
@@ -603,8 +624,7 @@ void EmbeddedWorkerInstance::OnURLJobCreatedForMainScript() {
if (!step_time_.is_null()) {
base::TimeDelta duration = UpdateStepTime();
if (inflight_start_task_->is_installed())
- ServiceWorkerMetrics::RecordTimeToURLJob(
- duration, inflight_start_task_->start_situation());
+ ServiceWorkerMetrics::RecordTimeToURLJob(duration, start_situation_);
}
}
@@ -628,23 +648,22 @@ void EmbeddedWorkerInstance::OnThreadStarted(int thread_id) {
if (!step_time_.is_null()) {
base::TimeDelta duration = UpdateStepTime();
if (inflight_start_task_->is_installed())
- ServiceWorkerMetrics::RecordTimeToStartThread(
- duration, inflight_start_task_->start_situation());
+ ServiceWorkerMetrics::RecordTimeToStartThread(duration, start_situation_);
}
thread_id_ = thread_id;
FOR_EACH_OBSERVER(Listener, listener_list_, OnThreadStarted());
- shell::mojom::InterfaceProviderPtr exposed_services;
- service_registry_->Bind(GetProxy(&exposed_services));
- shell::mojom::InterfaceProviderPtr services;
- shell::mojom::InterfaceProviderRequest services_request = GetProxy(&services);
+ shell::mojom::InterfaceProviderPtr exposed_interfaces;
+ interface_registry_->Bind(GetProxy(&exposed_interfaces));
+ shell::mojom::InterfaceProviderPtr remote_interfaces;
+ shell::mojom::InterfaceProviderRequest request = 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(&services_request),
- base::Passed(exposed_services.PassInterface())));
- service_registry_->BindRemoteServiceProvider(std::move(services));
+ base::Passed(&request),
+ base::Passed(exposed_interfaces.PassInterface())));
}
void EmbeddedWorkerInstance::OnScriptLoadFailed() {
@@ -659,7 +678,7 @@ void EmbeddedWorkerInstance::OnScriptLoadFailed() {
void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
if (!inflight_start_task_)
return;
- DCHECK_EQ(STARTING, status_);
+ DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status_);
TRACE_EVENT_ASYNC_STEP_PAST1("ServiceWorker", "EmbeddedWorkerInstance::Start",
inflight_start_task_.get(), "OnScriptEvaluated",
@@ -668,8 +687,8 @@ void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
if (!step_time_.is_null()) {
base::TimeDelta duration = UpdateStepTime();
if (success && inflight_start_task_->is_installed())
- ServiceWorkerMetrics::RecordTimeToEvaluateScript(
- duration, inflight_start_task_->start_situation());
+ ServiceWorkerMetrics::RecordTimeToEvaluateScript(duration,
+ start_situation_);
}
base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr();
@@ -682,22 +701,22 @@ void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
void EmbeddedWorkerInstance::OnStarted() {
// Stop is requested before OnStarted is sent back from the worker.
- if (status_ == STOPPING)
+ if (status_ == EmbeddedWorkerStatus::STOPPING)
return;
- DCHECK(status_ == STARTING);
- status_ = RUNNING;
+ DCHECK(status_ == EmbeddedWorkerStatus::STARTING);
+ status_ = EmbeddedWorkerStatus::RUNNING;
inflight_start_task_.reset();
FOR_EACH_OBSERVER(Listener, listener_list_, OnStarted());
}
void EmbeddedWorkerInstance::OnStopped() {
- Status old_status = status_;
+ EmbeddedWorkerStatus old_status = status_;
ReleaseProcess();
FOR_EACH_OBSERVER(Listener, listener_list_, OnStopped(old_status));
}
void EmbeddedWorkerInstance::OnDetached() {
- Status old_status = status_;
+ EmbeddedWorkerStatus old_status = status_;
ReleaseProcess();
FOR_EACH_OBSERVER(Listener, listener_list_, OnDetached(old_status));
}
@@ -785,18 +804,19 @@ void EmbeddedWorkerInstance::ReleaseProcess() {
devtools_proxy_.reset();
process_handle_.reset();
- status_ = STOPPED;
+ status_ = EmbeddedWorkerStatus::STOPPED;
thread_id_ = kInvalidEmbeddedWorkerThreadId;
- service_registry_.reset();
+ interface_registry_.reset();
+ remote_interfaces_.reset();
}
void EmbeddedWorkerInstance::OnStartFailed(const StatusCallback& callback,
ServiceWorkerStatusCode status) {
- Status old_status = status_;
+ EmbeddedWorkerStatus old_status = status_;
ReleaseProcess();
base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr();
callback.Run(status);
- if (weak_this && old_status != STOPPED)
+ if (weak_this && old_status != EmbeddedWorkerStatus::STOPPED)
FOR_EACH_OBSERVER(Listener, weak_this->listener_list_,
OnStopped(old_status));
}
@@ -812,25 +832,28 @@ base::TimeDelta EmbeddedWorkerInstance::UpdateStepTime() {
void EmbeddedWorkerInstance::AddMessageToConsole(ConsoleMessageLevel level,
const std::string& message) {
- if (status_ != RUNNING && status_ != STARTING)
+ if (status_ != EmbeddedWorkerStatus::RUNNING &&
+ status_ != EmbeddedWorkerStatus::STARTING) {
return;
+ }
registry_->Send(process_id(), new EmbeddedWorkerMsg_AddMessageToConsole(
embedded_worker_id_, level, message));
}
// static
-std::string EmbeddedWorkerInstance::StatusToString(Status status) {
+std::string EmbeddedWorkerInstance::StatusToString(
+ EmbeddedWorkerStatus status) {
switch (status) {
- case STOPPED:
+ case EmbeddedWorkerStatus::STOPPED:
return "STOPPED";
- case STARTING:
+ case EmbeddedWorkerStatus::STARTING:
return "STARTING";
- case RUNNING:
+ case EmbeddedWorkerStatus::RUNNING:
return "RUNNING";
- case STOPPING:
+ case EmbeddedWorkerStatus::STOPPING:
return "STOPPING";
}
- NOTREACHED() << status;
+ NOTREACHED() << static_cast<int>(status);
return std::string();
}
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 9356bb531f0..b0b0da93138 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -20,6 +20,7 @@
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
@@ -37,12 +38,15 @@ namespace IPC {
class Message;
}
+namespace shell {
+class InterfaceProvider;
+class InterfaceRegistry;
+}
+
namespace content {
class EmbeddedWorkerRegistry;
class MessagePortMessageFilter;
-class ServiceRegistry;
-class ServiceRegistryImpl;
class ServiceWorkerContextCore;
// This gives an interface to control one EmbeddedWorker instance, which
@@ -51,12 +55,6 @@ class ServiceWorkerContextCore;
class CONTENT_EXPORT EmbeddedWorkerInstance {
public:
typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
- enum Status {
- STOPPED,
- STARTING,
- RUNNING,
- STOPPING,
- };
// This enum is used in UMA histograms. Append-only.
enum StartingPhase {
@@ -88,9 +86,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
virtual void OnStopping() {}
// Received ACK from renderer that the worker context terminated.
- virtual void OnStopped(Status old_status) {}
+ virtual void OnStopped(EmbeddedWorkerStatus old_status) {}
// The browser-side IPC endpoint for communication with the worker died.
- virtual void OnDetached(Status old_status) {}
+ virtual void OnDetached(EmbeddedWorkerStatus old_status) {}
virtual void OnScriptLoaded() {}
virtual void OnScriptLoadFailed() {}
virtual void OnReportException(const base::string16& error_message,
@@ -135,14 +133,16 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
// Resumes the worker if it paused after download.
void ResumeAfterDownload();
- // Returns the ServiceRegistry for this worker. It is invalid to call this
- // when the worker is not in STARTING or RUNNING status.
- ServiceRegistry* GetServiceRegistry();
+ // Returns the shell::InterfaceRegistry and shell::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();
int embedded_worker_id() const { return embedded_worker_id_; }
- Status status() const { return status_; }
+ EmbeddedWorkerStatus status() const { return status_; }
StartingPhase starting_phase() const {
- DCHECK_EQ(STARTING, status());
+ DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status());
return starting_phase_;
}
int process_id() const;
@@ -163,6 +163,12 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
return network_accessed_for_script_;
}
+ ServiceWorkerMetrics::StartSituation start_situation() const {
+ DCHECK(status() == EmbeddedWorkerStatus::STARTING ||
+ status() == EmbeddedWorkerStatus::RUNNING);
+ return start_situation_;
+ }
+
// Called when the main script load accessed the network.
void OnNetworkAccessedForScriptLoad();
@@ -185,7 +191,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
void AddMessageToConsole(ConsoleMessageLevel level,
const std::string& message);
- static std::string StatusToString(Status status);
+ static std::string StatusToString(EmbeddedWorkerStatus status);
static std::string StartingPhaseToString(StartingPhase phase);
void Detach();
@@ -208,7 +214,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
int embedded_worker_id);
// Called back from StartTask after a process is allocated on the UI thread.
- void OnProcessAllocated(std::unique_ptr<WorkerProcessHandle> handle);
+ void OnProcessAllocated(std::unique_ptr<WorkerProcessHandle> handle,
+ ServiceWorkerMetrics::StartSituation start_situation);
// Called back from StartTask after the worker is registered to
// WorkerDevToolsManager.
@@ -289,13 +296,14 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
base::WeakPtr<ServiceWorkerContextCore> context_;
scoped_refptr<EmbeddedWorkerRegistry> registry_;
const int embedded_worker_id_;
- Status status_;
+ EmbeddedWorkerStatus status_;
StartingPhase starting_phase_;
// Current running information.
std::unique_ptr<EmbeddedWorkerInstance::WorkerProcessHandle> process_handle_;
int thread_id_;
- std::unique_ptr<ServiceRegistryImpl> service_registry_;
+ std::unique_ptr<shell::InterfaceRegistry> interface_registry_;
+ std::unique_ptr<shell::InterfaceProvider> remote_interfaces_;
// Whether devtools is attached or not.
bool devtools_attached_;
@@ -309,6 +317,10 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
std::unique_ptr<StartTask> inflight_start_task_;
+ // This is valid only after a process is allocated for the worker.
+ ServiceWorkerMetrics::StartSituation start_situation_ =
+ ServiceWorkerMetrics::StartSituation::UNKNOWN;
+
// Used for UMA. The start time of the current start sequence step.
base::TimeTicks step_time_;
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 62e1ce66f6d..f2df6b57612 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -12,6 +12,7 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -61,12 +62,12 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
struct EventLog {
EventType type;
- EmbeddedWorkerInstance::Status status;
+ EmbeddedWorkerStatus status;
};
void RecordEvent(
EventType type,
- EmbeddedWorkerInstance::Status status = EmbeddedWorkerInstance::STOPPED) {
+ EmbeddedWorkerStatus status = EmbeddedWorkerStatus::STOPPED) {
EventLog log = {type, status};
events_.push_back(log);
}
@@ -76,10 +77,10 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
RecordEvent(START_WORKER_MESSAGE_SENT);
}
void OnStarted() override { RecordEvent(STARTED); }
- void OnStopped(EmbeddedWorkerInstance::Status old_status) override {
+ void OnStopped(EmbeddedWorkerStatus old_status) override {
RecordEvent(STOPPED, old_status);
}
- void OnDetached(EmbeddedWorkerInstance::Status old_status) override {
+ void OnDetached(EmbeddedWorkerStatus old_status) override {
RecordEvent(DETACHED, old_status);
}
@@ -164,7 +165,7 @@ class FailToSendIPCHelper : public EmbeddedWorkerTestHelper {
TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
const int64_t service_worker_version_id = 55L;
const GURL pattern("http://example.com/");
@@ -181,23 +182,23 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
CreateStartParams(service_worker_version_id, pattern, url);
worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
run_loop.QuitClosure()));
- EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
run_loop.Run();
EXPECT_EQ(SERVICE_WORKER_OK, status);
// The 'WorkerStarted' message should have been sent by
// EmbeddedWorkerTestHelper.
- EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
// Stop the worker.
EXPECT_EQ(SERVICE_WORKER_OK, worker->Stop());
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, worker->status());
base::RunLoop().RunUntilIdle();
// The 'WorkerStopped' message should have been sent by
// EmbeddedWorkerTestHelper.
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
// Verify that we've sent two messages to start and terminate the worker.
ASSERT_TRUE(
@@ -211,7 +212,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
const int64_t service_worker_version_id = 55L;
const GURL pattern("http://example.com/");
@@ -238,7 +239,7 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
// The worker should be using the default render process.
EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
@@ -260,11 +261,11 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
CreateStartParams(service_worker_version_id, pattern, url));
worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
run_loop.QuitClosure()));
- EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
run_loop.Run();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
// The worker should be using the new render process.
EXPECT_EQ(helper_->new_render_process_id(), worker->process_id());
EXPECT_EQ(SERVICE_WORKER_OK, worker->Stop());
@@ -275,7 +276,7 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
const int64_t service_worker_version_id = 55L;
const GURL pattern("http://example.com/");
@@ -288,33 +289,33 @@ TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
// Start the worker and then call StopIfIdle().
EXPECT_EQ(SERVICE_WORKER_OK,
StartWorker(worker.get(), service_worker_version_id, pattern, url));
- EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
worker->StopIfIdle();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, worker->status());
base::RunLoop().RunUntilIdle();
// The worker must be stopped now.
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
// Set devtools_attached to true, and do the same.
worker->set_devtools_attached(true);
EXPECT_EQ(SERVICE_WORKER_OK,
StartWorker(worker.get(), service_worker_version_id, pattern, url));
- EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
worker->StopIfIdle();
base::RunLoop().RunUntilIdle();
// The worker must not be stopped this time.
- EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
// Calling Stop() actually stops the worker regardless of whether devtools
// is attached or not.
EXPECT_EQ(SERVICE_WORKER_OK, worker->Stop());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
}
// Test that the removal of a worker from the registry doesn't remove
@@ -392,7 +393,7 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
worker->Detach();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
// The start callback should not be aborted by detach (see a comment on the
@@ -402,7 +403,7 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
// "PROCESS_ALLOCATED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
EXPECT_EQ(DETACHED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerInstance::STARTING, events_[0].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
}
TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
@@ -431,7 +432,7 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
worker->Detach();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
// The start callback should not be aborted by detach (see a comment on the
@@ -441,7 +442,7 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
// "STARTED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
EXPECT_EQ(DETACHED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerInstance::STARTING, events_[0].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
}
TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
@@ -463,7 +464,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
worker->Stop();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
// The start callback should not be aborted by stop (see a comment on the dtor
@@ -473,7 +474,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
// "PROCESS_ALLOCATED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
EXPECT_EQ(DETACHED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerInstance::STARTING, events_[0].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
events_.clear();
// Restart the worker.
@@ -520,7 +521,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
base::RunLoop().RunUntilIdle();
// The resume after download message should not have been sent.
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
EXPECT_FALSE(ipc_sink()->GetFirstMessageMatching(
EmbeddedWorkerMsg_ResumeAfterDownload::ID));
}
@@ -551,7 +552,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
worker->Stop();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, worker->process_id());
// The start callback should not be aborted by stop (see a comment on the dtor
@@ -561,7 +562,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
// "STARTED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
EXPECT_EQ(STOPPED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, events_[0].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, events_[0].status);
events_.clear();
// Restart the worker.
@@ -608,13 +609,13 @@ TEST_F(EmbeddedWorkerInstanceTest, Detach) {
// Detach.
int process_id = worker->process_id();
worker->Detach();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
// Send the registry a message from the detached worker. Nothing should
// happen.
embedded_worker_registry()->OnWorkerStarted(process_id,
worker->embedded_worker_id());
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
}
// Test for when sending the start IPC failed.
@@ -645,7 +646,7 @@ TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
ASSERT_EQ(2u, events_.size());
EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
EXPECT_EQ(STOPPED, events_[1].type);
- EXPECT_EQ(EmbeddedWorkerInstance::STARTING, events_[1].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[1].status);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.cc b/chromium/content/browser/service_worker/embedded_worker_registry.cc
index 70f2d9ef048..f0031c5ec9b 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.cc
@@ -61,7 +61,14 @@ bool EmbeddedWorkerRegistry::OnMessageReceived(const IPC::Message& message,
// purposely handling the message as no-op.
return true;
}
- return worker->OnMessageReceived(message);
+ bool handled = worker->OnMessageReceived(message);
+
+ // Assume an unhandled message for a stopping worker is because the message
+ // was timed out and its handler removed prior to stopping.
+ // We might be more precise and record timed out request ids, but some
+ // cumbersome bookkeeping is needed and the IPC messaging will soon migrate
+ // to Mojo anyway.
+ return handled || worker->status() == EmbeddedWorkerStatus::STOPPING;
}
void EmbeddedWorkerRegistry::Shutdown() {
diff --git a/chromium/content/browser/service_worker/embedded_worker_status.h b/chromium/content/browser/service_worker/embedded_worker_status.h
new file mode 100644
index 00000000000..f6bc13a7780
--- /dev/null
+++ b/chromium/content/browser/service_worker/embedded_worker_status.h
@@ -0,0 +1,19 @@
+// 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_SERVICE_WORKER_EMBEDDED_WORKER_STATUS_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_STATUS_H_
+
+namespace content {
+
+enum class EmbeddedWorkerStatus {
+ STOPPED,
+ STARTING,
+ RUNNING,
+ STOPPING,
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_STATUS_H_
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 adb88e7bab5..7f170a5e694 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -15,6 +15,7 @@
#include "content/browser/message_port_message_filter.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/embedded_worker_messages.h"
@@ -23,7 +24,10 @@
#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 "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -61,12 +65,12 @@ class EmbeddedWorkerTestHelper::MockEmbeddedWorkerSetup
void ExchangeInterfaceProviders(
int32_t thread_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services) override {
+ shell::mojom::InterfaceProviderRequest request,
+ shell::mojom::InterfaceProviderPtr remote_interfaces) override {
if (!helper_)
return;
- helper_->OnSetupMojoStub(thread_id, std::move(services),
- std::move(exposed_services));
+ helper_->OnSetupMojoStub(thread_id, std::move(request),
+ std::move(remote_interfaces));
}
private:
@@ -97,15 +101,21 @@ EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
registry()->AddChildProcessSender(mock_render_process_id_, this,
NewMessagePortMessageFilter());
- // Setup process level mojo service registry pair.
- std::unique_ptr<ServiceRegistryImpl> host_service_registry(
- new ServiceRegistryImpl);
- render_process_service_registry_.ServiceRegistry::AddService(
+ // Setup process level interface registry.
+ render_process_interface_registry_.reset(
+ new shell::InterfaceRegistry(nullptr));
+ render_process_interface_registry_->AddInterface(
base::Bind(&MockEmbeddedWorkerSetup::Create, weak_factory_.GetWeakPtr()));
- shell::mojom::InterfaceProviderPtr services;
- render_process_service_registry_.Bind(mojo::GetProxy(&services));
- host_service_registry->BindRemoteServiceProvider(std::move(services));
- render_process_host_->SetServiceRegistry(std::move(host_service_registry));
+ shell::mojom::InterfaceProviderPtr interfaces;
+ render_process_interface_registry_->Bind(mojo::GetProxy(&interfaces));
+
+ std::unique_ptr<shell::InterfaceProvider> host_remote_interfaces(
+ new shell::InterfaceProvider);
+ host_remote_interfaces->Bind(std::move(interfaces));
+ std::unique_ptr<shell::InterfaceRegistry> host_registry(
+ new shell::InterfaceRegistry(nullptr));
+ render_process_host_->SetInterfaceRegistry(std::move(host_registry));
+ render_process_host_->SetRemoteInterfaces(std::move(host_remote_interfaces));
}
EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
@@ -113,13 +123,12 @@ EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
wrapper_->Shutdown();
}
-void EmbeddedWorkerTestHelper::SimulateAddProcessToPattern(
- const GURL& pattern,
- int process_id) {
+void EmbeddedWorkerTestHelper::SimulateAddProcessToPattern(const GURL& pattern,
+ int process_id) {
registry()->AddChildProcessSender(process_id, this,
NewMessagePortMessageFilter());
- wrapper_->process_manager()->AddProcessReferenceToPattern(
- pattern, process_id);
+ wrapper_->process_manager()->AddProcessReferenceToPattern(pattern,
+ process_id);
}
bool EmbeddedWorkerTestHelper::Send(IPC::Message* message) {
@@ -181,10 +190,9 @@ void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id) {
SimulateWorkerStopped(embedded_worker_id);
}
-bool EmbeddedWorkerTestHelper::OnMessageToWorker(
- int thread_id,
- int embedded_worker_id,
- const IPC::Message& message) {
+bool EmbeddedWorkerTestHelper::OnMessageToWorker(int thread_id,
+ int embedded_worker_id,
+ const IPC::Message& message) {
bool handled = true;
current_embedded_worker_id_ = embedded_worker_id;
IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper, message)
@@ -201,14 +209,14 @@ bool EmbeddedWorkerTestHelper::OnMessageToWorker(
return handled;
}
-void EmbeddedWorkerTestHelper::OnSetupMojo(ServiceRegistry* service_registry) {}
+void EmbeddedWorkerTestHelper::OnSetupMojo(
+ shell::InterfaceRegistry* interface_registry) {}
void EmbeddedWorkerTestHelper::OnActivateEvent(int embedded_worker_id,
int request_id) {
- SimulateSend(
- new ServiceWorkerHostMsg_ActivateEventFinished(
- embedded_worker_id, request_id,
- blink::WebServiceWorkerEventResultCompleted));
+ SimulateSend(new ServiceWorkerHostMsg_ActivateEventFinished(
+ embedded_worker_id, request_id,
+ blink::WebServiceWorkerEventResultCompleted));
}
void EmbeddedWorkerTestHelper::OnExtendableMessageEvent(int embedded_worker_id,
@@ -223,25 +231,29 @@ void EmbeddedWorkerTestHelper::OnInstallEvent(int embedded_worker_id,
// The installing worker may have been doomed and terminated.
if (!registry()->GetWorker(embedded_worker_id))
return;
- SimulateSend(
- new ServiceWorkerHostMsg_InstallEventFinished(
- embedded_worker_id, request_id,
- blink::WebServiceWorkerEventResultCompleted));
+ SimulateSend(new ServiceWorkerHostMsg_InstallEventFinished(
+ embedded_worker_id, request_id,
+ blink::WebServiceWorkerEventResultCompleted, true));
}
void EmbeddedWorkerTestHelper::OnFetchEvent(
int embedded_worker_id,
- int request_id,
+ int response_id,
+ int event_finish_id,
const ServiceWorkerFetchRequest& request) {
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id, request_id,
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
+ embedded_worker_id, response_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
- ServiceWorkerResponse(GURL(), 200, "OK",
- blink::WebServiceWorkerResponseTypeDefault,
- ServiceWorkerHeaderMap(), std::string(), 0, GURL(),
- blink::WebServiceWorkerResponseErrorUnknown,
- base::Time(), false /* is_in_cache_storage */,
- std::string() /* cache_storage_cache_name */)));
+ ServiceWorkerResponse(
+ GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
+ ServiceWorkerHeaderMap(), std::string(), 0, GURL(),
+ blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* is_in_cache_storage */,
+ std::string() /* cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */)));
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
+ embedded_worker_id, event_finish_id,
+ blink::WebServiceWorkerEventResultCompleted));
}
void EmbeddedWorkerTestHelper::OnPushEvent(int embedded_worker_id,
@@ -301,24 +313,19 @@ void EmbeddedWorkerTestHelper::SimulateWorkerScriptEvaluated(
success);
}
-void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
- int embedded_worker_id) {
+void EmbeddedWorkerTestHelper::SimulateWorkerStarted(int embedded_worker_id) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker != NULL);
- registry()->OnWorkerStarted(
- worker->process_id(),
- embedded_worker_id);
+ registry()->OnWorkerStarted(worker->process_id(), embedded_worker_id);
}
-void EmbeddedWorkerTestHelper::SimulateWorkerStopped(
- int embedded_worker_id) {
+void EmbeddedWorkerTestHelper::SimulateWorkerStopped(int embedded_worker_id) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
if (worker != NULL)
registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
}
-void EmbeddedWorkerTestHelper::SimulateSend(
- IPC::Message* message) {
+void EmbeddedWorkerTestHelper::SimulateSend(IPC::Message* message) {
registry()->OnMessageReceived(*message, mock_render_process_id_);
delete message;
}
@@ -328,7 +335,7 @@ void EmbeddedWorkerTestHelper::OnStartWorkerStub(
EmbeddedWorkerInstance* worker =
registry()->GetWorker(params.embedded_worker_id);
ASSERT_TRUE(worker != NULL);
- EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker,
@@ -350,10 +357,8 @@ void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker != NULL);
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnStopWorker,
- weak_factory_.GetWeakPtr(),
- embedded_worker_id));
+ FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnStopWorker,
+ weak_factory_.GetWeakPtr(), embedded_worker_id));
}
void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
@@ -367,10 +372,7 @@ void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
FROM_HERE,
base::Bind(
base::IgnoreResult(&EmbeddedWorkerTestHelper::OnMessageToWorker),
- weak_factory_.GetWeakPtr(),
- thread_id,
- embedded_worker_id,
- message));
+ weak_factory_.GetWeakPtr(), thread_id, embedded_worker_id, message));
}
void EmbeddedWorkerTestHelper::OnActivateEventStub(int request_id) {
@@ -391,23 +393,20 @@ void EmbeddedWorkerTestHelper::OnExtendableMessageEventStub(
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,
+ weak_factory_.GetWeakPtr(),
+ current_embedded_worker_id_, request_id));
}
void EmbeddedWorkerTestHelper::OnFetchEventStub(
- int request_id,
+ int response_id,
+ int event_finish_id,
const ServiceWorkerFetchRequest& request) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&EmbeddedWorkerTestHelper::OnFetchEvent,
- weak_factory_.GetWeakPtr(),
- current_embedded_worker_id_,
- request_id,
- request));
+ weak_factory_.GetWeakPtr(), current_embedded_worker_id_,
+ response_id, event_finish_id, request));
}
void EmbeddedWorkerTestHelper::OnPushEventStub(
@@ -421,13 +420,19 @@ void EmbeddedWorkerTestHelper::OnPushEventStub(
void EmbeddedWorkerTestHelper::OnSetupMojoStub(
int thread_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services) {
- std::unique_ptr<ServiceRegistryImpl> new_registry(new ServiceRegistryImpl);
- new_registry->Bind(std::move(services));
- new_registry->BindRemoteServiceProvider(std::move(exposed_services));
- OnSetupMojo(new_registry.get());
- thread_id_service_registry_map_.add(thread_id, std::move(new_registry));
+ shell::mojom::InterfaceProviderRequest request,
+ shell::mojom::InterfaceProviderPtr remote_interfaces) {
+ std::unique_ptr<shell::InterfaceRegistry> local(
+ new shell::InterfaceRegistry(nullptr));
+ local->Bind(std::move(request));
+
+ std::unique_ptr<shell::InterfaceProvider> remote(
+ new shell::InterfaceProvider);
+ remote->Bind(std::move(remote_interfaces));
+
+ OnSetupMojo(local.get());
+ InterfaceRegistryAndProvider pair(std::move(local), std::move(remote));
+ thread_id_service_registry_map_[thread_id] = std::move(pair);
}
EmbeddedWorkerRegistry* EmbeddedWorkerTestHelper::registry() {
diff --git a/chromium/content/browser/service_worker/embedded_worker_test_helper.h b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
index ba45120cb48..88bf11bee43 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -12,12 +12,12 @@
#include <vector>
#include "base/callback.h"
-#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "content/common/mojo/service_registry_impl.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_test_sink.h"
+#include "services/shell/public/interfaces/interface_provider.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -25,6 +25,11 @@ class GURL;
struct EmbeddedWorkerMsg_StartWorker_Params;
struct ServiceWorkerMsg_ExtendableMessageEvent_Params;
+namespace shell {
+class InterfaceProvider;
+class InterfaceRegistry;
+}
+
namespace content {
class EmbeddedWorkerRegistry;
@@ -115,8 +120,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
const IPC::Message& message);
// Called to setup mojo for a new embedded worker. Override to register
- // services the worker should expose to the browser.
- virtual void OnSetupMojo(ServiceRegistry* service_registry);
+ // interfaces the worker should expose to the browser.
+ virtual void OnSetupMojo(shell::InterfaceRegistry* interface_registry);
// On*Event handlers. Called by the default implementation of
// OnMessageToWorker when events are sent to the embedded
@@ -126,7 +131,8 @@ 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 request_id,
+ int response_id,
+ int event_finish_id,
const ServiceWorkerFetchRequest& request);
virtual void OnPushEvent(int embedded_worker_id,
int request_id,
@@ -146,6 +152,10 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
EmbeddedWorkerRegistry* registry();
private:
+ using InterfaceRegistryAndProvider =
+ std::pair<std::unique_ptr<shell::InterfaceRegistry>,
+ std::unique_ptr<shell::InterfaceProvider>>;
+
class MockEmbeddedWorkerSetup;
void OnStartWorkerStub(const EmbeddedWorkerMsg_StartWorker_Params& params);
@@ -159,7 +169,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
int request_id,
const ServiceWorkerMsg_ExtendableMessageEvent_Params& params);
void OnInstallEventStub(int request_id);
- void OnFetchEventStub(int request_id,
+ void OnFetchEventStub(int response_id,
+ int event_finish_id,
const ServiceWorkerFetchRequest& request);
void OnPushEventStub(int request_id, const PushEventPayload& payload);
void OnSetupMojoStub(int thread_id,
@@ -179,13 +190,13 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
int next_thread_id_;
int mock_render_process_id_;
- ServiceRegistryImpl render_process_service_registry_;
+ std::unique_ptr<shell::InterfaceRegistry> render_process_interface_registry_;
std::map<int, int64_t> embedded_worker_id_service_worker_version_id_map_;
- // Stores the ServiceRegistries that are associated with each individual
- // service worker.
- base::ScopedPtrHashMap<int, std::unique_ptr<ServiceRegistryImpl>>
+ // Stores the InterfaceRegistry/InterfaceProviders that are associated with
+ // each individual service worker.
+ base::hash_map<int, InterfaceRegistryAndProvider>
thread_id_service_registry_map_;
// Updated each time MessageToWorker message is received.
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 59fe4846dfd..9b213107576 100644
--- a/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
+++ b/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
@@ -10,7 +10,7 @@
#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.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_interceptor.h"
@@ -51,28 +51,35 @@ void ForeignFetchRequestHandler::InitializeHandler(
storage::BlobStorageContext* blob_storage_context,
int process_id,
int provider_id,
- bool skip_service_worker,
+ SkipServiceWorker skip_service_worker,
FetchRequestMode request_mode,
FetchCredentialsMode credentials_mode,
FetchRedirectMode redirect_mode,
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body) {
- if (!context_wrapper) {
+ scoped_refptr<ResourceRequestBodyImpl> body,
+ bool initiated_in_secure_context) {
+ if (!context_wrapper)
return;
- }
- if (!context_wrapper->OriginHasForeignFetchRegistrations(
- request->url().GetOrigin())) {
+ if (skip_service_worker == SkipServiceWorker::ALL)
return;
- }
- if (request->initiator().IsSameOriginWith(url::Origin(request->url())))
+ if (!initiated_in_secure_context)
return;
+
if (ServiceWorkerUtils::IsMainResourceType(resource_type))
return;
+ if (request->initiator().IsSameOriginWith(url::Origin(request->url())))
+ return;
+
+ if (!context_wrapper->OriginHasForeignFetchRegistrations(
+ request->url().GetOrigin())) {
+ return;
+ }
+
// Any more precise checks to see if the request should be intercepted are
// asynchronous, so just create our handler in all cases.
std::unique_ptr<ForeignFetchRequestHandler> handler(
@@ -152,7 +159,7 @@ ForeignFetchRequestHandler::ForeignFetchRequestHandler(
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body)
+ scoped_refptr<ResourceRequestBodyImpl> body)
: context_(context),
blob_storage_context_(blob_storage_context),
resource_type_(resource_type),
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 2ecc04a6aad..c9c302676da 100644
--- a/chromium/content/browser/service_worker/foreign_fetch_request_handler.h
+++ b/chromium/content/browser/service_worker/foreign_fetch_request_handler.h
@@ -31,7 +31,7 @@ class BlobStorageContext;
namespace content {
class ResourceContext;
-class ResourceRequestBody;
+class ResourceRequestBodyImpl;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
class ServiceWorkerProviderHost;
@@ -54,14 +54,15 @@ class CONTENT_EXPORT ForeignFetchRequestHandler
storage::BlobStorageContext* blob_storage_context,
int process_id,
int provider_id,
- bool skip_service_worker,
+ SkipServiceWorker skip_service_worker,
FetchRequestMode request_mode,
FetchCredentialsMode credentials_mode,
FetchRedirectMode redirect_mode,
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body);
+ scoped_refptr<ResourceRequestBodyImpl> body,
+ bool initiated_in_secure_context);
// Returns the handler attached to |request|. This may return null
// if no handler is attached.
@@ -88,7 +89,7 @@ class CONTENT_EXPORT ForeignFetchRequestHandler
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body);
+ scoped_refptr<ResourceRequestBodyImpl> body);
// Called when a ServiceWorkerRegistration has (or hasn't) been found for the
// request being handled.
@@ -114,7 +115,7 @@ class CONTENT_EXPORT ForeignFetchRequestHandler
FetchRedirectMode redirect_mode_;
RequestContextType request_context_type_;
RequestContextFrameType frame_type_;
- scoped_refptr<ResourceRequestBody> body_;
+ scoped_refptr<ResourceRequestBodyImpl> body_;
base::WeakPtr<ServiceWorkerURLRequestJob> job_;
scoped_refptr<ServiceWorkerVersion> target_worker_;
diff --git a/chromium/content/browser/service_worker/link_header_support.cc b/chromium/content/browser/service_worker/link_header_support.cc
index 4f46dfcac0d..92b2d319eaf 100644
--- a/chromium/content/browser/service_worker/link_header_support.cc
+++ b/chromium/content/browser/service_worker/link_header_support.cc
@@ -11,6 +11,7 @@
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_request_handler.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
@@ -55,14 +56,19 @@ void HandleServiceWorkerLink(
if (!service_worker_context)
return;
- // TODO(mek): serviceworker links should only be supported on requests from
- // secure contexts. For now just check the initiator origin, even though that
- // is not correct: 1) the initiator isn't the origin that matters in case of
- // navigations, and 2) more than just a secure origin this needs to be a
- // secure context.
- if (!request->initiator().unique() &&
- !IsOriginSecure(GURL(request->initiator().Serialize())))
- 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 {
+ // If this is not a navigation, make sure the request was initiated from a
+ // secure context.
+ if (!request_info->initiated_in_secure_context())
+ return;
+ }
// TODO(mek): support for a serviceworker link on a request that wouldn't ever
// be able to be intercepted by a serviceworker isn't very useful, so this
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 8bc59226645..34dfda9e24e 100644
--- a/chromium/content/browser/service_worker/link_header_support_unittest.cc
+++ b/chromium/content/browser/service_worker/link_header_support_unittest.cc
@@ -7,22 +7,26 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/run_loop.h"
+#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
-#include "content/public/browser/resource_request_info.h"
+#include "content/browser/service_worker/service_worker_request_handler.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
+const int kMockProviderId = 1;
+
void SaveFoundRegistrationsCallback(
ServiceWorkerStatusCode expected_status,
bool* called,
@@ -56,27 +60,53 @@ class LinkHeaderServiceWorkerTest : public ::testing::Test {
void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+
+ // An empty host.
+ std::unique_ptr<ServiceWorkerProviderHost> host(
+ new ServiceWorkerProviderHost(
+ helper_->mock_render_process_id(), MSG_ROUTING_NONE,
+ kMockProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ ServiceWorkerProviderHost::FrameSecurityLevel::UNINITIALIZED,
+ context()->AsWeakPtr(), nullptr));
+ provider_host_ = host->AsWeakPtr();
+ context()->AddProviderHost(std::move(host));
}
void TearDown() override { helper_.reset(); }
+ ServiceWorkerContextCore* context() { return helper_->context(); }
ServiceWorkerContextWrapper* context_wrapper() {
return helper_->context_wrapper();
}
+ ServiceWorkerProviderHost* provider_host() { return provider_host_.get(); }
- void ProcessLinkHeader(const GURL& request_url,
- const std::string& link_header) {
+ std::unique_ptr<net::URLRequest> CreateRequest(const GURL& request_url,
+ ResourceType resource_type) {
std::unique_ptr<net::URLRequest> request = request_context_.CreateRequest(
request_url, net::DEFAULT_PRIORITY, &request_delegate_);
ResourceRequestInfo::AllocateForTesting(
- request.get(), RESOURCE_TYPE_SCRIPT, &resource_context_,
+ request.get(), resource_type, &resource_context_,
-1 /* render_process_id */, -1 /* render_view_id */,
- -1 /* render_frame_id */, false /* is_main_frame */,
+ -1 /* render_frame_id */, resource_type == RESOURCE_TYPE_MAIN_FRAME,
false /* parent_is_main_frame */, true /* allow_download */,
true /* is_async */, false /* is_using_lofi */);
+ ResourceRequestInfoImpl::ForRequest(request.get())
+ ->set_initiated_in_secure_context_for_testing(true);
+
+ 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);
+
+ return request;
+ }
- ProcessLinkHeaderForRequest(request.get(), link_header, context_wrapper());
- base::RunLoop().RunUntilIdle();
+ std::unique_ptr<net::URLRequest> CreateSubresourceRequest(
+ const GURL& request_url) {
+ return CreateRequest(request_url, RESOURCE_TYPE_SCRIPT);
}
std::vector<ServiceWorkerRegistrationInfo> GetRegistrations() {
@@ -95,11 +125,15 @@ class LinkHeaderServiceWorkerTest : public ::testing::Test {
net::TestURLRequestContext request_context_;
net::TestDelegate request_delegate_;
MockResourceContext resource_context_;
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+ storage::BlobStorageContext blob_storage_context_;
};
TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_Basic) {
- ProcessLinkHeader(GURL("https://example.com/foo/bar/"),
- "<../foo.js>; rel=serviceworker");
+ 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());
@@ -109,8 +143,10 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_Basic) {
}
TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeWithFragment) {
- ProcessLinkHeader(GURL("https://example.com/foo/bar/"),
- "<../bar.js>; rel=serviceworker; scope=\"scope#ref\"");
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
+ "<../bar.js>; rel=serviceworker; scope=\"scope#ref\"", context_wrapper());
+ base::RunLoop().RunUntilIdle();
std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
ASSERT_EQ(1u, registrations.size());
@@ -121,9 +157,12 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeWithFragment) {
}
TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeAbsoluteUrl) {
- ProcessLinkHeader(GURL("https://example.com/foo/bar/"),
- "<bar.js>; rel=serviceworker; "
- "scope=\"https://example.com:443/foo/bar/scope\"");
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foo/bar/")).get(),
+ "<bar.js>; rel=serviceworker; "
+ "scope=\"https://example.com:443/foo/bar/scope\"",
+ context_wrapper());
+ base::RunLoop().RunUntilIdle();
std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
ASSERT_EQ(1u, registrations.size());
@@ -134,17 +173,21 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeAbsoluteUrl) {
}
TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeDifferentOrigin) {
- ProcessLinkHeader(
- GURL("https://example.com/foobar/"),
- "<bar.js>; rel=serviceworker; scope=\"https://google.com/scope\"");
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
+ "<bar.js>; rel=serviceworker; scope=\"https://google.com/scope\"",
+ context_wrapper());
+ base::RunLoop().RunUntilIdle();
std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
ASSERT_EQ(0u, registrations.size());
}
TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeUrlEncodedSlash) {
- ProcessLinkHeader(GURL("https://example.com/foobar/"),
- "<bar.js>; rel=serviceworker; scope=\"./foo%2Fbar\"");
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
+ "<bar.js>; rel=serviceworker; scope=\"./foo%2Fbar\"", context_wrapper());
+ base::RunLoop().RunUntilIdle();
std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
ASSERT_EQ(0u, registrations.size());
@@ -152,17 +195,21 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeUrlEncodedSlash) {
TEST_F(LinkHeaderServiceWorkerTest,
InstallServiceWorker_ScriptUrlEncodedSlash) {
- ProcessLinkHeader(GURL("https://example.com/foobar/"),
- "<foo%2Fbar.js>; rel=serviceworker");
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
+ "<foo%2Fbar.js>; rel=serviceworker", context_wrapper());
+ base::RunLoop().RunUntilIdle();
std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
ASSERT_EQ(0u, registrations.size());
}
TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptAbsoluteUrl) {
- ProcessLinkHeader(
- GURL("https://example.com/foobar/"),
- "<https://example.com/bar.js>; rel=serviceworker; scope=foo");
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
+ "<https://example.com/bar.js>; rel=serviceworker; scope=foo",
+ context_wrapper());
+ base::RunLoop().RunUntilIdle();
std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
ASSERT_EQ(1u, registrations.size());
@@ -173,18 +220,23 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptAbsoluteUrl) {
TEST_F(LinkHeaderServiceWorkerTest,
InstallServiceWorker_ScriptDifferentOrigin) {
- ProcessLinkHeader(
- GURL("https://example.com/foobar/"),
- "<https://google.com/bar.js>; rel=serviceworker; scope=foo");
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
+ "<https://google.com/bar.js>; rel=serviceworker; scope=foo",
+ context_wrapper());
+ base::RunLoop().RunUntilIdle();
std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
ASSERT_EQ(0u, registrations.size());
}
TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_MultipleWorkers) {
- ProcessLinkHeader(GURL("https://example.com/foobar/"),
- "<bar.js>; rel=serviceworker; scope=foo, <baz.js>; "
- "rel=serviceworker; scope=scope");
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
+ "<bar.js>; rel=serviceworker; scope=foo, <baz.js>; "
+ "rel=serviceworker; scope=scope",
+ context_wrapper());
+ base::RunLoop().RunUntilIdle();
std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
ASSERT_EQ(2u, registrations.size());
@@ -198,10 +250,12 @@ TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_MultipleWorkers) {
TEST_F(LinkHeaderServiceWorkerTest,
InstallServiceWorker_ValidAndInvalidValues) {
- ProcessLinkHeader(
- GURL("https://example.com/foobar/"),
+ ProcessLinkHeaderForRequest(
+ CreateSubresourceRequest(GURL("https://example.com/foobar/")).get(),
"<https://google.com/bar.js>; rel=serviceworker; scope=foo, <baz.js>; "
- "rel=serviceworker; scope=scope");
+ "rel=serviceworker; scope=scope",
+ context_wrapper());
+ base::RunLoop().RunUntilIdle();
std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
ASSERT_EQ(1u, registrations.size());
@@ -210,6 +264,70 @@ TEST_F(LinkHeaderServiceWorkerTest,
registrations[0].active_version.script_url);
}
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_InsecureContext) {
+ std::unique_ptr<net::URLRequest> request =
+ CreateSubresourceRequest(GURL("https://example.com/foo/bar/"));
+ ResourceRequestInfoImpl::ForRequest(request.get())
+ ->set_initiated_in_secure_context_for_testing(false);
+ ProcessLinkHeaderForRequest(request.get(), "<../foo.js>; rel=serviceworker",
+ context_wrapper());
+ base::RunLoop().RunUntilIdle();
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(0u, registrations.size());
+}
+
+TEST_F(LinkHeaderServiceWorkerTest,
+ InstallServiceWorker_NavigationFromInsecureContextToSecureContext) {
+ std::unique_ptr<net::URLRequest> request = CreateRequest(
+ GURL("https://example.com/foo/bar/"), RESOURCE_TYPE_MAIN_FRAME);
+ ResourceRequestInfoImpl::ForRequest(request.get())
+ ->set_initiated_in_secure_context_for_testing(false);
+
+ provider_host()->SetDocumentUrl(GURL("https://example.com/foo/bar/"));
+ provider_host()->set_parent_frame_secure(true);
+
+ ProcessLinkHeaderForRequest(request.get(), "<../foo.js>; rel=serviceworker",
+ context_wrapper());
+ base::RunLoop().RunUntilIdle();
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(1u, registrations.size());
+ EXPECT_EQ(GURL("https://example.com/foo/"), registrations[0].pattern);
+ EXPECT_EQ(GURL("https://example.com/foo/foo.js"),
+ registrations[0].active_version.script_url);
+}
+
+TEST_F(LinkHeaderServiceWorkerTest,
+ InstallServiceWorker_NavigationToInsecureContext) {
+ provider_host()->SetDocumentUrl(GURL("http://example.com/foo/bar/"));
+ provider_host()->set_parent_frame_secure(true);
+ ProcessLinkHeaderForRequest(CreateRequest(GURL("http://example.com/foo/bar/"),
+ RESOURCE_TYPE_MAIN_FRAME)
+ .get(),
+ "<../foo.js>; rel=serviceworker",
+ context_wrapper());
+ base::RunLoop().RunUntilIdle();
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(0u, registrations.size());
+}
+
+TEST_F(LinkHeaderServiceWorkerTest,
+ InstallServiceWorker_NavigationToInsecureHttpsContext) {
+ provider_host()->SetDocumentUrl(GURL("https://example.com/foo/bar/"));
+ provider_host()->set_parent_frame_secure(false);
+ ProcessLinkHeaderForRequest(
+ CreateRequest(GURL("https://example.com/foo/bar/"),
+ RESOURCE_TYPE_MAIN_FRAME)
+ .get(),
+ "<../foo.js>; rel=serviceworker", context_wrapper());
+ base::RunLoop().RunUntilIdle();
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(0u, registrations.size());
+}
+
} // namespace
} // 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 d067b506e92..631ea7be75a 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -25,10 +25,12 @@
#include "build/build_config.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -60,6 +62,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/log/net_log.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
@@ -652,8 +655,30 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
int request_id =
version_->StartRequest(ServiceWorkerMetrics::EventType::INSTALL,
CreateReceiver(BrowserThread::UI, done, result));
- version_->DispatchSimpleEvent<ServiceWorkerHostMsg_InstallEventFinished>(
- request_id, ServiceWorkerMsg_InstallEvent(request_id));
+ version_
+ ->RegisterRequestCallback<ServiceWorkerHostMsg_InstallEventFinished>(
+ request_id, base::Bind(&self::ReceiveInstallEventOnIOThread, this,
+ done, result));
+ version_->DispatchEvent({request_id},
+ ServiceWorkerMsg_InstallEvent(request_id));
+ }
+
+ void ReceiveInstallEventOnIOThread(const base::Closure& done,
+ ServiceWorkerStatusCode* out_result,
+ int request_id,
+ blink::WebServiceWorkerEventResult result,
+ bool has_fetch_handler) {
+ version_->FinishRequest(
+ request_id, result == blink::WebServiceWorkerEventResultCompleted);
+ version_->set_has_fetch_handler(has_fetch_handler);
+
+ ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
+ if (result == blink::WebServiceWorkerEventResultRejected)
+ status = SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED;
+
+ *out_result = status;
+ if (!done.is_null())
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done);
}
void StoreOnIOThread(const base::Closure& done,
@@ -699,7 +724,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
std::move(request), version_.get(), RESOURCE_TYPE_MAIN_FRAME,
- CreatePrepareReceiver(prepare_result),
+ net::BoundNetLog(), CreatePrepareReceiver(prepare_result),
CreateResponseReceiver(done, blob_context_.get(), result)));
fetch_dispatcher_->Run();
}
@@ -867,6 +892,18 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
SERVICE_WORKER_OK);
}
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+ InstallWithFetchHandler) {
+ InstallTestHelper("/service_worker/fetch_event.js", SERVICE_WORKER_OK);
+ EXPECT_TRUE(version_->has_fetch_handler());
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+ InstallWithoutFetchHandler) {
+ InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
+ EXPECT_FALSE(version_->has_fetch_handler());
+}
+
// Check that ServiceWorker script requests set a "Service-Worker: script"
// header.
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
@@ -949,7 +986,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
// The script has loaded but start has not completed yet.
ASSERT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
- EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
// Simulate execution timeout. Use a delay to prevent killing the worker
// before it's started execution.
@@ -1625,22 +1662,26 @@ class CacheStorageSideDataSizeChecker
this, result, continuation));
}
- void OnCacheStorageOpenCallback(int* result,
- const base::Closure& continuation,
- scoped_refptr<CacheStorageCache> cache,
- CacheStorageError error) {
+ void OnCacheStorageOpenCallback(
+ int* result,
+ const base::Closure& continuation,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
+ CacheStorageError error) {
ASSERT_EQ(CACHE_STORAGE_OK, error);
std::unique_ptr<ServiceWorkerFetchRequest> scoped_request(
new ServiceWorkerFetchRequest());
scoped_request->url = url_;
- cache->Match(std::move(scoped_request),
- base::Bind(&self::OnCacheStorageCacheMatchCallback, this,
- result, continuation));
+ CacheStorageCache* cache = cache_handle->value();
+ cache->Match(
+ std::move(scoped_request),
+ base::Bind(&self::OnCacheStorageCacheMatchCallback, this, result,
+ continuation, base::Passed(std::move(cache_handle))));
}
void OnCacheStorageCacheMatchCallback(
int* result,
const base::Closure& continuation,
+ std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error,
std::unique_ptr<ServiceWorkerResponse> response,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle) {
@@ -1700,6 +1741,56 @@ class ServiceWorkerV8CacheStrategiesTest : public ServiceWorkerBrowserTest {
~ServiceWorkerV8CacheStrategiesTest() override {}
protected:
+ void CheckStrategyIsNone() {
+ RegisterAndActivateServiceWorker();
+
+ NavigateToTestPage();
+ EXPECT_EQ(0, GetSideDataSize());
+
+ NavigateToTestPage();
+ EXPECT_EQ(0, GetSideDataSize());
+
+ NavigateToTestPage();
+ EXPECT_EQ(0, GetSideDataSize());
+ }
+
+ void CheckStrategyIsNormal() {
+ RegisterAndActivateServiceWorker();
+
+ NavigateToTestPage();
+ // fetch_event_response_via_cache.js returns |cloned_response| for the first
+ // load. So the V8 code cache should not be stored to the CacheStorage.
+ EXPECT_EQ(0, GetSideDataSize());
+
+ NavigateToTestPage();
+ // V8ScriptRunner::setCacheTimeStamp() stores 12 byte data (tag +
+ // timestamp).
+ EXPECT_EQ(kV8CacheTimeStampDataSize, GetSideDataSize());
+
+ NavigateToTestPage();
+ // The V8 code cache must be stored to the CacheStorage which must be bigger
+ // than 12 byte.
+ EXPECT_GT(GetSideDataSize(), kV8CacheTimeStampDataSize);
+ }
+
+ void CheckStrategyIsAggressive() {
+ RegisterAndActivateServiceWorker();
+
+ NavigateToTestPage();
+ // fetch_event_response_via_cache.js returns |cloned_response| for the first
+ // load. So the V8 code cache should not be stored to the CacheStorage.
+ EXPECT_EQ(0, GetSideDataSize());
+
+ NavigateToTestPage();
+ // The V8 code cache must be stored to the CacheStorage which must be bigger
+ // than 12 byte.
+ EXPECT_GT(GetSideDataSize(), kV8CacheTimeStampDataSize);
+
+ NavigateToTestPage();
+ EXPECT_GT(GetSideDataSize(), kV8CacheTimeStampDataSize);
+ }
+
+ private:
static const std::string kPageUrl;
static const std::string kWorkerUrl;
static const std::string kScriptUrl;
@@ -1734,7 +1825,6 @@ class ServiceWorkerV8CacheStrategiesTest : public ServiceWorkerBrowserTest {
std::string("cache_name"), embedded_test_server()->GetURL(kScriptUrl));
}
- private:
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerV8CacheStrategiesTest);
};
@@ -1748,6 +1838,12 @@ const std::string ServiceWorkerV8CacheStrategiesTest::kScriptUrl =
const int ServiceWorkerV8CacheStrategiesTest::kV8CacheTimeStampDataSize =
sizeof(unsigned) + sizeof(double);
+IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesTest,
+ V8CacheOnCacheStorage) {
+ // The strategy is "aggressive" on default.
+ CheckStrategyIsAggressive();
+}
+
class ServiceWorkerV8CacheStrategiesNoneTest
: public ServiceWorkerV8CacheStrategiesTest {
public:
@@ -1764,16 +1860,7 @@ class ServiceWorkerV8CacheStrategiesNoneTest
IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesNoneTest,
V8CacheOnCacheStorage) {
- RegisterAndActivateServiceWorker();
-
- NavigateToTestPage();
- EXPECT_EQ(0, GetSideDataSize());
-
- NavigateToTestPage();
- EXPECT_EQ(0, GetSideDataSize());
-
- NavigateToTestPage();
- EXPECT_EQ(0, GetSideDataSize());
+ CheckStrategyIsNone();
}
class ServiceWorkerV8CacheStrategiesNormalTest
@@ -1792,21 +1879,7 @@ class ServiceWorkerV8CacheStrategiesNormalTest
IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesNormalTest,
V8CacheOnCacheStorage) {
- RegisterAndActivateServiceWorker();
-
- NavigateToTestPage();
- // fetch_event_response_via_cache.js returns |cloned_response| for the first
- // load. So the V8 code cache should not be stored to the CacheStorage.
- EXPECT_EQ(0, GetSideDataSize());
-
- NavigateToTestPage();
- // V8ScriptRunner::setCacheTimeStamp() stores 12 byte data (tag + timestamp).
- EXPECT_EQ(kV8CacheTimeStampDataSize, GetSideDataSize());
-
- NavigateToTestPage();
- // The V8 code cache must be stored to the CacheStorage which must be bigger
- // than 12 byte.
- EXPECT_GT(GetSideDataSize(), kV8CacheTimeStampDataSize);
+ CheckStrategyIsNormal();
}
class ServiceWorkerV8CacheStrategiesAggressiveTest
@@ -1825,20 +1898,7 @@ class ServiceWorkerV8CacheStrategiesAggressiveTest
IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesAggressiveTest,
V8CacheOnCacheStorage) {
- RegisterAndActivateServiceWorker();
-
- NavigateToTestPage();
- // fetch_event_response_via_cache.js returns |cloned_response| for the first
- // load. So the V8 code cache should not be stored to the CacheStorage.
- EXPECT_EQ(0, GetSideDataSize());
-
- NavigateToTestPage();
- // The V8 code cache must be stored to the CacheStorage which must be bigger
- // than 12 byte.
- EXPECT_GT(GetSideDataSize(), kV8CacheTimeStampDataSize);
-
- NavigateToTestPage();
- EXPECT_GT(GetSideDataSize(), kV8CacheTimeStampDataSize);
+ CheckStrategyIsAggressive();
}
} // 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 2c7c1274f2e..6f8f367ce0d 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.cc
@@ -5,9 +5,13 @@
#include "content/browser/service_worker/service_worker_client_utils.h"
#include <algorithm>
+#include <tuple>
+#include "base/location.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/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/service_worker/service_worker_context_core.h"
@@ -86,7 +90,7 @@ class OpenURLObserver : public WebContentsObserver {
BrowserThread::IO, FROM_HERE,
base::Bind(callback_, render_process_id, render_frame_id));
Observe(nullptr);
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
int frame_tree_node_id_;
@@ -149,7 +153,14 @@ ServiceWorkerClientInfo FocusOnUI(int render_process_id,
void DidOpenURLOnUI(const OpenURLCallback& callback,
WebContents* web_contents) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(web_contents);
+
+ if (!web_contents) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(callback, ChildProcessHost::kInvalidUniqueID,
+ MSG_ROUTING_NONE));
+ return;
+ }
RenderFrameHostImpl* rfhi =
static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame());
@@ -266,11 +277,11 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
void AddWindowClient(
ServiceWorkerProviderHost* host,
- std::vector<base::Tuple<int, int, std::string>>* client_info) {
+ std::vector<std::tuple<int, int, std::string>>* client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (host->client_type() != blink::WebServiceWorkerClientTypeWindow)
return;
- client_info->push_back(base::MakeTuple(host->process_id(), host->frame_id(),
+ client_info->push_back(std::make_tuple(host->process_id(), host->frame_id(),
host->client_uuid()));
}
@@ -295,7 +306,7 @@ void AddNonWindowClient(ServiceWorkerProviderHost* host,
void OnGetWindowClientsOnUI(
// The tuple contains process_id, frame_id, client_uuid.
- const std::vector<base::Tuple<int, int, std::string>>& clients_info,
+ const std::vector<std::tuple<int, int, std::string>>& clients_info,
const GURL& script_url,
const GetWindowClientsCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -303,7 +314,7 @@ void OnGetWindowClientsOnUI(
std::unique_ptr<ServiceWorkerClients> clients(new ServiceWorkerClients);
for (const auto& it : clients_info) {
ServiceWorkerClientInfo info = GetWindowClientInfoOnUI(
- base::get<0>(it), base::get<1>(it), base::get<2>(it));
+ std::get<0>(it), std::get<1>(it), std::get<2>(it));
// If the request to the provider_host returned an empty
// ServiceWorkerClientInfo, that means that it wasn't possible to associate
@@ -375,7 +386,7 @@ void GetWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
DCHECK(options.client_type == blink::WebServiceWorkerClientTypeWindow ||
options.client_type == blink::WebServiceWorkerClientTypeAll);
- std::vector<base::Tuple<int, int, std::string>> clients_info;
+ std::vector<std::tuple<int, int, std::string>> clients_info;
if (!options.include_uncontrolled) {
for (auto& controllee : controller->controllee_map())
AddWindowClient(controllee.second, &clients_info);
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.cc b/chromium/content/browser/service_worker/service_worker_context_core.cc
index 5afed8a7c8d..2db3464318f 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -20,6 +20,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_database_task_manager.h"
@@ -115,8 +116,8 @@ class ClearAllServiceWorkersHelper
context->GetLiveVersions();
for (const auto& version_itr : live_versions_copy) {
ServiceWorkerVersion* version(version_itr.second);
- if (version->running_status() == ServiceWorkerVersion::STARTING ||
- version->running_status() == ServiceWorkerVersion::RUNNING) {
+ if (version->running_status() == EmbeddedWorkerStatus::STARTING ||
+ version->running_status() == EmbeddedWorkerStatus::RUNNING) {
version->StopWorker(
base::Bind(&ClearAllServiceWorkersHelper::OnResult, this));
}
diff --git a/chromium/content/browser/service_worker/service_worker_context_observer.h b/chromium/content/browser/service_worker/service_worker_context_observer.h
index b643153f951..ebb41cc5c22 100644
--- a/chromium/content/browser/service_worker/service_worker_context_observer.h
+++ b/chromium/content/browser/service_worker/service_worker_context_observer.h
@@ -14,6 +14,8 @@
namespace content {
+enum class EmbeddedWorkerStatus;
+
class ServiceWorkerContextObserver {
public:
struct ErrorInfo {
@@ -52,9 +54,8 @@ class ServiceWorkerContextObserver {
virtual void OnNewLiveVersion(int64_t version_id,
int64_t registration_id,
const GURL& script_url) {}
- virtual void OnRunningStateChanged(
- int64_t version_id,
- ServiceWorkerVersion::RunningStatus running_status) {}
+ virtual void OnRunningStateChanged(int64_t version_id,
+ EmbeddedWorkerStatus running_status) {}
virtual void OnVersionStateChanged(int64_t version_id,
ServiceWorkerVersion::Status status) {}
virtual void OnMainScriptHttpResponseInfoSet(
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 6b417401f7f..05409c833aa 100644
--- a/chromium/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -85,10 +85,9 @@ class RejectInstallTestHelper : public EmbeddedWorkerTestHelper {
void OnInstallEvent(int embedded_worker_id,
int request_id) override {
- SimulateSend(
- new ServiceWorkerHostMsg_InstallEventFinished(
- embedded_worker_id, request_id,
- blink::WebServiceWorkerEventResultRejected));
+ SimulateSend(new ServiceWorkerHostMsg_InstallEventFinished(
+ embedded_worker_id, request_id,
+ blink::WebServiceWorkerEventResultRejected, true));
}
};
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher.cc b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
index d599d3d657f..4309b0a18de 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/containers/scoped_ptr_hash_map.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_version.h"
@@ -20,8 +21,7 @@ namespace content {
namespace {
bool IsStoppedAndRedundant(const ServiceWorkerVersionInfo& version_info) {
- return version_info.running_status ==
- content::ServiceWorkerVersion::STOPPED &&
+ return version_info.running_status == EmbeddedWorkerStatus::STOPPED &&
version_info.status == content::ServiceWorkerVersion::REDUNDANT;
}
@@ -186,7 +186,7 @@ void ServiceWorkerContextWatcher::OnNewLiveVersion(int64_t version_id,
void ServiceWorkerContextWatcher::OnRunningStateChanged(
int64_t version_id,
- content::ServiceWorkerVersion::RunningStatus running_status) {
+ content::EmbeddedWorkerStatus running_status) {
ServiceWorkerVersionInfo* version = version_info_map_.get(version_id);
DCHECK(version);
if (version->running_status == running_status)
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher.h b/chromium/content/browser/service_worker/service_worker_context_watcher.h
index aae387d6a9c..d7341a51ad0 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.h
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.h
@@ -17,6 +17,7 @@
namespace content {
class ServiceWorkerContextWrapper;
+enum class EmbeddedWorkerStatus;
// Used to monitor the status change of the ServiceWorker registrations and
// versions in the ServiceWorkerContext from UI thread.
@@ -72,7 +73,7 @@ class ServiceWorkerContextWatcher
const GURL& script_url) override;
void OnRunningStateChanged(
int64_t version_id,
- content::ServiceWorkerVersion::RunningStatus running_status) override;
+ content::EmbeddedWorkerStatus running_status) override;
void OnVersionStateChanged(
int64_t version_id,
content::ServiceWorkerVersion::Status status) override;
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
index 68408b4962b..e45ca4c7d3f 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -15,7 +15,7 @@
#include "content/browser/service_worker/service_worker_registration.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.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"
@@ -37,13 +37,14 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body)
+ scoped_refptr<ResourceRequestBodyImpl> body)
: ServiceWorkerRequestHandler(context,
provider_host,
blob_storage_context,
resource_type),
is_main_resource_load_(
ServiceWorkerUtils::IsMainResourceType(resource_type)),
+ is_main_frame_load_(resource_type == RESOURCE_TYPE_MAIN_FRAME),
request_mode_(request_mode),
credentials_mode_(credentials_mode),
redirect_mode_(redirect_mode),
@@ -262,16 +263,14 @@ ServiceWorkerControlleeRequestHandler::DidLookupRegistrationForMainResource(
return;
}
- ServiceWorkerMetrics::CountControlledPageLoad(stripped_url_);
+ ServiceWorkerMetrics::CountControlledPageLoad(
+ stripped_url_, active_version->has_fetch_handler(), is_main_frame_load_);
job_->ForwardToServiceWorker();
TRACE_EVENT_ASYNC_END2(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- job_.get(),
- "Status", status,
- "Info",
- "Forwarded to the ServiceWorker");
+ job_.get(), "Status", status, "Info", "Forwarded to the ServiceWorker");
}
void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
@@ -290,7 +289,8 @@ void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
return;
}
- ServiceWorkerMetrics::CountControlledPageLoad(stripped_url_);
+ ServiceWorkerMetrics::CountControlledPageLoad(
+ stripped_url_, version->has_fetch_handler(), is_main_frame_load_);
provider_host_->AssociateRegistration(registration,
false /* notify_controllerchange */);
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
index 8a168e4aee4..8da2a56a51e 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -28,7 +28,7 @@ class URLRequest;
namespace content {
-class ResourceRequestBody;
+class ResourceRequestBodyImpl;
class ServiceWorkerRegistration;
class ServiceWorkerVersion;
@@ -48,7 +48,7 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body);
+ scoped_refptr<ResourceRequestBodyImpl> body);
~ServiceWorkerControlleeRequestHandler() override;
// Called via custom URLRequestJobFactory.
@@ -99,14 +99,15 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
// that job, except for timing information.
void ClearJob();
- bool is_main_resource_load_;
+ const bool is_main_resource_load_;
+ const bool is_main_frame_load_;
base::WeakPtr<ServiceWorkerURLRequestJob> job_;
FetchRequestMode request_mode_;
FetchCredentialsMode credentials_mode_;
FetchRedirectMode redirect_mode_;
RequestContextType request_context_type_;
RequestContextFrameType frame_type_;
- scoped_refptr<ResourceRequestBody> body_;
+ scoped_refptr<ResourceRequestBodyImpl> body_;
ResourceContext* resource_context_;
GURL stripped_url_;
bool force_update_started_;
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 eb4c1808ccf..1e2ac451507 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
@@ -18,7 +18,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_url_request_job.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.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"
@@ -76,7 +76,7 @@ class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
type,
REQUEST_CONTEXT_TYPE_HYPERLINK,
REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
- scoped_refptr<ResourceRequestBody>())),
+ scoped_refptr<ResourceRequestBodyImpl>())),
job_(nullptr) {}
ServiceWorkerURLRequestJob* MaybeCreateJob() {
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 de52af6b8ce..10b633b904b 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -17,11 +17,11 @@
#include "content/browser/message_port_message_filter.h"
#include "content/browser/message_port_service.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_client_utils.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_handle.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "content/common/service_worker/embedded_worker_messages.h"
@@ -762,40 +762,14 @@ void ServiceWorkerDispatcherHost::OnProviderCreated(
return;
}
- std::unique_ptr<ServiceWorkerProviderHost> provider_host;
- if (IsBrowserSideNavigationEnabled() &&
- ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id)) {
- // PlzNavigate
- // Retrieve the provider host previously created for navigation requests.
- ServiceWorkerNavigationHandleCore* navigation_handle_core =
- GetContext()->GetNavigationHandleCore(provider_id);
- if (navigation_handle_core != nullptr) {
- provider_host = navigation_handle_core->RetrievePreCreatedHost();
- provider_host->set_parent_frame_secure(is_parent_frame_secure);
- }
-
- // If no host is found, the navigation has been cancelled in the meantime.
- // Just return as the navigation will be stopped in the renderer as well.
- if (provider_host == nullptr)
- return;
- DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_WINDOW, provider_type);
- provider_host->CompleteNavigationInitialized(render_process_id_, route_id,
- this);
- } else {
- if (ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id)) {
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_PROVIDER_CREATED_NO_HOST);
- return;
- }
- ServiceWorkerProviderHost::FrameSecurityLevel parent_frame_security_level =
- is_parent_frame_secure
- ? ServiceWorkerProviderHost::FrameSecurityLevel::SECURE
- : ServiceWorkerProviderHost::FrameSecurityLevel::INSECURE;
- provider_host = std::unique_ptr<ServiceWorkerProviderHost>(
- new ServiceWorkerProviderHost(
- render_process_id_, route_id, provider_id, provider_type,
- parent_frame_security_level, GetContext()->AsWeakPtr(), this));
- }
+ ServiceWorkerProviderHost::FrameSecurityLevel parent_frame_security_level =
+ is_parent_frame_secure
+ ? ServiceWorkerProviderHost::FrameSecurityLevel::SECURE
+ : ServiceWorkerProviderHost::FrameSecurityLevel::INSECURE;
+ std::unique_ptr<ServiceWorkerProviderHost> provider_host =
+ std::unique_ptr<ServiceWorkerProviderHost>(new ServiceWorkerProviderHost(
+ render_process_id_, route_id, provider_id, provider_type,
+ parent_frame_security_level, GetContext()->AsWeakPtr(), this));
GetContext()->AddProviderHost(std::move(provider_host));
}
@@ -820,7 +794,8 @@ void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
}
void ServiceWorkerDispatcherHost::OnSetHostedVersionId(int provider_id,
- int64_t version_id) {
+ int64_t version_id,
+ int embedded_worker_id) {
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnSetHostedVersionId");
if (!GetContext())
@@ -832,20 +807,39 @@ void ServiceWorkerDispatcherHost::OnSetHostedVersionId(int provider_id,
this, bad_message::SWDH_SET_HOSTED_VERSION_NO_HOST);
return;
}
+
+ // This provider host must be specialized for a controller.
+ if (provider_host->IsProviderForClient()) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_SET_HOSTED_VERSION_INVALID_HOST);
+ return;
+ }
+
+ // A service worker context associated with this provider host was destroyed
+ // due to restarting the service worker system etc.
if (!provider_host->IsContextAlive())
return;
// We might not be STARTING if the stop sequence was entered (STOPPING) or
// ended up being detached (STOPPED).
ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
- if (!version || version->running_status() != ServiceWorkerVersion::STARTING)
+ if (!version || version->running_status() != EmbeddedWorkerStatus::STARTING)
return;
- if (!provider_host->SetHostedVersion(version)) {
- bad_message::ReceivedBadMessage(this, bad_message::SWDH_SET_HOSTED_VERSION);
+ // If the version has a different embedded worker, assume the message is about
+ // a detached worker and ignore.
+ if (version->embedded_worker()->embedded_worker_id() != embedded_worker_id)
+ return;
+
+ // A process for the worker must be equal to a process for the provider host.
+ if (version->embedded_worker()->process_id() != provider_host->process_id()) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_SET_HOSTED_VERSION_PROCESS_MISMATCH);
return;
}
+ provider_host->SetHostedVersion(version);
+
// Retrieve the registration associated with |version|. The registration
// must be alive because the version keeps it during starting worker.
ServiceWorkerRegistration* registration =
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 95330b411e8..9e1c587cb80 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -119,7 +119,9 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
ServiceWorkerProviderType provider_type,
bool is_parent_frame_secure);
void OnProviderDestroyed(int provider_id);
- void OnSetHostedVersionId(int provider_id, int64_t version_id);
+ void OnSetHostedVersionId(int provider_id,
+ int64_t version_id,
+ int embedded_worker_id);
void OnWorkerReadyForInspection(int embedded_worker_id);
void OnWorkerScriptLoaded(int embedded_worker_id);
void OnWorkerThreadStarted(int embedded_worker_id,
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 3aec7f1151f..b210803966d 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
@@ -16,12 +16,14 @@
#include "content/browser/message_port_service.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#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/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -141,9 +143,11 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
EXPECT_EQ(SERVICE_WORKER_OK, status);
}
- void SendSetHostedVersionId(int provider_id, int64_t version_id) {
- dispatcher_host_->OnMessageReceived(
- ServiceWorkerHostMsg_SetVersionId(provider_id, version_id));
+ void SendSetHostedVersionId(int provider_id,
+ int64_t version_id,
+ int embedded_worker_id) {
+ dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_SetVersionId(
+ provider_id, version_id, embedded_worker_id));
}
void SendProviderCreated(ServiceWorkerProviderType type,
@@ -637,14 +641,14 @@ TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_TRUE(context()->GetProviderHost(process_id, provider_id));
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Simulate the render process crashing.
dispatcher_host_->OnFilterRemoved();
// The dispatcher host should clean up the state from the process.
EXPECT_FALSE(context()->GetProviderHost(process_id, provider_id));
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
// We should be able to hook up a new dispatcher host although the old object
// is not yet destroyed. This is what the browser does when reusing a crashed
@@ -761,11 +765,68 @@ TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId) {
EXPECT_NE(version_->embedded_worker()->process_id(),
provider_host_->process_id());
// SendSetHostedVersionId should reject because the provider host process id
- // is different.
- SendSetHostedVersionId(kProviderId, version_->version_id());
+ // is different. It should call BadMessageReceived because it's not an
+ // expected error state.
+ SendSetHostedVersionId(kProviderId, version_->version_id(),
+ version_->embedded_worker()->embedded_worker_id());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_AssociateRegistration::ID));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId_DetachedWorker) {
+ GURL pattern = GURL("http://www.example.com/");
+ GURL script_url = GURL("http://www.example.com/service_worker.js");
+
+ Initialize(base::WrapUnique(new FailToStartWorkerTestHelper));
+ SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern);
+ SetUpRegistration(pattern, script_url);
+
+ const int64_t kProviderId = 99; // Dummy value
+ bool called;
+ ServiceWorkerStatusCode status;
+ // StartWorker puts the worker in STARTING state.
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ base::Bind(&SaveStatusCallback, &called, &status));
+
+ // SendSetHostedVersionId should bail because the embedded worker is
+ // different. It shouldn't call BadMessageReceived because receiving a message
+ // for a detached worker is a legitimite possibility.
+ int bad_embedded_worker_id =
+ version_->embedded_worker()->embedded_worker_id() + 1;
+ SendSetHostedVersionId(kProviderId, version_->version_id(),
+ bad_embedded_worker_id);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
ServiceWorkerMsg_AssociateRegistration::ID));
+ EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, ReceivedTimedOutRequestResponse) {
+ GURL pattern = GURL("https://www.example.com/");
+ GURL script_url = GURL("https://www.example.com/service_worker.js");
+
+ SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_WINDOW, pattern);
+ SetUpRegistration(pattern, script_url);
+
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
+
+ // Set the worker status to STOPPING.
+ version_->embedded_worker()->Stop();
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
+
+ // Receive a response for a timed out request. The bad message count should
+ // not increase.
+ const int kRequestId = 91; // Dummy value
+ dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_FetchEventResponse(
+ version_->embedded_worker()->embedded_worker_id(), kRequestId,
+ SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK, ServiceWorkerResponse()));
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index dad6fba12ce..c08f2659c7b 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -4,16 +4,20 @@
#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
+#include <string>
#include <utility>
#include "base/bind.h"
#include "base/trace_event/trace_event.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/common/service_worker/service_worker_utils.h"
namespace content {
namespace {
+
using EventType = ServiceWorkerMetrics::EventType;
EventType ResourceTypeToEventType(ResourceType resource_type) {
switch (resource_type) {
@@ -31,22 +35,96 @@ EventType ResourceTypeToEventType(ResourceType resource_type) {
return EventType::FETCH_SUB_RESOURCE;
}
}
+
+std::unique_ptr<base::Value> NetLogServiceWorkerStatusCallback(
+ ServiceWorkerStatusCode status,
+ net::NetLogCaptureMode) {
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+ dict->SetString("status", ServiceWorkerStatusToString(status));
+ return std::move(dict);
+}
+
+std::unique_ptr<base::Value> NetLogFetchEventCallback(
+ ServiceWorkerStatusCode status,
+ ServiceWorkerFetchEventResult result,
+ net::NetLogCaptureMode) {
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+ dict->SetString("status", ServiceWorkerStatusToString(status));
+ dict->SetBoolean("has_response",
+ result == SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE);
+ return std::move(dict);
+}
+
+void EndNetLogEventWithServiceWorkerStatus(const net::BoundNetLog& net_log,
+ net::NetLog::EventType type,
+ ServiceWorkerStatusCode status) {
+ net_log.EndEvent(type,
+ base::Bind(&NetLogServiceWorkerStatusCallback, status));
+}
+
+ServiceWorkerMetrics::EventType FetchTypeToWaitUntilEventType(
+ ServiceWorkerFetchType type) {
+ if (type == ServiceWorkerFetchType::FOREIGN_FETCH)
+ return ServiceWorkerMetrics::EventType::FOREIGN_FETCH_WAITUNTIL;
+ return ServiceWorkerMetrics::EventType::FETCH_WAITUNTIL;
+}
+
} // namespace
+// Helper to receive the fetch event response even if
+// ServiceWorkerFetchDispatcher has been destroyed.
+class ServiceWorkerFetchDispatcher::ResponseCallback {
+ public:
+ ResponseCallback(base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
+ ServiceWorkerVersion* version)
+ : fetch_dispatcher_(fetch_dispatcher), version_(version) {}
+
+ void Run(int request_id,
+ ServiceWorkerFetchEventResult fetch_result,
+ const ServiceWorkerResponse& response) {
+ const bool handled =
+ (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE);
+ if (!version_->FinishRequest(request_id, handled))
+ NOTREACHED() << "Should only receive one reply per event";
+
+ // |fetch_dispatcher| is null if the URLRequest was killed.
+ if (fetch_dispatcher_)
+ fetch_dispatcher_->DidFinish(request_id, fetch_result, response);
+ }
+
+ private:
+ base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
+ // Owns |this|.
+ ServiceWorkerVersion* version_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResponseCallback);
+};
+
ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher(
std::unique_ptr<ServiceWorkerFetchRequest> request,
ServiceWorkerVersion* version,
ResourceType resource_type,
+ const net::BoundNetLog& net_log,
const base::Closure& prepare_callback,
const FetchCallback& fetch_callback)
: version_(version),
+ net_log_(net_log),
prepare_callback_(prepare_callback),
fetch_callback_(fetch_callback),
request_(std::move(request)),
resource_type_(resource_type),
- weak_factory_(this) {}
+ did_complete_(false),
+ weak_factory_(this) {
+ net_log_.BeginEvent(net::NetLog::TYPE_SERVICE_WORKER_DISPATCH_FETCH_EVENT,
+ net::NetLog::StringCallback(
+ "event_type", ServiceWorkerMetrics::EventTypeToString(
+ GetEventType())));
+}
-ServiceWorkerFetchDispatcher::~ServiceWorkerFetchDispatcher() {}
+ServiceWorkerFetchDispatcher::~ServiceWorkerFetchDispatcher() {
+ if (!did_complete_)
+ net_log_.EndEvent(net::NetLog::TYPE_SERVICE_WORKER_DISPATCH_FETCH_EVENT);
+}
void ServiceWorkerFetchDispatcher::Run() {
DCHECK(version_->status() == ServiceWorkerVersion::ACTIVATING ||
@@ -54,82 +132,119 @@ void ServiceWorkerFetchDispatcher::Run() {
<< version_->status();
if (version_->status() == ServiceWorkerVersion::ACTIVATING) {
+ net_log_.BeginEvent(net::NetLog::TYPE_SERVICE_WORKER_WAIT_FOR_ACTIVATION);
version_->RegisterStatusChangeCallback(
- base::Bind(&ServiceWorkerFetchDispatcher::DidWaitActivation,
+ base::Bind(&ServiceWorkerFetchDispatcher::DidWaitForActivation,
weak_factory_.GetWeakPtr()));
return;
}
- DidWaitActivation();
+ StartWorker();
+}
+
+void ServiceWorkerFetchDispatcher::DidWaitForActivation() {
+ net_log_.EndEvent(net::NetLog::TYPE_SERVICE_WORKER_WAIT_FOR_ACTIVATION);
+ StartWorker();
}
-void ServiceWorkerFetchDispatcher::DidWaitActivation() {
+void ServiceWorkerFetchDispatcher::StartWorker() {
+ // We might be REDUNDANT if a new worker started activating and kicked us out
+ // before we could finish activation.
if (version_->status() != ServiceWorkerVersion::ACTIVATED) {
- DCHECK_EQ(ServiceWorkerVersion::INSTALLED, version_->status());
- DidFailActivation();
+ DCHECK_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
+ DidFail(SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED);
return;
}
+
+ if (version_->running_status() == EmbeddedWorkerStatus::RUNNING) {
+ DispatchFetchEvent();
+ return;
+ }
+
+ net_log_.BeginEvent(net::NetLog::TYPE_SERVICE_WORKER_START_WORKER);
version_->RunAfterStartWorker(
- GetEventType(),
- base::Bind(&ServiceWorkerFetchDispatcher::DispatchFetchEvent,
- weak_factory_.GetWeakPtr()),
- base::Bind(&ServiceWorkerFetchDispatcher::DidFail,
+ GetEventType(), base::Bind(&ServiceWorkerFetchDispatcher::DidStartWorker,
+ weak_factory_.GetWeakPtr()),
+ base::Bind(&ServiceWorkerFetchDispatcher::DidFailToStartWorker,
weak_factory_.GetWeakPtr()));
}
-void ServiceWorkerFetchDispatcher::DidFailActivation() {
- // The previous activation seems to have failed, abort the step
- // with activate error. (The error should be separately reported
- // to the associated documents and association must be dropped
- // at this point)
- DidFinish(SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED,
- SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
- ServiceWorkerResponse());
+void ServiceWorkerFetchDispatcher::DidStartWorker() {
+ net_log_.EndEvent(net::NetLog::TYPE_SERVICE_WORKER_START_WORKER);
+ DispatchFetchEvent();
+}
+
+void ServiceWorkerFetchDispatcher::DidFailToStartWorker(
+ ServiceWorkerStatusCode status) {
+ EndNetLogEventWithServiceWorkerStatus(
+ net_log_, net::NetLog::TYPE_SERVICE_WORKER_START_WORKER, status);
+ DidFail(status);
}
void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
- DCHECK_EQ(ServiceWorkerVersion::RUNNING, version_->running_status())
+ DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status())
<< "Worker stopped too soon after it was started.";
DCHECK(!prepare_callback_.is_null());
base::Closure prepare_callback = prepare_callback_;
prepare_callback.Run();
- int request_id = version_->StartRequest(
- GetEventType(), base::Bind(&ServiceWorkerFetchDispatcher::DidFail,
- weak_factory_.GetWeakPtr()));
- version_->DispatchEvent<ServiceWorkerHostMsg_FetchEventFinished>(
- request_id, ServiceWorkerMsg_FetchEvent(request_id, *request_.get()),
- base::Bind(&ServiceWorkerFetchDispatcher::DidFinish,
+ net_log_.BeginEvent(net::NetLog::TYPE_SERVICE_WORKER_FETCH_EVENT);
+ int response_id = version_->StartRequest(
+ GetEventType(),
+ base::Bind(&ServiceWorkerFetchDispatcher::DidFailToDispatch,
weak_factory_.GetWeakPtr()));
+ int event_finish_id = version_->StartRequest(
+ FetchTypeToWaitUntilEventType(request_->fetch_type),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+
+ ResponseCallback* response_callback =
+ new ResponseCallback(weak_factory_.GetWeakPtr(), version_.get());
+ version_->RegisterRequestCallback<ServiceWorkerHostMsg_FetchEventResponse>(
+ response_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()));
}
-void ServiceWorkerFetchDispatcher::DidPrepare() {
- DCHECK(!prepare_callback_.is_null());
- base::Closure prepare_callback = prepare_callback_;
- prepare_callback.Run();
+void ServiceWorkerFetchDispatcher::DidFailToDispatch(
+ ServiceWorkerStatusCode status) {
+ EndNetLogEventWithServiceWorkerStatus(
+ net_log_, net::NetLog::TYPE_SERVICE_WORKER_FETCH_EVENT, status);
+ DidFail(status);
}
void ServiceWorkerFetchDispatcher::DidFail(ServiceWorkerStatusCode status) {
- DCHECK(!fetch_callback_.is_null());
- FetchCallback fetch_callback = fetch_callback_;
- scoped_refptr<ServiceWorkerVersion> version = version_;
- fetch_callback.Run(status, SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
- ServiceWorkerResponse(), version);
+ DCHECK_NE(SERVICE_WORKER_OK, status);
+ Complete(status, SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
+ ServiceWorkerResponse());
}
void ServiceWorkerFetchDispatcher::DidFinish(
int request_id,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response) {
- const bool handled =
- (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE);
- if (!version_->FinishRequest(request_id, handled))
- NOTREACHED() << "Should only receive one reply per event";
+ net_log_.EndEvent(net::NetLog::TYPE_SERVICE_WORKER_FETCH_EVENT);
+ Complete(SERVICE_WORKER_OK, fetch_result, response);
+}
+void ServiceWorkerFetchDispatcher::Complete(
+ ServiceWorkerStatusCode status,
+ ServiceWorkerFetchEventResult fetch_result,
+ const ServiceWorkerResponse& response) {
DCHECK(!fetch_callback_.is_null());
+
+ did_complete_ = true;
+ net_log_.EndEvent(
+ net::NetLog::TYPE_SERVICE_WORKER_DISPATCH_FETCH_EVENT,
+ base::Bind(&NetLogFetchEventCallback, status, fetch_result));
+
FetchCallback fetch_callback = fetch_callback_;
scoped_refptr<ServiceWorkerVersion> version = version_;
- fetch_callback.Run(SERVICE_WORKER_OK, fetch_result, response, version);
+ fetch_callback.Run(status, fetch_result, response, version);
}
ServiceWorkerMetrics::EventType ServiceWorkerFetchDispatcher::GetEventType()
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 31d0bc1be72..b1010c7aa9d 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -13,6 +13,7 @@
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/resource_type.h"
+#include "net/log/net_log.h"
namespace content {
@@ -31,31 +32,43 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
std::unique_ptr<ServiceWorkerFetchRequest> request,
ServiceWorkerVersion* version,
ResourceType resource_type,
+ const net::BoundNetLog& net_log,
const base::Closure& prepare_callback,
const FetchCallback& fetch_callback);
~ServiceWorkerFetchDispatcher();
// Dispatches a fetch event to the |version| given in ctor, and fires
- // |callback| (also given in ctor) when finishes.
+ // |fetch_callback| (also given in ctor) when finishes. It runs
+ // |prepare_callback| as an intermediate step once the version is activated
+ // and running.
void Run();
private:
- void DidWaitActivation();
- void DidFailActivation();
+ class ResponseCallback;
+
+ void DidWaitForActivation();
+ void StartWorker();
+ void DidStartWorker();
+ void DidFailToStartWorker(ServiceWorkerStatusCode status);
void DispatchFetchEvent();
- void DidPrepare();
+ void DidFailToDispatch(ServiceWorkerStatusCode status);
void DidFail(ServiceWorkerStatusCode status);
void DidFinish(int request_id,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response);
+ void Complete(ServiceWorkerStatusCode status,
+ ServiceWorkerFetchEventResult fetch_result,
+ const ServiceWorkerResponse& response);
ServiceWorkerMetrics::EventType GetEventType() const;
scoped_refptr<ServiceWorkerVersion> version_;
+ net::BoundNetLog net_log_;
base::Closure prepare_callback_;
FetchCallback fetch_callback_;
std::unique_ptr<ServiceWorkerFetchRequest> request_;
ResourceType resource_type_;
+ bool did_complete_;
base::WeakPtrFactory<ServiceWorkerFetchDispatcher> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFetchDispatcher);
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 0bd9e15c6f2..d5a2109d640 100644
--- a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <tuple>
#include <vector>
#include "base/macros.h"
@@ -36,8 +37,8 @@ void VerifyStateChangedMessage(int expected_handle_id,
ServiceWorkerMsg_ServiceWorkerStateChanged::Param param;
ASSERT_TRUE(ServiceWorkerMsg_ServiceWorkerStateChanged::Read(
message, &param));
- EXPECT_EQ(expected_handle_id, base::get<1>(param));
- EXPECT_EQ(expected_state, base::get<2>(param));
+ EXPECT_EQ(expected_handle_id, std::get<1>(param));
+ EXPECT_EQ(expected_state, std::get<2>(param));
}
} // namespace
diff --git a/chromium/content/browser/service_worker/service_worker_info.cc b/chromium/content/browser/service_worker/service_worker_info.cc
index 0f4a4c5d9e7..47e0d139631 100644
--- a/chromium/content/browser/service_worker/service_worker_info.cc
+++ b/chromium/content/browser/service_worker/service_worker_info.cc
@@ -4,6 +4,7 @@
#include "content/browser/service_worker/service_worker_info.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/child_process_host.h"
#include "ipc/ipc_message.h"
@@ -25,7 +26,7 @@ ServiceWorkerVersionInfo::ClientInfo::~ClientInfo() {
}
ServiceWorkerVersionInfo::ServiceWorkerVersionInfo()
- : running_status(ServiceWorkerVersion::STOPPED),
+ : running_status(EmbeddedWorkerStatus::STOPPED),
status(ServiceWorkerVersion::NEW),
registration_id(kInvalidServiceWorkerRegistrationId),
version_id(kInvalidServiceWorkerVersionId),
@@ -34,7 +35,7 @@ ServiceWorkerVersionInfo::ServiceWorkerVersionInfo()
devtools_agent_route_id(MSG_ROUTING_NONE) {}
ServiceWorkerVersionInfo::ServiceWorkerVersionInfo(
- ServiceWorkerVersion::RunningStatus running_status,
+ EmbeddedWorkerStatus running_status,
ServiceWorkerVersion::Status status,
const GURL& script_url,
int64_t registration_id,
diff --git a/chromium/content/browser/service_worker/service_worker_info.h b/chromium/content/browser/service_worker/service_worker_info.h
index 8de17feaa24..e2708780340 100644
--- a/chromium/content/browser/service_worker/service_worker_info.h
+++ b/chromium/content/browser/service_worker/service_worker_info.h
@@ -16,6 +16,8 @@
namespace content {
+enum class EmbeddedWorkerStatus;
+
struct CONTENT_EXPORT ServiceWorkerVersionInfo {
public:
struct CONTENT_EXPORT ClientInfo {
@@ -29,7 +31,7 @@ struct CONTENT_EXPORT ServiceWorkerVersionInfo {
};
ServiceWorkerVersionInfo();
- ServiceWorkerVersionInfo(ServiceWorkerVersion::RunningStatus running_status,
+ ServiceWorkerVersionInfo(EmbeddedWorkerStatus running_status,
ServiceWorkerVersion::Status status,
const GURL& script_url,
int64_t registration_id,
@@ -40,7 +42,7 @@ struct CONTENT_EXPORT ServiceWorkerVersionInfo {
ServiceWorkerVersionInfo(const ServiceWorkerVersionInfo& other);
~ServiceWorkerVersionInfo();
- ServiceWorkerVersion::RunningStatus running_status;
+ EmbeddedWorkerStatus running_status;
ServiceWorkerVersion::Status status;
GURL script_url;
int64_t registration_id;
diff --git a/chromium/content/browser/service_worker/service_worker_internals_ui.cc b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
index 5b410efd7bf..3d546077020 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
@@ -5,6 +5,7 @@
#include "content/browser/service_worker/service_worker_internals_ui.h"
#include <stdint.h>
+
#include <string>
#include <utility>
#include <vector>
@@ -15,6 +16,7 @@
#include "base/values.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/service_worker_devtools_manager.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
@@ -58,7 +60,7 @@ void OperationCompleteCallback(WeakPtr<ServiceWorkerInternalsUI> internals,
}
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (internals) {
- internals->web_ui()->CallJavascriptFunction(
+ internals->web_ui()->CallJavascriptFunctionUnsafe(
"serviceworker.onOperationComplete",
FundamentalValue(static_cast<int>(status)),
FundamentalValue(callback_id));
@@ -113,16 +115,16 @@ base::ProcessId GetRealProcessId(int process_host_id) {
void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
DictionaryValue* info) {
switch (version.running_status) {
- case ServiceWorkerVersion::STOPPED:
+ case EmbeddedWorkerStatus::STOPPED:
info->SetString("running_status", "STOPPED");
break;
- case ServiceWorkerVersion::STARTING:
+ case EmbeddedWorkerStatus::STARTING:
info->SetString("running_status", "STARTING");
break;
- case ServiceWorkerVersion::RUNNING:
+ case EmbeddedWorkerStatus::RUNNING:
info->SetString("running_status", "RUNNING");
break;
- case ServiceWorkerVersion::STOPPING:
+ case EmbeddedWorkerStatus::STOPPING:
info->SetString("running_status", "STOPPING");
break;
}
@@ -164,7 +166,8 @@ ListValue* GetRegistrationListValue(
it != registrations.end();
++it) {
const ServiceWorkerRegistrationInfo& registration = *it;
- DictionaryValue* registration_info = new DictionaryValue();
+ std::unique_ptr<class base::DictionaryValue> registration_info(
+ new DictionaryValue());
registration_info->SetString("scope", registration.pattern.spec());
registration_info->SetString(
"registration_id", base::Int64ToString(registration.registration_id));
@@ -183,7 +186,7 @@ ListValue* GetRegistrationListValue(
registration_info->Set("waiting", waiting_info);
}
- result->Append(registration_info);
+ result->Append(std::move(registration_info));
}
return result;
}
@@ -239,8 +242,8 @@ void DidGetRegistrations(
args.push_back(GetRegistrationListValue(stored_registrations));
args.push_back(new FundamentalValue(partition_id));
args.push_back(new StringValue(context_path.value()));
- internals->web_ui()->CallJavascriptFunction("serviceworker.onPartitionData",
- args.get());
+ internals->web_ui()->CallJavascriptFunctionUnsafe(
+ "serviceworker.onPartitionData", args.get());
}
} // namespace
@@ -253,18 +256,17 @@ class ServiceWorkerInternalsUI::PartitionObserver
~PartitionObserver() override {}
// ServiceWorkerContextObserver overrides:
void OnRunningStateChanged(int64_t version_id,
- ServiceWorkerVersion::RunningStatus) override {
+ EmbeddedWorkerStatus) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- web_ui_->CallJavascriptFunction(
+ web_ui_->CallJavascriptFunctionUnsafe(
"serviceworker.onRunningStateChanged", FundamentalValue(partition_id_),
StringValue(base::Int64ToString(version_id)));
}
void OnVersionStateChanged(int64_t version_id,
ServiceWorkerVersion::Status) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- web_ui_->CallJavascriptFunction(
- "serviceworker.onVersionStateChanged",
- FundamentalValue(partition_id_),
+ web_ui_->CallJavascriptFunctionUnsafe(
+ "serviceworker.onVersionStateChanged", FundamentalValue(partition_id_),
StringValue(base::Int64ToString(version_id)));
}
void OnErrorReported(int64_t version_id,
@@ -283,8 +285,8 @@ class ServiceWorkerInternalsUI::PartitionObserver
value->SetInteger("columnNumber", info.column_number);
value->SetString("sourceURL", info.source_url.spec());
args.push_back(value.release());
- web_ui_->CallJavascriptFunction("serviceworker.onErrorReported",
- args.get());
+ web_ui_->CallJavascriptFunctionUnsafe("serviceworker.onErrorReported",
+ args.get());
}
void OnReportConsoleMessage(int64_t version_id,
int process_id,
@@ -303,19 +305,19 @@ class ServiceWorkerInternalsUI::PartitionObserver
value->SetInteger("lineNumber", message.line_number);
value->SetString("sourceURL", message.source_url.spec());
args.push_back(value.release());
- web_ui_->CallJavascriptFunction("serviceworker.onConsoleMessageReported",
- args.get());
+ web_ui_->CallJavascriptFunctionUnsafe(
+ "serviceworker.onConsoleMessageReported", args.get());
}
void OnRegistrationStored(int64_t registration_id,
const GURL& pattern) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- web_ui_->CallJavascriptFunction("serviceworker.onRegistrationStored",
- StringValue(pattern.spec()));
+ web_ui_->CallJavascriptFunctionUnsafe("serviceworker.onRegistrationStored",
+ StringValue(pattern.spec()));
}
void OnRegistrationDeleted(int64_t registration_id,
const GURL& pattern) override {
- web_ui_->CallJavascriptFunction("serviceworker.onRegistrationDeleted",
- StringValue(pattern.spec()));
+ web_ui_->CallJavascriptFunctionUnsafe("serviceworker.onRegistrationDeleted",
+ StringValue(pattern.spec()));
}
int partition_id() const { return partition_id_; }
@@ -386,7 +388,7 @@ void ServiceWorkerInternalsUI::GetOptions(const ListValue* args) {
options.SetBoolean("debug_on_start",
ServiceWorkerDevToolsManager::GetInstance()
->debug_service_worker_on_start());
- web_ui()->CallJavascriptFunction("serviceworker.onOptions", options);
+ web_ui()->CallJavascriptFunctionUnsafe("serviceworker.onOptions", options);
}
void ServiceWorkerInternalsUI::SetOption(const ListValue* args) {
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 2d71520b7f9..d06955f01f6 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -3,15 +3,19 @@
// found in the LICENSE file.
#include <stdint.h>
+#include <tuple>
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/test/test_simple_task_runner.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
#include "content/browser/service_worker/service_worker_registration.h"
@@ -19,6 +23,7 @@
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_test_sink.h"
#include "net/base/io_buffer.h"
@@ -654,15 +659,14 @@ TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
version->SetStatus(ServiceWorkerVersion::INSTALLED);
registration->SetWaitingVersion(version);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING,
- version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status());
RunUnregisterJob(GURL("http://www.example.com/"));
// The version should be stopped since there is no controllee after
// unregistration.
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
}
@@ -675,14 +679,14 @@ TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
ASSERT_TRUE(registration.get());
scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
RunUnregisterJob(GURL("http://www.example.com/"));
// The version should be stopped since there is no controllee after
// unregistration.
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
}
@@ -699,20 +703,20 @@ TEST_F(ServiceWorkerJobTest,
registration->active_version()->AddControllee(host.get());
scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
RunUnregisterJob(GURL("http://www.example.com/"));
// The version should be running since there is still a controllee.
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
registration->active_version()->RemoveControllee(host.get());
base::RunLoop().RunUntilIdle();
// The version should be stopped since there is no controllee.
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
}
@@ -726,7 +730,7 @@ const std::string kScript("script.js");
void RunNestedUntilIdle() {
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
void OnIOComplete(int* rv_out, int rv) {
@@ -1226,6 +1230,9 @@ TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(pattern, script1);
+ scoped_refptr<base::TestSimpleTaskRunner> runner(
+ new base::TestSimpleTaskRunner());
+ registration->SetTaskRunnerForTest(runner);
// Add a controllee and queue an unregister to force the uninstalling state.
std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
@@ -1246,7 +1253,7 @@ TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
// Verify the new version is installed but not activated yet.
EXPECT_EQ(NULL, registration->installing_version());
EXPECT_TRUE(new_version);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
old_version->RemoveControllee(host.get());
@@ -1259,7 +1266,11 @@ TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
EXPECT_EQ(NULL, registration->installing_version());
EXPECT_EQ(NULL, registration->waiting_version());
EXPECT_EQ(new_version, registration->active_version());
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, new_version->status());
+
+ runner->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
}
@@ -1294,9 +1305,9 @@ TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
EXPECT_TRUE(registration->is_uninstalling());
EXPECT_EQ(old_version, registration->active_version());
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, old_version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, old_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, old_version->status());
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
old_version->RemoveControllee(host.get());
@@ -1305,9 +1316,9 @@ TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
EXPECT_FALSE(registration->is_uninstalling());
EXPECT_TRUE(registration->is_uninstalled());
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, old_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, new_version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, new_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, new_version->status());
}
@@ -1318,6 +1329,9 @@ TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(pattern, script1);
+ scoped_refptr<base::TestSimpleTaskRunner> runner(
+ new base::TestSimpleTaskRunner());
+ registration->SetTaskRunnerForTest(runner);
// Add a controllee and queue an unregister to force the uninstalling state.
std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
@@ -1351,7 +1365,11 @@ TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
EXPECT_EQ(NULL, registration->installing_version());
EXPECT_EQ(NULL, registration->waiting_version());
EXPECT_EQ(new_version, registration->active_version());
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, new_version->status());
+
+ runner->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
}
@@ -1363,6 +1381,9 @@ TEST_F(ServiceWorkerJobTest, RegisterMultipleTimesWhileUninstalling) {
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(pattern, script1);
+ scoped_refptr<base::TestSimpleTaskRunner> runner(
+ new base::TestSimpleTaskRunner());
+ registration->SetTaskRunnerForTest(runner);
// Add a controllee and queue an unregister to force the uninstalling state.
std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
@@ -1400,7 +1421,11 @@ TEST_F(ServiceWorkerJobTest, RegisterMultipleTimesWhileUninstalling) {
EXPECT_EQ(NULL, registration->installing_version());
EXPECT_EQ(NULL, registration->waiting_version());
EXPECT_EQ(third_version, registration->active_version());
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, third_version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, third_version->status());
+
+ runner->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, third_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, third_version->status());
}
@@ -1415,9 +1440,9 @@ class EventCallbackHelper : public EmbeddedWorkerTestHelper {
int request_id) override {
if (!install_callback_.is_null())
install_callback_.Run();
- SimulateSend(
- new ServiceWorkerHostMsg_InstallEventFinished(
- embedded_worker_id, request_id, install_event_result_));
+ SimulateSend(new ServiceWorkerHostMsg_InstallEventFinished(
+ embedded_worker_id, request_id, install_event_result_,
+ has_fetch_handler_));
}
void OnActivateEvent(int embedded_worker_id, int request_id) override {
SimulateSend(
@@ -1434,11 +1459,15 @@ class EventCallbackHelper : public EmbeddedWorkerTestHelper {
void set_activate_event_result(blink::WebServiceWorkerEventResult result) {
activate_event_result_ = result;
}
+ void set_has_fetch_handler(bool has_fetch_handler) {
+ has_fetch_handler_ = has_fetch_handler;
+ }
private:
base::Closure install_callback_;
blink::WebServiceWorkerEventResult install_event_result_;
blink::WebServiceWorkerEventResult activate_event_result_;
+ bool has_fetch_handler_ = true;
};
TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) {
@@ -1475,7 +1504,7 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) {
EXPECT_EQ(NULL, registration->installing_version());
EXPECT_EQ(NULL, registration->waiting_version());
EXPECT_EQ(new_version, registration->active_version());
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
EXPECT_EQ(registration, FindRegistrationForPattern(pattern));
@@ -1511,7 +1540,7 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) {
EXPECT_FALSE(registration->is_uninstalling());
EXPECT_TRUE(registration->is_uninstalled());
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, old_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
@@ -1547,12 +1576,33 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
EXPECT_FALSE(registration->is_uninstalling());
EXPECT_FALSE(registration->is_uninstalled());
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, old_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
FindRegistrationForPattern(pattern, SERVICE_WORKER_OK);
}
+TEST_F(ServiceWorkerJobTest, HasFetchHandler) {
+ EventCallbackHelper* helper = new EventCallbackHelper;
+ helper_.reset(helper);
+
+ GURL pattern("http://www.example.com/");
+ GURL script("http://www.example.com/service_worker.js");
+ scoped_refptr<ServiceWorkerRegistration> registration;
+
+ helper->set_has_fetch_handler(true);
+ RunRegisterJob(pattern, script);
+ registration = FindRegistrationForPattern(pattern);
+ EXPECT_TRUE(registration->active_version()->has_fetch_handler());
+ RunUnregisterJob(pattern);
+
+ helper->set_has_fetch_handler(false);
+ RunRegisterJob(pattern, script);
+ registration = FindRegistrationForPattern(pattern);
+ EXPECT_FALSE(registration->active_version()->has_fetch_handler());
+ RunUnregisterJob(pattern);
+}
+
TEST_F(ServiceWorkerJobTest, Update_PauseAfterDownload) {
UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
helper_.reset(update_helper);
@@ -1567,7 +1617,7 @@ TEST_F(ServiceWorkerJobTest, Update_PauseAfterDownload) {
ASSERT_TRUE(start_msg);
EmbeddedWorkerMsg_StartWorker::Param param;
EmbeddedWorkerMsg_StartWorker::Read(start_msg, &param);
- EmbeddedWorkerMsg_StartWorker_Params start_params = base::get<0>(param);
+ EmbeddedWorkerMsg_StartWorker_Params start_params = std::get<0>(param);
EXPECT_FALSE(start_params.pause_after_download);
sink->ClearMessages();
}
@@ -1582,10 +1632,67 @@ TEST_F(ServiceWorkerJobTest, Update_PauseAfterDownload) {
ASSERT_TRUE(start_msg);
EmbeddedWorkerMsg_StartWorker::Param param;
EmbeddedWorkerMsg_StartWorker::Read(start_msg, &param);
- EmbeddedWorkerMsg_StartWorker_Params start_params = base::get<0>(param);
+ EmbeddedWorkerMsg_StartWorker_Params start_params = std::get<0>(param);
EXPECT_TRUE(start_params.pause_after_download);
sink->ClearMessages();
}
}
+// 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) {
+ UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
+ helper_.reset(update_helper);
+ GURL pattern("http://www.example.com/");
+ GURL script("http://www.example.com/service_worker.js");
+
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ RunRegisterJob(pattern, script);
+ scoped_refptr<base::TestSimpleTaskRunner> runner(
+ new base::TestSimpleTaskRunner());
+ registration->SetTaskRunnerForTest(runner);
+
+ // Add a controllee.
+ std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ scoped_refptr<ServiceWorkerVersion> first_version =
+ registration->active_version();
+ first_version->AddControllee(host.get());
+
+ // Update. The new version should be waiting.
+ registration->AddListener(update_helper);
+ first_version->StartUpdate();
+ base::RunLoop().RunUntilIdle();
+ scoped_refptr<ServiceWorkerVersion> new_version =
+ registration->waiting_version();
+ ASSERT_TRUE(new_version);
+ EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
+
+ // Stop the worker so that it must start again when activation is attempted.
+ // (This is not strictly necessary to exercise the codepath, but it makes it
+ // easy to cause a failure with set_force_start_worker_failure after
+ // shutdown is simulated. Otherwise our test helper often fails on
+ // DCHECK(context)).
+ new_version->StopWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+
+ // Remove the controllee. The new version should be activating, and delayed
+ // until the runner runs again.
+ first_version->RemoveControllee(host.get());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(new_version.get(), registration->active_version());
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, new_version->status());
+
+ // Shutdown.
+ update_helper->context()->wrapper()->Shutdown();
+ update_helper->set_force_start_worker_failure(true);
+
+ // Allow the activation to continue. It will fail, and the worker
+ // should not be promoted to ACTIVATED because failure occur
+ // during shutdown.
+ runner->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(new_version.get(), registration->active_version());
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, new_version->status());
+ registration->RemoveListener(update_helper);
+}
+
} // 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 a481b8bf035..07585564f47 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -10,6 +10,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/strings/string_util.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
@@ -21,6 +22,8 @@ namespace {
std::string StartSituationToSuffix(
ServiceWorkerMetrics::StartSituation situation) {
+ // Don't change these returned strings. They are written (in hashed form) into
+ // logs.
switch (situation) {
case ServiceWorkerMetrics::StartSituation::DURING_STARTUP:
return "_DuringStartup";
@@ -34,6 +37,73 @@ std::string StartSituationToSuffix(
return "_Unknown";
}
+std::string EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
+ // Don't change these returned strings. They are written (in hashed form) into
+ // logs.
+ switch (event_type) {
+ case ServiceWorkerMetrics::EventType::ACTIVATE:
+ return "_ACTIVATE";
+ case ServiceWorkerMetrics::EventType::INSTALL:
+ return "_INSTALL";
+ case ServiceWorkerMetrics::EventType::SYNC:
+ return "_SYNC";
+ case ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK:
+ return "_NOTIFICATION_CLICK";
+ case ServiceWorkerMetrics::EventType::PUSH:
+ return "_PUSH";
+ case ServiceWorkerMetrics::EventType::MESSAGE:
+ return "_MESSAGE";
+ case ServiceWorkerMetrics::EventType::NOTIFICATION_CLOSE:
+ return "_NOTIFICATION_CLOSE";
+ case ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME:
+ return "_FETCH_MAIN_FRAME";
+ case ServiceWorkerMetrics::EventType::FETCH_SUB_FRAME:
+ return "_FETCH_SUB_FRAME";
+ case ServiceWorkerMetrics::EventType::FETCH_SHARED_WORKER:
+ return "_FETCH_SHARED_WORKER";
+ case ServiceWorkerMetrics::EventType::FETCH_SUB_RESOURCE:
+ return "_FETCH_SUB_RESOURCE";
+ case ServiceWorkerMetrics::EventType::UNKNOWN:
+ return "_UNKNOWN";
+ case ServiceWorkerMetrics::EventType::FOREIGN_FETCH:
+ return "_FOREIGN_FETCH";
+ case ServiceWorkerMetrics::EventType::FETCH_WAITUNTIL:
+ return "_FETCH_WAITUNTIL";
+ case ServiceWorkerMetrics::EventType::FOREIGN_FETCH_WAITUNTIL:
+ return "_FOREIGN_FETCH_WAITUNTIL";
+ case ServiceWorkerMetrics::EventType::NUM_TYPES:
+ NOTREACHED() << static_cast<int>(event_type);
+ }
+ return "_UNKNOWN";
+}
+
+std::string GetWorkerPreparationSuffix(
+ EmbeddedWorkerStatus initial_worker_status,
+ ServiceWorkerMetrics::StartSituation start_situation) {
+ switch (initial_worker_status) {
+ case EmbeddedWorkerStatus::STOPPED: {
+ switch (start_situation) {
+ case ServiceWorkerMetrics::StartSituation::DURING_STARTUP:
+ return "_StartWorkerDuringStartup";
+ case ServiceWorkerMetrics::StartSituation::NEW_PROCESS:
+ return "_StartWorkerNewProcess";
+ case ServiceWorkerMetrics::StartSituation::EXISTING_PROCESS:
+ return "_StartWorkerExistingProcess";
+ default:
+ NOTREACHED() << static_cast<int>(start_situation);
+ }
+ }
+ case EmbeddedWorkerStatus::STARTING:
+ return "_StartingWorker";
+ case EmbeddedWorkerStatus::RUNNING:
+ return "_RunningWorker";
+ case EmbeddedWorkerStatus::STOPPING:
+ return "_StoppingWorker";
+ }
+ NOTREACHED();
+ return "_UNKNOWN";
+}
+
// Use this for histograms with dynamically generated names, which
// otherwise can't use the UMA_HISTOGRAM macro without code duplication.
void RecordSuffixedTimeHistogram(const std::string& name,
@@ -48,6 +118,20 @@ void RecordSuffixedTimeHistogram(const std::string& name,
histogram_pointer->AddTime(sample);
}
+// Use this for histograms with dynamically generated names, which
+// otherwise can't use the UMA_HISTOGRAM macro without code duplication.
+void RecordSuffixedStatusHistogram(const std::string& name,
+ const std::string& suffix,
+ ServiceWorkerStatusCode status) {
+ const std::string name_with_suffix = name + suffix;
+ // This unrolls UMA_HISTOGRAM_ENUMERATION.
+ base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet(
+ name_with_suffix, 1, SERVICE_WORKER_ERROR_MAX_VALUE,
+ SERVICE_WORKER_ERROR_MAX_VALUE + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ histogram_pointer->Add(status);
+}
+
void RecordURLMetricOnUI(const GURL& url) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GetContentClient()->browser()->RecordURLMetric(
@@ -106,6 +190,10 @@ const char* ServiceWorkerMetrics::EventTypeToString(EventType event_type) {
return "Unknown";
case EventType::FOREIGN_FETCH:
return "Foreign Fetch";
+ case EventType::FETCH_WAITUNTIL:
+ return "Fetch WaitUntil";
+ case EventType::FOREIGN_FETCH_WAITUNTIL:
+ return "Foreign Fetch WaitUntil";
case EventType::NUM_TYPES:
break;
}
@@ -172,10 +260,21 @@ void ServiceWorkerMetrics::RecordDeleteAndStartOverResult(
result, NUM_DELETE_AND_START_OVER_RESULT_TYPES);
}
-void ServiceWorkerMetrics::CountControlledPageLoad(const GURL& url) {
+void ServiceWorkerMetrics::CountControlledPageLoad(const GURL& url,
+ bool has_fetch_handler,
+ bool is_main_frame_load) {
Site site = SiteFromURL(url);
+ if (site == Site::OTHER) {
+ site = (has_fetch_handler) ? Site::WITH_FETCH_HANDLER
+ : Site::WITHOUT_FETCH_HANDLER;
+ }
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.PageLoad", static_cast<int>(site),
static_cast<int>(Site::NUM_TYPES));
+ if (is_main_frame_load) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.MainFramePageLoad",
+ static_cast<int>(site),
+ static_cast<int>(Site::NUM_TYPES));
+ }
if (ShouldExcludeSiteFromHistogram(site))
return;
@@ -195,77 +294,8 @@ void ServiceWorkerMetrics::RecordStartWorkerStatus(
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status,
SERVICE_WORKER_ERROR_MAX_VALUE);
- switch (purpose) {
- case EventType::ACTIVATE:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_ACTIVATE", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::INSTALL:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_INSTALL", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::SYNC:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_SYNC", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::NOTIFICATION_CLICK:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_NOTIFICATION_CLICK",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::PUSH:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_PUSH", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::MESSAGE:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_MESSAGE", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::NOTIFICATION_CLOSE:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_NOTIFICATION_CLOSE",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::FETCH_MAIN_FRAME:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_FETCH_MAIN_FRAME", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::FETCH_SUB_FRAME:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_FETCH_SUB_FRAME", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::FETCH_SHARED_WORKER:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_FETCH_SHARED_WORKER",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::FETCH_SUB_RESOURCE:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_FETCH_SUB_RESOURCE",
- status, SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::UNKNOWN:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_UNKNOWN", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::FOREIGN_FETCH:
- UMA_HISTOGRAM_ENUMERATION(
- "ServiceWorker.StartWorker.StatusByPurpose_FOREIGN_FETCH", status,
- SERVICE_WORKER_ERROR_MAX_VALUE);
- break;
- case EventType::NUM_TYPES:
- NOTREACHED();
- break;
- }
-
+ RecordSuffixedStatusHistogram("ServiceWorker.StartWorker.StatusByPurpose",
+ EventTypeToSuffix(purpose), status);
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose",
static_cast<int>(purpose),
static_cast<int>(EventType::NUM_TYPES));
@@ -276,20 +306,36 @@ void ServiceWorkerMetrics::RecordStartWorkerStatus(
}
}
-void ServiceWorkerMetrics::RecordStartWorkerTime(
- base::TimeDelta time,
- bool is_installed,
- StartSituation start_situation) {
+void ServiceWorkerMetrics::RecordStartWorkerTime(base::TimeDelta time,
+ bool is_installed,
+ StartSituation start_situation,
+ EventType purpose) {
if (is_installed) {
std::string name = "ServiceWorker.StartWorker.Time";
UMA_HISTOGRAM_MEDIUM_TIMES(name, time);
RecordSuffixedTimeHistogram(name, StartSituationToSuffix(start_situation),
time);
+ RecordSuffixedTimeHistogram(
+ "ServiceWorker.StartWorker.Time",
+ StartSituationToSuffix(start_situation) + EventTypeToSuffix(purpose),
+ time);
} else {
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartNewWorker.Time", time);
}
}
+void ServiceWorkerMetrics::RecordActivatedWorkerPreparationTimeForMainFrame(
+ base::TimeDelta time,
+ EmbeddedWorkerStatus initial_worker_status,
+ StartSituation start_situation) {
+ std::string name =
+ "ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time";
+ UMA_HISTOGRAM_MEDIUM_TIMES(name, time);
+ RecordSuffixedTimeHistogram(
+ name, GetWorkerPreparationSuffix(initial_worker_status, start_situation),
+ time);
+}
+
void ServiceWorkerMetrics::RecordWorkerStopped(StopStatus status) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.WorkerStopped",
static_cast<int>(status),
@@ -301,9 +347,17 @@ void ServiceWorkerMetrics::RecordStopWorkerTime(base::TimeDelta time) {
}
void ServiceWorkerMetrics::RecordActivateEventStatus(
- ServiceWorkerStatusCode status) {
+ ServiceWorkerStatusCode status,
+ bool is_shutdown) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.ActivateEventStatus", status,
SERVICE_WORKER_ERROR_MAX_VALUE);
+ if (is_shutdown) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.ActivateEventStatus_InShutdown",
+ status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.ActivateEventStatus_NotInShutdown",
+ status, SERVICE_WORKER_ERROR_MAX_VALUE);
+ }
}
void ServiceWorkerMetrics::RecordInstallEventStatus(
@@ -371,6 +425,10 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
time);
}
break;
+ case EventType::FETCH_WAITUNTIL:
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.FetchEvent.WaitUntil.Time",
+ time);
+ break;
case EventType::FOREIGN_FETCH:
if (was_handled) {
UMA_HISTOGRAM_MEDIUM_TIMES(
@@ -380,6 +438,10 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
"ServiceWorker.ForeignFetchEvent.Fallback.Time", time);
}
break;
+ case EventType::FOREIGN_FETCH_WAITUNTIL:
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.ForeignFetchEvent.WaitUntil.Time", time);
+ break;
case EventType::SYNC:
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.BackgroundSyncEvent.Time",
time);
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.h b/chromium/content/browser/service_worker/service_worker_metrics.h
index dd2372ad316..d4cc56e308d 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.h
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -16,6 +16,8 @@ class GURL;
namespace content {
+enum class EmbeddedWorkerStatus;
+
class ServiceWorkerMetrics {
public:
// Used for UMA. Append-only.
@@ -78,6 +80,13 @@ class ServiceWorkerMetrics {
};
// Used for UMA. Append-only.
+ // This class is used to indicate which event is fired/finished. Most events
+ // have only one request that starts the event and one response that finishes
+ // the event, but the fetch and the foreign fetch event have two responses, so
+ // there are two types of EventType to break down the measurement into two:
+ // FETCH/FOREIGN_FETCH and FETCH_WAITUNTIL/FOREIGN_FETCH_WAITUNTIL.
+ // Moreover, FETCH is separated into the four: MAIN_FRAME, SUB_FRAME,
+ // SHARED_WORKER and SUB_RESOURCE for more detailed UMA.
enum class EventType {
ACTIVATE = 0,
INSTALL = 1,
@@ -95,12 +104,20 @@ class ServiceWorkerMetrics {
FETCH_SUB_RESOURCE = 13,
UNKNOWN = 14, // Used when event type is not known.
FOREIGN_FETCH = 15,
+ FETCH_WAITUNTIL = 16,
+ FOREIGN_FETCH_WAITUNTIL = 17,
// Add new events to record here.
NUM_TYPES
};
// Used for UMA. Append only.
- enum class Site { OTHER, NEW_TAB_PAGE, NUM_TYPES };
+ enum class Site {
+ OTHER, // Obsolete
+ NEW_TAB_PAGE,
+ WITH_FETCH_HANDLER,
+ WITHOUT_FETCH_HANDLER,
+ NUM_TYPES
+ };
// Not used for UMA.
enum class StartSituation {
@@ -138,7 +155,9 @@ class ServiceWorkerMetrics {
static void RecordDeleteAndStartOverResult(DeleteAndStartOverResult result);
// Counts the number of page loads controlled by a Service Worker.
- static void CountControlledPageLoad(const GURL& url);
+ static void CountControlledPageLoad(const GURL& url,
+ bool has_fetch_handler,
+ bool is_main_frame_load);
// Records the result of trying to start a worker. |is_installed| indicates
// whether the version has been installed.
@@ -150,7 +169,15 @@ class ServiceWorkerMetrics {
// indicates whether the version has been installed.
static void RecordStartWorkerTime(base::TimeDelta time,
bool is_installed,
- StartSituation start_situation);
+ StartSituation start_situation,
+ EventType purpose);
+
+ // Records the time taken to prepare an activated Service Worker for a main
+ // frame fetch.
+ static void RecordActivatedWorkerPreparationTimeForMainFrame(
+ base::TimeDelta time,
+ EmbeddedWorkerStatus initial_worker_status,
+ StartSituation start_situation);
// Records the result of trying to stop a worker.
static void RecordWorkerStopped(StopStatus status);
@@ -158,7 +185,8 @@ class ServiceWorkerMetrics {
// Records the time taken to successfully stop a worker.
static void RecordStopWorkerTime(base::TimeDelta time);
- static void RecordActivateEventStatus(ServiceWorkerStatusCode status);
+ static void RecordActivateEventStatus(ServiceWorkerStatusCode status,
+ bool is_shutdown);
static void RecordInstallEventStatus(ServiceWorkerStatusCode status);
// Records how much of dispatched events are handled while a Service
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_handle.cc b/chromium/content/browser/service_worker/service_worker_navigation_handle.cc
deleted file mode 100644
index 2bc87a22fb5..00000000000
--- a/chromium/content/browser/service_worker/service_worker_navigation_handle.cc
+++ /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.
-
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
-
-#include "base/bind.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-ServiceWorkerNavigationHandle::ServiceWorkerNavigationHandle(
- ServiceWorkerContextWrapper* context_wrapper)
- : service_worker_provider_host_id_(kInvalidServiceWorkerProviderId),
- weak_factory_(this) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- core_ = new ServiceWorkerNavigationHandleCore(weak_factory_.GetWeakPtr(),
- context_wrapper);
-}
-
-ServiceWorkerNavigationHandle::~ServiceWorkerNavigationHandle() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // Delete the ServiceWorkerNavigationHandleCore on the IO thread.
- BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, core_);
-}
-
-void ServiceWorkerNavigationHandle::DidCreateServiceWorkerProviderHost(
- int service_worker_provider_host_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- service_worker_provider_host_id_ = service_worker_provider_host_id;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_handle.h b/chromium/content/browser/service_worker/service_worker_navigation_handle.h
deleted file mode 100644
index c5c69388cf7..00000000000
--- a/chromium/content/browser/service_worker/service_worker_navigation_handle.h
+++ /dev/null
@@ -1,78 +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_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-
-namespace content {
-
-class ServiceWorkerContextWrapper;
-class ServiceWorkerNavigationHandleCore;
-
-// This class is used to manage the lifetime of ServiceWorkerProviderHosts
-// created during navigation. This is a UI thread class, with a pendant class
-// on the IO thread, the ServiceWorkerNavigationHandleCore.
-//
-// The lifetime of the ServiceWorkerNavigationHandle, the
-// ServiceWorkerNavigationHandleCore and the ServiceWorkerProviderHost are the
-// following :
-// 1) We create a ServiceWorkerNavigationHandle on the UI thread with a
-// service worker provider id of -1. This also leads to the creation of a
-// ServiceWorkerNavigationHandleCore with an id of -1.
-//
-// 2) When the navigation request is sent to the IO thread, we include a
-// pointer to the ServiceWorkerNavigationHandleCore.
-//
-// 3) If we pre-create a ServiceWorkerProviderHost for this navigation, its
-// ownershipped is passed to the ServiceWorkerNavigationHandleCore. The
-// ServiceWorkerNavigationHandleCore id is updated.
-//
-// 4) The ServiceWorkerNavigationHandleCore informs the
-// ServiceWorkerNavigationHandle on the UI that the service worker provider
-// id was updated.
-//
-// 5) When the navigation is ready to commit, the NavigationRequest will
-// update the RequestNavigationParams based on the id from the
-// ServiceWorkerNavigationHandle.
-//
-// 6) If the commit leads to the creation of a ServiceWorkerNetworkProvider
-// in the renderer, a ServiceWorkerHostMsg_ProviderCreated will be received
-// in the browser. The ServiceWorkerDispatcherHost will retrieve the
-// ServiceWorkerProviderHost from the ServiceWorkerNavigationHandleCore and
-// put it in the ServiceWorkerContextCore map of ServiceWorkerProviderHosts.
-//
-// 7) When the navigation finishes, the ServiceWorkerNavigationHandle is
-// destroyed. The destructor of the ServiceWorkerNavigationHandle posts a
-// task to destroy the ServiceWorkerNavigationHandleCore on the IO thread.
-// This in turn leads to the destruction of an unclaimed
-// ServiceWorkerProviderHost.
-class ServiceWorkerNavigationHandle {
- public:
- explicit ServiceWorkerNavigationHandle(
- ServiceWorkerContextWrapper* context_wrapper);
- ~ServiceWorkerNavigationHandle();
-
- int service_worker_provider_host_id() const {
- return service_worker_provider_host_id_;
- }
- ServiceWorkerNavigationHandleCore* core() const { return core_; }
-
- // Called after a ServiceWorkerProviderHost with id
- // |service_worker_provider_host_id| was pre-created for the navigation on the
- // IO thread.
- void DidCreateServiceWorkerProviderHost(int service_worker_provider_host_id);
-
- private:
- int service_worker_provider_host_id_;
- ServiceWorkerNavigationHandleCore* core_;
- base::WeakPtrFactory<ServiceWorkerNavigationHandle> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerNavigationHandle);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_H_
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc b/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc
deleted file mode 100644
index 279461f8e8f..00000000000
--- a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc
+++ /dev/null
@@ -1,65 +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/service_worker/service_worker_navigation_handle_core.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
-#include "content/browser/service_worker/service_worker_provider_host.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-ServiceWorkerNavigationHandleCore::ServiceWorkerNavigationHandleCore(
- base::WeakPtr<ServiceWorkerNavigationHandle> ui_handle,
- ServiceWorkerContextWrapper* context_wrapper)
- : context_wrapper_(context_wrapper), ui_handle_(ui_handle) {
- // The ServiceWorkerNavigationHandleCore is created on the UI thread but
- // should only be accessed from the IO thread afterwards.
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-ServiceWorkerNavigationHandleCore::~ServiceWorkerNavigationHandleCore() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (precreated_host_.get() && context_wrapper_->context()) {
- context_wrapper_->context()->RemoveNavigationHandleCore(
- precreated_host_->provider_id());
- }
-}
-
-void ServiceWorkerNavigationHandleCore::DidPreCreateProviderHost(
- std::unique_ptr<ServiceWorkerProviderHost> precreated_host) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(precreated_host.get());
- DCHECK(context_wrapper_->context());
-
- precreated_host_ = std::move(precreated_host);
- context_wrapper_->context()->AddNavigationHandleCore(
- precreated_host_->provider_id(), this);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &ServiceWorkerNavigationHandle::DidCreateServiceWorkerProviderHost,
- ui_handle_, precreated_host_->provider_id()));
-}
-
-std::unique_ptr<ServiceWorkerProviderHost>
-ServiceWorkerNavigationHandleCore::RetrievePreCreatedHost() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(precreated_host_);
- // Remove the ServiceWorkerNavigationHandleCore from the list of
- // ServiceWorkerNavigationHandleCores since it will no longer hold a
- // ServiceWorkerProviderHost.
- DCHECK(context_wrapper_->context());
- context_wrapper_->context()->RemoveNavigationHandleCore(
- precreated_host_->provider_id());
- return std::move(precreated_host_);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.h b/chromium/content/browser/service_worker/service_worker_navigation_handle_core.h
deleted file mode 100644
index 88e5013c9d2..00000000000
--- a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.h
+++ /dev/null
@@ -1,58 +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_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_CORE_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_CORE_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-
-namespace content {
-
-class ServiceWorkerContextWrapper;
-class ServiceWorkerNavigationHandle;
-class ServiceWorkerProviderHost;
-
-// PlzNavigate
-// This class is used to manage the lifetime of ServiceWorkerProviderHosts
-// created during navigations. This class is created on the UI thread, but
-// should only be accessed from the IO thread afterwards. It is the IO thread
-// pendant of ServiceWorkerNavigationHandle. See the
-// ServiceWorkerNavigationHandle header for more details about the lifetime of
-// both classes.
-class ServiceWorkerNavigationHandleCore {
- public:
- ServiceWorkerNavigationHandleCore(
- base::WeakPtr<ServiceWorkerNavigationHandle> ui_handle,
- ServiceWorkerContextWrapper* context_wrapper);
- ~ServiceWorkerNavigationHandleCore();
-
- // Called when a ServiceWorkerProviderHost was pre-created for the navigation
- // tracked by this ServiceWorkerNavigationHandleCore. Takes ownership of
- // |precreated_host|.
- void DidPreCreateProviderHost(
- std::unique_ptr<ServiceWorkerProviderHost> precreated_host);
-
- // Called when the renderer created a ServiceWorkerNetworkProvider matching
- // |precreated_host_|. This releases ownership of |precreated_host_|.
- std::unique_ptr<ServiceWorkerProviderHost> RetrievePreCreatedHost();
-
- ServiceWorkerContextWrapper* context_wrapper() const {
- return context_wrapper_.get();
- }
-
- private:
- std::unique_ptr<ServiceWorkerProviderHost> precreated_host_;
- scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
- base::WeakPtr<ServiceWorkerNavigationHandle> ui_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerNavigationHandleCore);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_HANDLE_CORE_H_
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager.cc b/chromium/content/browser/service_worker/service_worker_process_manager.cc
index 74253b59d57..d59b221bf05 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.cc
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.cc
@@ -69,7 +69,11 @@ ServiceWorkerProcessManager::~ServiceWorkerProcessManager() {
void ServiceWorkerProcessManager::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- browser_context_ = NULL;
+ {
+ base::AutoLock lock(browser_context_lock_);
+ browser_context_ = nullptr;
+ }
+
for (std::map<int, ProcessInfo>::const_iterator it = instance_info_.begin();
it != instance_info_.end();
++it) {
@@ -78,6 +82,11 @@ void ServiceWorkerProcessManager::Shutdown() {
instance_info_.clear();
}
+bool ServiceWorkerProcessManager::IsShutdown() {
+ base::AutoLock lock(browser_context_lock_);
+ return !browser_context_;
+}
+
void ServiceWorkerProcessManager::AddProcessReferenceToPattern(
const GURL& pattern, int process_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
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 01ddae74be7..da8443f9fe6 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.h
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.h
@@ -12,6 +12,7 @@
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
#include "content/common/service_worker/service_worker_status_code.h"
class GURL;
@@ -36,9 +37,12 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
~ServiceWorkerProcessManager();
// Synchronously prevents new processes from being allocated
- // and drops references to RenderProcessHosts.
+ // and drops references to RenderProcessHosts. Called on the UI thread.
void Shutdown();
+ // Returns true if Shutdown() has been called. May be called by any thread.
+ bool IsShutdown();
+
// Returns a reference to a running process suitable for starting the Service
// Worker at |script_url|. Posts |callback| to the IO thread to indicate
// whether creation succeeded and the process ID that has a new reference.
@@ -109,9 +113,6 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
int process_id;
};
- // Returns true if Shutdown() has been called.
- bool IsShutdown() const { return !browser_context_; }
-
// Maps the process ID to its reference count.
typedef std::map<int, int> ProcessRefMap;
@@ -125,9 +126,16 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
// ChildProcessHost::kInvalidUniqueID if there is none.
int FindAvailableProcess(const GURL& pattern);
- // These fields are only accessed on the UI thread.
+ // Guarded by |browser_context_lock_|.
+ // Written only on the UI thread, so the UI thread doesn't need to acquire the
+ // lock when reading. Can be read from other threads with the lock.
BrowserContext* browser_context_;
+ // Protects |browser_context_|.
+ base::Lock browser_context_lock_;
+
+ // All fields below are only accessed on the UI thread.
+
// Maps the ID of a running EmbeddedWorkerInstance to information about the
// process it's running inside. Since the Instances themselves live on the IO
// thread, this can be slightly out of date:
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host.cc b/chromium/content/browser/service_worker/service_worker_provider_host.cc
index 2666b5dd191..c914a550c91 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -10,6 +10,7 @@
#include "base/stl_util.h"
#include "base/time/time.h"
#include "content/browser/message_port_message_filter.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_request_handler.h"
#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
@@ -17,7 +18,7 @@
#include "content/browser/service_worker/service_worker_handle.h"
#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/common/resource_request_body.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_types.h"
#include "content/common/service_worker/service_worker_utils.h"
@@ -211,22 +212,12 @@ void ServiceWorkerProviderHost::SetControllerVersionAttribute(
notify_controllerchange));
}
-bool ServiceWorkerProviderHost::SetHostedVersion(
+void ServiceWorkerProviderHost::SetHostedVersion(
ServiceWorkerVersion* version) {
- // TODO(falken): Unclear why we check active_version. Should this just check
- // that IsProviderForClient() is false?
- if (active_version())
- return false; // Unexpected bad message.
-
- DCHECK_EQ(ServiceWorkerVersion::STARTING, version->running_status());
- if (version->embedded_worker()->process_id() != render_process_id_) {
- // If we aren't trying to start this version in our process
- // something is amiss.
- return false;
- }
-
+ DCHECK(!IsProviderForClient());
+ DCHECK_EQ(EmbeddedWorkerStatus::STARTING, version->running_status());
+ DCHECK_EQ(render_process_id_, version->embedded_worker()->process_id());
running_hosted_version_ = version;
- return true;
}
bool ServiceWorkerProviderHost::IsProviderForClient() const {
@@ -353,7 +344,7 @@ ServiceWorkerProviderHost::CreateRequestHandler(
RequestContextType request_context_type,
RequestContextFrameType frame_type,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
- scoped_refptr<ResourceRequestBody> body) {
+ scoped_refptr<ResourceRequestBodyImpl> body) {
if (IsHostToRunningServiceWorker()) {
return std::unique_ptr<ServiceWorkerRequestHandler>(
new ServiceWorkerContextRequestHandler(
@@ -643,7 +634,7 @@ bool ServiceWorkerProviderHost::IsReadyToSendMessages() const {
}
bool ServiceWorkerProviderHost::IsContextAlive() {
- return context_ != NULL;
+ return context_ != nullptr;
}
void ServiceWorkerProviderHost::Send(IPC::Message* message) const {
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 8e3aebab10f..f6ceed91f76 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -32,7 +32,7 @@ class BlobStorageContext;
namespace content {
-class ResourceRequestBody;
+class ResourceRequestBodyImpl;
class ServiceWorkerContextCore;
class ServiceWorkerDispatcherHost;
class ServiceWorkerRequestHandler;
@@ -89,8 +89,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
return parent_frame_security_level_ == FrameSecurityLevel::SECURE;
}
void set_parent_frame_secure(bool is_parent_frame_secure) {
- CHECK_EQ(static_cast<int>(parent_frame_security_level_),
- static_cast<int>(FrameSecurityLevel::UNINITIALIZED));
+ CHECK_EQ(parent_frame_security_level_, FrameSecurityLevel::UNINITIALIZED);
parent_frame_security_level_ = is_parent_frame_secure
? FrameSecurityLevel::SECURE
: FrameSecurityLevel::INSECURE;
@@ -155,9 +154,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// Clears the associated registration and stop listening to it.
void DisassociateRegistration();
- // Returns false if we have an active version or |version| is using a
- // different process. That would be indicative of a bad IPC message.
- bool SetHostedVersion(ServiceWorkerVersion* version);
+ void SetHostedVersion(ServiceWorkerVersion* version);
// Returns a handler for a request, the handler may return NULL if
// the request doesn't require special handling.
@@ -169,7 +166,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
RequestContextType request_context_type,
RequestContextFrameType frame_type,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
- scoped_refptr<ResourceRequestBody> body);
+ scoped_refptr<ResourceRequestBodyImpl> body);
// Used to get a ServiceWorkerObjectInfo to send to the renderer. Finds an
// existing ServiceWorkerHandle, and increments its reference count, or else
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.cc b/chromium/content/browser/service_worker/service_worker_register_job.cc
index 149502cddbd..fbfb635c3ba 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -9,6 +9,7 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.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_job_coordinator.h"
#include "content/browser/service_worker/service_worker_metrics.h"
@@ -410,7 +411,7 @@ void ServiceWorkerRegisterJob::InstallAndContinue() {
ServiceWorkerMetrics::EventType::INSTALL,
base::Bind(&ServiceWorkerRegisterJob::DispatchInstallEvent,
weak_factory_.GetWeakPtr()),
- base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
+ base::Bind(&ServiceWorkerRegisterJob::OnInstallFailed,
weak_factory_.GetWeakPtr()));
// A subsequent registration job may terminate our installing worker. It can
@@ -423,29 +424,49 @@ void ServiceWorkerRegisterJob::InstallAndContinue() {
void ServiceWorkerRegisterJob::DispatchInstallEvent() {
DCHECK_EQ(ServiceWorkerVersion::INSTALLING, new_version()->status())
<< new_version()->status();
- DCHECK_EQ(ServiceWorkerVersion::RUNNING, new_version()->running_status())
+ DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, new_version()->running_status())
<< "Worker stopped too soon after it was started.";
int request_id = new_version()->StartRequest(
ServiceWorkerMetrics::EventType::INSTALL,
- base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
+ base::Bind(&ServiceWorkerRegisterJob::OnInstallFailed,
weak_factory_.GetWeakPtr()));
- new_version()->DispatchSimpleEvent<ServiceWorkerHostMsg_InstallEventFinished>(
- request_id, ServiceWorkerMsg_InstallEvent(request_id));
+ new_version()
+ ->RegisterRequestCallback<ServiceWorkerHostMsg_InstallEventFinished>(
+ request_id, base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
+ weak_factory_.GetWeakPtr()));
+ new_version()->DispatchEvent({request_id},
+ ServiceWorkerMsg_InstallEvent(request_id));
}
void ServiceWorkerRegisterJob::OnInstallFinished(
- ServiceWorkerStatusCode status) {
- ServiceWorkerMetrics::RecordInstallEventStatus(status);
+ int request_id,
+ blink::WebServiceWorkerEventResult result,
+ bool has_fetch_handler) {
+ new_version()->FinishRequest(
+ request_id, result == blink::WebServiceWorkerEventResultCompleted);
+
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ switch (result) {
+ case blink::WebServiceWorkerEventResultCompleted:
+ status = SERVICE_WORKER_OK;
+ break;
+ case blink::WebServiceWorkerEventResultRejected:
+ status = SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED;
+ break;
+ default:
+ NOTREACHED();
+ }
if (status != SERVICE_WORKER_OK) {
- // "8. If installFailed is true, then:..."
- Complete(status, std::string("ServiceWorker failed to install: ") +
- ServiceWorkerStatusToString(status));
+ OnInstallFailed(status);
return;
}
+ ServiceWorkerMetrics::RecordInstallEventStatus(status);
+
SetPhase(STORE);
DCHECK(!registration()->last_update_check().is_null());
+ new_version()->set_has_fetch_handler(has_fetch_handler);
context_->storage()->StoreRegistration(
registration(),
new_version(),
@@ -453,6 +474,17 @@ void ServiceWorkerRegisterJob::OnInstallFinished(
weak_factory_.GetWeakPtr()));
}
+void ServiceWorkerRegisterJob::OnInstallFailed(ServiceWorkerStatusCode status) {
+ ServiceWorkerMetrics::RecordInstallEventStatus(status);
+
+ if (status != SERVICE_WORKER_OK) {
+ Complete(status, std::string("ServiceWorker failed to install: ") +
+ ServiceWorkerStatusToString(status));
+ } else {
+ NOTREACHED() << "OnInstallFailed should not handle SERVICE_WORKER_OK";
+ }
+}
+
void ServiceWorkerRegisterJob::OnStoreRegistrationComplete(
ServiceWorkerStatusCode status) {
if (status != SERVICE_WORKER_OK) {
@@ -462,8 +494,13 @@ void ServiceWorkerRegisterJob::OnStoreRegistrationComplete(
// "9. If registration.waitingWorker is not null, then:..."
if (registration()->waiting_version()) {
- // "1. Run the [[UpdateState]] algorithm passing registration.waitingWorker
- // and "redundant" as the arguments."
+ // 1. Set redundantWorker to registration’s waiting worker.
+ // 2. Terminate redundantWorker.
+ registration()->waiting_version()->StopWorker(
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ // TODO(falken): Move this further down. The spec says to set status to
+ // 'redundant' after promoting the new version to .waiting attribute and
+ // 'installed' status.
registration()->waiting_version()->SetStatus(
ServiceWorkerVersion::REDUNDANT);
}
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 455f3598209..153203eab46 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.h
+++ b/chromium/content/browser/service_worker/service_worker_register_job.h
@@ -123,7 +123,10 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase,
void OnStoreRegistrationComplete(ServiceWorkerStatusCode status);
void InstallAndContinue();
void DispatchInstallEvent();
- void OnInstallFinished(ServiceWorkerStatusCode status);
+ void OnInstallFinished(int request_id,
+ blink::WebServiceWorkerEventResult result,
+ bool has_fetch_handler);
+ void OnInstallFailed(ServiceWorkerStatusCode status);
void Complete(ServiceWorkerStatusCode status);
void Complete(ServiceWorkerStatusCode status,
const std::string& status_message);
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index 047e20f82f5..ef587ee2a6b 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -6,7 +6,9 @@
#include <vector>
+#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_wrapper.h"
#include "content/browser/service_worker/service_worker_info.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_register_job.h"
@@ -37,7 +39,8 @@ ServiceWorkerRegistration::ServiceWorkerRegistration(
is_uninstalled_(false),
should_activate_when_ready_(false),
resources_total_size_bytes_(0),
- context_(context) {
+ context_(context),
+ task_runner_(base::ThreadTaskRunnerHandle::Get()) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_NE(kInvalidServiceWorkerRegistrationId, registration_id);
DCHECK(context_);
@@ -45,6 +48,11 @@ 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_)
@@ -99,10 +107,11 @@ ServiceWorkerRegistrationInfo ServiceWorkerRegistration::GetInfo() {
void ServiceWorkerRegistration::SetActiveVersion(
const scoped_refptr<ServiceWorkerVersion>& version) {
- should_activate_when_ready_ = false;
if (active_version_ == version)
return;
+ should_activate_when_ready_ = false;
+
ChangedVersionAttributesMask mask;
if (version)
UnsetVersionInternal(version.get(), &mask);
@@ -118,10 +127,11 @@ void ServiceWorkerRegistration::SetActiveVersion(
void ServiceWorkerRegistration::SetWaitingVersion(
const scoped_refptr<ServiceWorkerVersion>& version) {
- should_activate_when_ready_ = false;
if (waiting_version_ == version)
return;
+ should_activate_when_ready_ = false;
+
ChangedVersionAttributesMask mask;
if (version)
UnsetVersionInternal(version.get(), &mask);
@@ -163,6 +173,7 @@ void ServiceWorkerRegistration::UnsetVersionInternal(
mask->add(ChangedVersionAttributesMask::INSTALLING_VERSION);
} else if (waiting_version_.get() == version) {
waiting_version_ = NULL;
+ should_activate_when_ready_ = false;
mask->add(ChangedVersionAttributesMask::WAITING_VERSION);
} else if (active_version_.get() == version) {
active_version_->RemoveListener(this);
@@ -174,10 +185,8 @@ void ServiceWorkerRegistration::UnsetVersionInternal(
void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() {
DCHECK(waiting_version());
should_activate_when_ready_ = true;
-
- if (!active_version() || !active_version()->HasControllee() ||
- waiting_version()->skip_waiting())
- ActivateWaitingVersion();
+ if (IsReadyToActivate())
+ ActivateWaitingVersion(false /* delay */);
}
void ServiceWorkerRegistration::ClaimClients() {
@@ -244,16 +253,37 @@ void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
DCHECK_EQ(active_version(), version);
if (is_uninstalling_)
Clear();
- else if (should_activate_when_ready_)
- ActivateWaitingVersion();
- is_uninstalling_ = false;
- should_activate_when_ready_ = false;
+ else if (IsReadyToActivate())
+ ActivateWaitingVersion(true /* delay */);
}
-void ServiceWorkerRegistration::ActivateWaitingVersion() {
- DCHECK(context_);
+void ServiceWorkerRegistration::OnNoWork(ServiceWorkerVersion* version) {
+ if (!context_)
+ return;
+ DCHECK_EQ(active_version(), version);
+ if (IsReadyToActivate())
+ ActivateWaitingVersion(false /* delay */);
+}
+
+bool ServiceWorkerRegistration::IsReadyToActivate() const {
+ if (!should_activate_when_ready_)
+ return false;
+
DCHECK(waiting_version());
- DCHECK(should_activate_when_ready_);
+ const ServiceWorkerVersion* active = active_version();
+ if (!active)
+ return true;
+ if (!active->HasWork() &&
+ (!active->HasControllee() || waiting_version()->skip_waiting())) {
+ return true;
+ }
+ return false;
+}
+
+void ServiceWorkerRegistration::ActivateWaitingVersion(bool delay) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(context_);
+ DCHECK(IsReadyToActivate());
should_activate_when_ready_ = false;
scoped_refptr<ServiceWorkerVersion> activating_version = waiting_version();
scoped_refptr<ServiceWorkerVersion> exiting_version = active_version();
@@ -263,8 +293,11 @@ void ServiceWorkerRegistration::ActivateWaitingVersion() {
// "5. If exitingWorker is not null,
if (exiting_version.get()) {
- // TODO(michaeln): should wait for events to be complete
+ // TODO(falken): Update the quoted spec comments once
+ // https://github.com/slightlyoff/ServiceWorker/issues/916 is codified in
+ // the spec.
// "1. Wait for exitingWorker to finish handling any in-progress requests."
+ // This is already handled by IsReadyToActivate().
// "2. Terminate exitingWorker."
exiting_version->StopWorker(
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
@@ -285,6 +318,25 @@ void ServiceWorkerRegistration::ActivateWaitingVersion() {
FOR_EACH_OBSERVER(Listener, listeners_, OnSkippedWaiting(this));
// "10. Queue a task to fire an event named activate..."
+ // The browser could be shutting down. To avoid spurious start worker
+ // failures, wait a bit before continuing.
+ if (delay) {
+ task_runner_->PostDelayedTask(
+ FROM_HERE, base::Bind(&ServiceWorkerRegistration::ContinueActivation,
+ this, activating_version),
+ base::TimeDelta::FromSeconds(1));
+ } else {
+ ContinueActivation(std::move(activating_version));
+ }
+}
+
+void ServiceWorkerRegistration::ContinueActivation(
+ scoped_refptr<ServiceWorkerVersion> activating_version) {
+ if (!context_)
+ return;
+ if (active_version() != activating_version.get())
+ return;
+ DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status());
activating_version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::ACTIVATE,
base::Bind(&ServiceWorkerRegistration::DispatchActivateEvent, this,
@@ -333,6 +385,11 @@ void ServiceWorkerRegistration::NotifyRegistrationFinished() {
callback.Run();
}
+void ServiceWorkerRegistration::SetTaskRunnerForTest(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ task_runner_ = task_runner;
+}
+
void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback(
const base::Closure& callback) {
// This should only be called if the registration is in progress.
@@ -342,14 +399,14 @@ void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback(
}
void ServiceWorkerRegistration::DispatchActivateEvent(
- const scoped_refptr<ServiceWorkerVersion>& activating_version) {
+ scoped_refptr<ServiceWorkerVersion> activating_version) {
if (activating_version != active_version()) {
OnActivateEventFinished(activating_version, SERVICE_WORKER_ERROR_FAILED);
return;
}
DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status());
- DCHECK_EQ(ServiceWorkerVersion::RUNNING, activating_version->running_status())
+ DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, activating_version->running_status())
<< "Worker stopped too soon after it was started.";
int request_id = activating_version->StartRequest(
ServiceWorkerMetrics::EventType::ACTIVATE,
@@ -361,15 +418,26 @@ void ServiceWorkerRegistration::DispatchActivateEvent(
}
void ServiceWorkerRegistration::OnActivateEventFinished(
- const scoped_refptr<ServiceWorkerVersion>& activating_version,
+ scoped_refptr<ServiceWorkerVersion> activating_version,
ServiceWorkerStatusCode status) {
+ // Activate is prone to failing due to shutdown, because it's triggered when
+ // tabs close.
+ bool is_shutdown =
+ !context_ || context_->wrapper()->process_manager()->IsShutdown();
+ ServiceWorkerMetrics::RecordActivateEventStatus(status, is_shutdown);
+
if (!context_ || activating_version != active_version() ||
- activating_version->status() != ServiceWorkerVersion::ACTIVATING)
+ activating_version->status() != ServiceWorkerVersion::ACTIVATING) {
return;
+ }
- // |status| is just for UMA. Once we've attempted to dispatch the activate
- // event to an installed worker, it's committed to becoming active.
- ServiceWorkerMetrics::RecordActivateEventStatus(status);
+ // Normally, the worker is committed to become activated once we get here, per
+ // spec. E.g., if the script rejected waitUntil or had an unhandled exception,
+ // it should still be activated. However, if the failure occurred during
+ // shutdown, ignore it to give the worker another chance the next time the
+ // browser starts up.
+ if (is_shutdown && status != SERVICE_WORKER_OK)
+ return;
// "Run the Update State algorithm passing registration's active worker and
// 'activated' as the arguments."
@@ -387,6 +455,7 @@ void ServiceWorkerRegistration::OnDeleteFinished(
void ServiceWorkerRegistration::Clear() {
is_uninstalling_ = false;
is_uninstalled_ = true;
+ should_activate_when_ready_ = false;
if (context_)
context_->storage()->NotifyDoneUninstallingRegistration(this);
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index 5b71848da6b..8a69821a962 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -9,10 +9,12 @@
#include <memory>
#include <string>
+#include <vector>
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -28,8 +30,8 @@ struct ServiceWorkerRegistrationInfo;
// to this class. This is refcounted via ServiceWorkerRegistrationHandle to
// facilitate multiple controllees being associated with the same registration.
class CONTENT_EXPORT ServiceWorkerRegistration
- : NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerRegistration>),
- public ServiceWorkerVersion::Listener {
+ : public NON_EXPORTED_BASE(base::RefCounted<ServiceWorkerRegistration>),
+ public NON_EXPORTED_BASE(ServiceWorkerVersion::Listener) {
public:
typedef base::Callback<void(ServiceWorkerStatusCode status)> StatusCallback;
@@ -71,6 +73,12 @@ class CONTENT_EXPORT ServiceWorkerRegistration
resources_total_size_bytes_ = resources_total_size_bytes;
}
+ // Returns the active version. This version may be in ACTIVATING or ACTIVATED
+ // state. If you require an ACTIVATED version, use
+ // ServiceWorkerContextWrapper::FindReadyRegistration* to get a registration
+ // with such a version. Alternatively, use
+ // ServiceWorkerVersion::Listener::OnVersionStateChanged to wait for the
+ // ACTIVATING version to become ACTIVATED.
ServiceWorkerVersion* active_version() const {
return active_version_.get();
}
@@ -139,6 +147,9 @@ class CONTENT_EXPORT ServiceWorkerRegistration
void RegisterRegistrationFinishedCallback(const base::Closure& callback);
void NotifyRegistrationFinished();
+ void SetTaskRunnerForTest(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
private:
friend class base::RefCounted<ServiceWorkerRegistration>;
@@ -150,14 +161,22 @@ class CONTENT_EXPORT ServiceWorkerRegistration
// ServiceWorkerVersion::Listener override.
void OnNoControllees(ServiceWorkerVersion* version) override;
+ void OnNoWork(ServiceWorkerVersion* version) override;
+
+ bool IsReadyToActivate() const;
- // This method corresponds to the [[Activate]] algorithm.
- void ActivateWaitingVersion();
+ // Promotes the waiting version to active version. If |delay| is true, waits
+ // a short time before attempting to start and dispatch the activate event
+ // to the version.
+ void ActivateWaitingVersion(bool delay);
+ void ContinueActivation(
+ scoped_refptr<ServiceWorkerVersion> activating_version);
void DispatchActivateEvent(
- const scoped_refptr<ServiceWorkerVersion>& activating_version);
+ scoped_refptr<ServiceWorkerVersion> activating_version);
void OnActivateEventFinished(
- const scoped_refptr<ServiceWorkerVersion>& activating_version,
+ scoped_refptr<ServiceWorkerVersion> activating_version,
ServiceWorkerStatusCode status);
+
void OnDeleteFinished(ServiceWorkerStatusCode status);
// This method corresponds to the [[ClearRegistration]] algorithm.
@@ -184,6 +203,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
base::ObserverList<Listener> listeners_;
std::vector<base::Closure> registration_finished_callbacks_;
base::WeakPtr<ServiceWorkerContextCore> context_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistration);
};
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 417896b6f41..654a434ca45 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -11,15 +11,31 @@
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/service_worker/embedded_worker_status.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_handle.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
+namespace {
+
+int CreateInflightRequest(ServiceWorkerVersion* version) {
+ version->StartWorker(ServiceWorkerMetrics::EventType::PUSH,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
+ return version->StartRequest(
+ ServiceWorkerMetrics::EventType::PUSH,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+}
+
+} // namespace
+
class ServiceWorkerRegistrationTest : public testing::Test {
public:
ServiceWorkerRegistrationTest()
@@ -27,6 +43,9 @@ class ServiceWorkerRegistrationTest : public testing::Test {
void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+
+ helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
}
void TearDown() override {
@@ -35,6 +54,7 @@ class ServiceWorkerRegistrationTest : public testing::Test {
}
ServiceWorkerContextCore* context() { return helper_->context(); }
+ ServiceWorkerStorage* storage() { return helper_->context()->storage(); }
class RegistrationListener : public ServiceWorkerRegistration::Listener {
public:
@@ -160,4 +180,151 @@ TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
// Don't crash when handle gets destructed.
}
+// Sets up a registration with a waiting worker, and an active worker
+// with a controllee and an inflight request.
+class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
+ public:
+ ServiceWorkerActivationTest() : ServiceWorkerRegistrationTest() {}
+
+ void SetUp() override {
+ ServiceWorkerRegistrationTest::SetUp();
+
+ const GURL kScope("https://www.example.not/");
+ const GURL kScript("https://www.example.not/service_worker.js");
+
+ registration_ = new ServiceWorkerRegistration(
+ kScope, storage()->NewRegistrationId(), context()->AsWeakPtr());
+
+ // Create an active version.
+ scoped_refptr<ServiceWorkerVersion> version_1 = new ServiceWorkerVersion(
+ registration_.get(), kScript, storage()->NewVersionId(),
+ context()->AsWeakPtr());
+ registration_->SetActiveVersion(version_1);
+ version_1->SetStatus(ServiceWorkerVersion::ACTIVATED);
+
+ // Store the registration.
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ records.push_back(ServiceWorkerDatabase::ResourceRecord(
+ 10, version_1->script_url(), 100));
+ version_1->script_cache_map()->SetResources(records);
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ context()->storage()->StoreRegistration(
+ registration_.get(), version_1.get(),
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(SERVICE_WORKER_OK, status);
+
+ // Give the active version a controllee.
+ host_.reset(new ServiceWorkerProviderHost(
+ 33 /* dummy render process id */,
+ MSG_ROUTING_NONE /* render_frame_id */, 1 /* dummy provider_id */,
+ SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ ServiceWorkerProviderHost::FrameSecurityLevel::SECURE,
+ context()->AsWeakPtr(), nullptr));
+ version_1->AddControllee(host_.get());
+
+ // Give the active version an in-flight request.
+ inflight_request_id_ = CreateInflightRequest(version_1.get());
+
+ // Create a waiting version.
+ scoped_refptr<ServiceWorkerVersion> version_2 = new ServiceWorkerVersion(
+ registration_.get(), kScript, storage()->NewVersionId(),
+ context()->AsWeakPtr());
+ registration_->SetWaitingVersion(version_2);
+ version_2->SetStatus(ServiceWorkerVersion::INSTALLED);
+
+ // Set it to activate when ready. The original version should still be
+ // active.
+ registration_->ActivateWaitingVersionWhenReady();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), registration_->active_version());
+ }
+
+ void TearDown() override {
+ registration_->active_version()->RemoveListener(registration_.get());
+ ServiceWorkerRegistrationTest::TearDown();
+ }
+
+ ServiceWorkerRegistration* registration() { return registration_.get(); }
+ ServiceWorkerProviderHost* controllee() { return host_.get(); }
+ int inflight_request_id() const { return inflight_request_id_; }
+
+ private:
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ std::unique_ptr<ServiceWorkerProviderHost> host_;
+ int inflight_request_id_ = -1;
+};
+
+// Test activation triggered by finishing all requests.
+TEST_F(ServiceWorkerActivationTest, NoInflightRequest) {
+ scoped_refptr<ServiceWorkerRegistration> reg = registration();
+ scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
+ scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
+
+ // Remove the controllee. Since there is an in-flight request,
+ // activation should not yet happen.
+ version_1->RemoveControllee(controllee());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), reg->active_version());
+
+ // Finish the request. Activation should happen.
+ version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_2.get(), reg->active_version());
+}
+
+// Test activation triggered by loss of controllee.
+TEST_F(ServiceWorkerActivationTest, NoControllee) {
+ scoped_refptr<ServiceWorkerRegistration> reg = registration();
+ scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
+ scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
+
+ // Finish the request. Since there is a controllee, activation should not yet
+ // happen.
+ version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), reg->active_version());
+
+ // Remove the controllee. Activation should happen.
+ version_1->RemoveControllee(controllee());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_2.get(), reg->active_version());
+}
+
+// Test activation triggered by skipWaiting.
+TEST_F(ServiceWorkerActivationTest, SkipWaiting) {
+ scoped_refptr<ServiceWorkerRegistration> reg = registration();
+ scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
+ scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
+
+ // Finish the in-flight request. Since there is a controllee,
+ // activation should not happen.
+ version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), reg->active_version());
+
+ // Call skipWaiting. Activation should happen.
+ version_2->OnSkipWaiting(77 /* dummy request_id */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_2.get(), reg->active_version());
+}
+
+// Test activation triggered by skipWaiting and finishing requests.
+TEST_F(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
+ scoped_refptr<ServiceWorkerRegistration> reg = registration();
+ scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
+ scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
+
+ // Set skip waiting flag. Since there is still an in-flight request,
+ // activation should not happen.
+ version_2->OnSkipWaiting(77 /* dummy request_id */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), reg->active_version());
+
+ // Finish the request. Activation should happen.
+ version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_2.get(), reg->active_version());
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler.cc b/chromium/content/browser/service_worker/service_worker_request_handler.cc
index 0195e32ddbd..980fd03d46b 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.cc
@@ -10,11 +10,10 @@
#include "base/macros.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_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_url_request_job.h"
-#include "content/common/resource_request_body.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"
@@ -66,7 +65,7 @@ void FinalizeHandlerInitialization(
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body) {
+ scoped_refptr<ResourceRequestBodyImpl> body) {
if (skip_service_worker) {
// TODO(horo): Does this work properly for PlzNavigate?
if (ServiceWorkerUtils::IsMainResourceType(resource_type)) {
@@ -92,54 +91,6 @@ void FinalizeHandlerInitialization(
} // namespace
-// PlzNavigate
-void ServiceWorkerRequestHandler::InitializeForNavigation(
- net::URLRequest* request,
- ServiceWorkerNavigationHandleCore* navigation_handle_core,
- storage::BlobStorageContext* blob_storage_context,
- bool skip_service_worker,
- ResourceType resource_type,
- RequestContextType request_context_type,
- RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body) {
- CHECK(IsBrowserSideNavigationEnabled());
-
- // Only create a handler when there is a ServiceWorkerNavigationHandlerCore
- // to take ownership of a pre-created SeviceWorkerProviderHost.
- if (!navigation_handle_core)
- return;
-
- // Create the handler even for insecure HTTP since it's used in the
- // case of redirect to HTTPS.
- if (!request->url().SchemeIsHTTPOrHTTPS() &&
- !OriginCanAccessServiceWorkers(request->url())) {
- return;
- }
-
- if (!navigation_handle_core->context_wrapper() ||
- !navigation_handle_core->context_wrapper()->context()) {
- return;
- }
-
- // Initialize the SWProviderHost.
- std::unique_ptr<ServiceWorkerProviderHost> provider_host =
- ServiceWorkerProviderHost::PreCreateNavigationHost(
- navigation_handle_core->context_wrapper()->context()->AsWeakPtr());
-
- FinalizeHandlerInitialization(
- request, provider_host.get(), blob_storage_context, skip_service_worker,
- FETCH_REQUEST_MODE_SAME_ORIGIN, FETCH_CREDENTIALS_MODE_INCLUDE,
- FetchRedirectMode::MANUAL_MODE, resource_type, request_context_type,
- frame_type, body);
-
- // Transfer ownership to the ServiceWorkerNavigationHandleCore.
- // In the case of a successful navigation, the SWProviderHost will be
- // transferred to its "final" destination in the OnProviderCreated handler. If
- // the navigation fails, it will be destroyed along with the
- // ServiceWorkerNavigationHandleCore.
- navigation_handle_core->DidPreCreateProviderHost(std::move(provider_host));
-}
-
void ServiceWorkerRequestHandler::InitializeHandler(
net::URLRequest* request,
ServiceWorkerContextWrapper* context_wrapper,
@@ -153,7 +104,7 @@ void ServiceWorkerRequestHandler::InitializeHandler(
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body) {
+ scoped_refptr<ResourceRequestBodyImpl> body) {
// Create the handler even for insecure HTTP since it's used in the
// case of redirect to HTTPS.
if (!request->url().SchemeIsHTTPOrHTTPS() &&
@@ -178,7 +129,7 @@ void ServiceWorkerRequestHandler::InitializeHandler(
}
ServiceWorkerRequestHandler* ServiceWorkerRequestHandler::GetHandler(
- net::URLRequest* request) {
+ const net::URLRequest* request) {
return static_cast<ServiceWorkerRequestHandler*>(
request->GetUserData(&kUserDataKey));
}
@@ -191,7 +142,7 @@ ServiceWorkerRequestHandler::CreateInterceptor(
}
bool ServiceWorkerRequestHandler::IsControlledByServiceWorker(
- net::URLRequest* request) {
+ const net::URLRequest* request) {
ServiceWorkerRequestHandler* handler = GetHandler(request);
if (!handler || !handler->provider_host_)
return false;
@@ -199,6 +150,12 @@ bool ServiceWorkerRequestHandler::IsControlledByServiceWorker(
handler->provider_host_->running_hosted_version();
}
+ServiceWorkerProviderHost* ServiceWorkerRequestHandler::GetProviderHost(
+ const net::URLRequest* request) {
+ ServiceWorkerRequestHandler* handler = GetHandler(request);
+ return handler ? handler->provider_host_.get() : nullptr;
+}
+
void ServiceWorkerRequestHandler::PrepareForCrossSiteTransfer(
int old_process_id) {
CHECK(!IsBrowserSideNavigationEnabled());
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 e5bba5585c6..449db58b1cb 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.h
@@ -33,10 +33,9 @@ namespace content {
class ResourceContext;
class ResourceMessageFilter;
-class ResourceRequestBody;
+class ResourceRequestBodyImpl;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
-class ServiceWorkerNavigationHandleCore;
class ServiceWorkerProviderHost;
// Abstract base class for routing network requests to ServiceWorkers.
@@ -44,19 +43,6 @@ class ServiceWorkerProviderHost;
class CONTENT_EXPORT ServiceWorkerRequestHandler
: public base::SupportsUserData::Data {
public:
- // PlzNavigate
- // Attaches a newly created handler if the given |request| needs to be handled
- // by ServiceWorker.
- static void InitializeForNavigation(
- net::URLRequest* request,
- ServiceWorkerNavigationHandleCore* navigation_handle_core,
- storage::BlobStorageContext* blob_storage_context,
- bool skip_service_worker,
- ResourceType resource_type,
- RequestContextType request_context_type,
- RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body);
-
// Attaches a newly created handler if the given |request| needs to
// be handled by ServiceWorker.
// TODO(kinuko): While utilizing UserData to attach data to URLRequest
@@ -76,12 +62,12 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body);
+ scoped_refptr<ResourceRequestBodyImpl> body);
// Returns the handler attached to |request|. This may return NULL
// if no handler is attached.
static ServiceWorkerRequestHandler* GetHandler(
- net::URLRequest* request);
+ const net::URLRequest* request);
// Creates a protocol interceptor for ServiceWorker.
static std::unique_ptr<net::URLRequestInterceptor> CreateInterceptor(
@@ -91,7 +77,12 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
// It's only reliable after the ServiceWorkerRequestHandler MaybeCreateJob
// method runs to completion for this request. The AppCache handler uses
// this to avoid colliding with ServiceWorkers.
- static bool IsControlledByServiceWorker(net::URLRequest* request);
+ static bool IsControlledByServiceWorker(const net::URLRequest* request);
+
+ // Returns the ServiceWorkerProviderHost the request is associated with.
+ // Only valid after InitializeHandler has been called. Can return null.
+ static ServiceWorkerProviderHost* GetProviderHost(
+ const net::URLRequest* request);
~ServiceWorkerRequestHandler() override;
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 7316c919828..a43a6724503 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,7 +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/common/resource_request_body.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"
#include "content/public/common/request_context_type.h"
diff --git a/chromium/content/browser/service_worker/service_worker_response_info.cc b/chromium/content/browser/service_worker/service_worker_response_info.cc
index aafb657db99..520b80712b5 100644
--- a/chromium/content/browser/service_worker/service_worker_response_info.cc
+++ b/chromium/content/browser/service_worker/service_worker_response_info.cc
@@ -35,6 +35,8 @@ void ServiceWorkerResponseInfo::ResetDataForRequest(net::URLRequest* request) {
info->ResetData();
}
+ServiceWorkerResponseInfo::~ServiceWorkerResponseInfo() {}
+
void ServiceWorkerResponseInfo::GetExtraResponseInfo(
ResourceResponseInfo* response_info) const {
response_info->was_fetched_via_service_worker =
@@ -49,6 +51,7 @@ void ServiceWorkerResponseInfo::GetExtraResponseInfo(
response_info->service_worker_ready_time = service_worker_ready_time_;
response_info->is_in_cache_storage = response_is_in_cache_storage_;
response_info->cache_storage_cache_name = response_cache_storage_cache_name_;
+ response_info->cors_exposed_header_names = cors_exposed_header_names_;
}
void ServiceWorkerResponseInfo::OnPrepareToRestart(
@@ -71,13 +74,15 @@ void ServiceWorkerResponseInfo::OnStartCompleted(
base::TimeTicks service_worker_start_time,
base::TimeTicks service_worker_ready_time,
bool response_is_in_cache_storage,
- const std::string& response_cache_storage_cache_name) {
+ const std::string& response_cache_storage_cache_name,
+ const ServiceWorkerHeaderList& cors_exposed_header_names) {
was_fetched_via_service_worker_ = was_fetched_via_service_worker;
was_fallback_required_ = was_fallback_required;
original_url_via_service_worker_ = original_url_via_service_worker;
response_type_via_service_worker_ = response_type_via_service_worker;
response_is_in_cache_storage_ = response_is_in_cache_storage;
response_cache_storage_cache_name_ = response_cache_storage_cache_name;
+ cors_exposed_header_names_ = cors_exposed_header_names;
// Update times, if not already set by a previous Job.
if (service_worker_start_time_.is_null()) {
@@ -94,6 +99,7 @@ void ServiceWorkerResponseInfo::ResetData() {
blink::WebServiceWorkerResponseTypeDefault;
response_is_in_cache_storage_ = false;
response_cache_storage_cache_name_ = std::string();
+ cors_exposed_header_names_.clear();
}
ServiceWorkerResponseInfo::ServiceWorkerResponseInfo() {}
diff --git a/chromium/content/browser/service_worker/service_worker_response_info.h b/chromium/content/browser/service_worker/service_worker_response_info.h
index 4e48cd97073..e270246a93f 100644
--- a/chromium/content/browser/service_worker/service_worker_response_info.h
+++ b/chromium/content/browser/service_worker/service_worker_response_info.h
@@ -7,6 +7,7 @@
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseType.h"
#include "url/gurl.h"
@@ -25,6 +26,8 @@ class CONTENT_EXPORT ServiceWorkerResponseInfo
bool create = false);
static void ResetDataForRequest(net::URLRequest* request);
+ ~ServiceWorkerResponseInfo() override;
+
void GetExtraResponseInfo(ResourceResponseInfo* response_info) const;
void OnPrepareToRestart(base::TimeTicks service_worker_start_time,
base::TimeTicks service_worker_ready_time);
@@ -36,7 +39,8 @@ class CONTENT_EXPORT ServiceWorkerResponseInfo
base::TimeTicks service_worker_start_time,
base::TimeTicks service_worker_ready_time,
bool response_is_in_cache_storage,
- const std::string& response_cache_storage_cache_name);
+ const std::string& response_cache_storage_cache_name,
+ const ServiceWorkerHeaderList& cors_exposed_header_names);
void ResetData();
bool was_fetched_via_service_worker() const {
@@ -74,6 +78,7 @@ class CONTENT_EXPORT ServiceWorkerResponseInfo
base::TimeTicks service_worker_ready_time_;
bool response_is_in_cache_storage_ = false;
std::string response_cache_storage_cache_name_;
+ ServiceWorkerHeaderList cors_exposed_header_names_;
};
} // 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 f493b004e53..7fe900830c9 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -399,7 +399,7 @@ void ServiceWorkerStorage::StoreRegistration(
data.registration_id = registration->id();
data.scope = registration->pattern();
data.script = version->script_url();
- data.has_fetch_handler = true;
+ data.has_fetch_handler = version->has_fetch_handler();
data.version_id = version->version_id();
data.last_update_check = registration->last_update_check();
data.is_active = (version == registration->active_version());
@@ -1248,6 +1248,7 @@ 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);
+ version->set_has_fetch_handler(data.has_fetch_handler);
}
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 6f78281dd4d..61ce44dc35e 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.h
+++ b/chromium/content/browser/service_worker/service_worker_storage.h
@@ -231,6 +231,7 @@ class CONTENT_EXPORT ServiceWorkerStorage
friend class ServiceWorkerDispatcherHostTest;
friend class ServiceWorkerHandleTest;
friend class ServiceWorkerStorageTest;
+ friend class ServiceWorkerRegistrationTest;
friend class ServiceWorkerResourceStorageTest;
friend class ServiceWorkerControlleeRequestHandlerTest;
friend class ServiceWorkerContextRequestHandlerTest;
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 c67d407d73e..a81f696815c 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
@@ -22,13 +22,14 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/resource_context_impl.h"
+#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_response_info.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_context.h"
#include "content/browser/streams/stream_registry.h"
-#include "content/common/resource_request_body.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/blob_handle.h"
@@ -130,9 +131,9 @@ class ServiceWorkerURLRequestJob::BlobConstructionWaiter {
num_pending_request_body_blobs_ = 0;
callback_ = callback;
- for (const ResourceRequestBody::Element& element :
+ for (const ResourceRequestBodyImpl::Element& element :
*(owner_->body_->elements())) {
- if (element.type() != ResourceRequestBody::Element::TYPE_BLOB)
+ if (element.type() != ResourceRequestBodyImpl::Element::TYPE_BLOB)
continue;
std::unique_ptr<storage::BlobDataHandle> handle =
@@ -181,7 +182,7 @@ class ServiceWorkerURLRequestJob::BlobConstructionWaiter {
// Owns and must outlive |this|.
ServiceWorkerURLRequestJob* owner_;
- scoped_refptr<ResourceRequestBody> body_;
+ scoped_refptr<ResourceRequestBodyImpl> body_;
base::Callback<void(bool)> callback_;
size_t num_pending_request_body_blobs_ = 0;
Phase phase_ = Phase::INITIAL;
@@ -207,7 +208,7 @@ ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body,
+ scoped_refptr<ResourceRequestBodyImpl> body,
ServiceWorkerFetchType fetch_type,
Delegate* delegate)
: net::URLRequestJob(request, network_delegate),
@@ -571,9 +572,9 @@ void ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid,
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 ResourceRequestBody::Element*> resolved_elements;
- for (const ResourceRequestBody::Element& element : (*body_->elements())) {
- if (element.type() != ResourceRequestBody::Element::TYPE_BLOB) {
+ std::vector<const ResourceRequestBodyImpl::Element*> resolved_elements;
+ for (const ResourceRequestBodyImpl::Element& element : (*body_->elements())) {
+ if (element.type() != ResourceRequestBodyImpl::Element::TYPE_BLOB) {
resolved_elements.push_back(&element);
continue;
}
@@ -597,26 +598,26 @@ void ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid,
storage::BlobDataBuilder blob_builder(uuid);
for (size_t i = 0; i < resolved_elements.size(); ++i) {
- const ResourceRequestBody::Element& element = *resolved_elements[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 ResourceRequestBody::Element::TYPE_BYTES:
+ case ResourceRequestBodyImpl::Element::TYPE_BYTES:
blob_builder.AppendData(element.bytes(), element.length());
break;
- case ResourceRequestBody::Element::TYPE_FILE:
+ case ResourceRequestBodyImpl::Element::TYPE_FILE:
blob_builder.AppendFile(element.path(), element.offset(),
element.length(),
element.expected_modification_time());
break;
- case ResourceRequestBody::Element::TYPE_BLOB:
+ case ResourceRequestBodyImpl::Element::TYPE_BLOB:
// Blob elements should be resolved beforehand.
NOTREACHED();
break;
- case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
+ case ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM:
blob_builder.AppendFileSystemFile(element.filesystem_url(),
element.offset(), element.length(),
element.expected_modification_time());
@@ -632,9 +633,42 @@ void ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid,
*blob_size = total_size;
}
-void ServiceWorkerURLRequestJob::DidPrepareFetchEvent() {
+void ServiceWorkerURLRequestJob::DidPrepareFetchEvent(
+ scoped_refptr<ServiceWorkerVersion> version) {
worker_ready_time_ = base::TimeTicks::Now();
load_timing_info_.send_start = worker_ready_time_;
+
+ // Record the time taken for the browser to find and possibly start an active
+ // worker to which to dispatch a FetchEvent for a main frame resource request.
+ // For context, a FetchEvent can only be dispatched to an ACTIVATED worker
+ // that is running (it has been successfully started). The measurements starts
+ // when the browser process receives the request. The browser then finds the
+ // worker appropriate for this request (if there is none, this metric is not
+ // recorded). If that worker is already started, the browser process can send
+ // the request to it, so the measurement ends quickly. Otherwise the browser
+ // process has to start the worker and the measurement ends when the worker is
+ // successfully started.
+ // The metric is not recorded in the following situations:
+ // 1) The worker was in state INSTALLED or ACTIVATING, and the browser had to
+ // wait for it to become ACTIVATED. This is to avoid including the time to
+ // execute the activate event handlers in the worker's script.
+ // 2) The worker was started for the fetch AND DevTools was attached during
+ // startup. This is intended to avoid including the time for debugging.
+ // 3) The request is for New Tab Page. This is because it tends to dominate
+ // the stats and makes the results largely skewed.
+ if (resource_type_ != RESOURCE_TYPE_MAIN_FRAME)
+ return;
+ if (!worker_already_activated_)
+ return;
+ if (version->skip_recording_startup_time() &&
+ initial_worker_status_ != EmbeddedWorkerStatus::RUNNING) {
+ return;
+ }
+ if (ServiceWorkerMetrics::ShouldExcludeURLFromHistogram(request()->url()))
+ return;
+ ServiceWorkerMetrics::RecordActivatedWorkerPreparationTimeForMainFrame(
+ worker_ready_time_ - request()->creation_time(), initial_worker_status_,
+ version->embedded_worker()->start_situation());
}
void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
@@ -740,6 +774,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
streaming_version_->AddStreamingURLRequestJob(this);
response_url_ = response.url;
service_worker_response_type_ = response.response_type;
+ cors_exposed_header_names_ = response.cors_exposed_header_names;
response_time_ = response.response_time;
CreateResponseHeader(
response.status_code, response.status_text, response.headers);
@@ -781,6 +816,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
response_time_ = response.response_time;
response_is_in_cache_storage_ = response.is_in_cache_storage;
response_cache_storage_cache_name_ = response.cache_storage_cache_name;
+ cors_exposed_header_names_ = response.cors_exposed_header_names;
CreateResponseHeader(
response.status_code, response.status_text, response.headers);
load_timing_info_.receive_headers_end = base::TimeTicks::Now();
@@ -915,15 +951,16 @@ void ServiceWorkerURLRequestJob::OnStartCompleted() const {
base::TimeTicks() /* service_worker_start_time */,
base::TimeTicks() /* service_worker_ready_time */,
false /* respons_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */);
+ std::string() /* response_cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */);
return;
}
ServiceWorkerResponseInfo::ForRequest(request_, true)
- ->OnStartCompleted(true /* was_fetched_via_service_worker */,
- fall_back_required_, response_url_,
- service_worker_response_type_, worker_start_time_,
- worker_ready_time_, response_is_in_cache_storage_,
- response_cache_storage_cache_name_);
+ ->OnStartCompleted(
+ true /* was_fetched_via_service_worker */, fall_back_required_,
+ response_url_, service_worker_response_type_, worker_start_time_,
+ worker_ready_time_, response_is_in_cache_storage_,
+ response_cache_storage_cache_name_, cors_exposed_header_names_);
}
bool ServiceWorkerURLRequestJob::IsMainResourceLoad() const {
@@ -959,11 +996,15 @@ void ServiceWorkerURLRequestJob::RequestBodyBlobsCompleted(bool success) {
return;
}
+ worker_already_activated_ =
+ active_worker->status() == ServiceWorkerVersion::ACTIVATED;
+ initial_worker_status_ = active_worker->running_status();
+
DCHECK(!fetch_dispatcher_);
fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
- CreateFetchRequest(), active_worker, resource_type_,
+ CreateFetchRequest(), active_worker, resource_type_, request()->net_log(),
base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent,
- weak_factory_.GetWeakPtr()),
+ weak_factory_.GetWeakPtr(), active_worker),
base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent,
weak_factory_.GetWeakPtr())));
worker_start_time_ = base::TimeTicks::Now();
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 b311e0bec02..029871bed96 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
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/streams/stream_read_observer.h"
#include "content/browser/streams/stream_register_observer.h"
@@ -43,7 +44,7 @@ class BlobStorageContext;
namespace content {
class ResourceContext;
-class ResourceRequestBody;
+class ResourceRequestBodyImpl;
class ServiceWorkerContextCore;
class ServiceWorkerFetchDispatcher;
class ServiceWorkerProviderHost;
@@ -95,7 +96,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
- scoped_refptr<ResourceRequestBody> body,
+ scoped_refptr<ResourceRequestBodyImpl> body,
ServiceWorkerFetchType fetch_type,
Delegate* delegate);
@@ -179,7 +180,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
void CreateRequestBodyBlob(std::string* blob_uuid, uint64_t* blob_size);
// For FORWARD_TO_SERVICE_WORKER case.
- void DidPrepareFetchEvent();
+ void DidPrepareFetchEvent(scoped_refptr<ServiceWorkerVersion> version);
void DidDispatchFetchEvent(
ServiceWorkerStatusCode status,
ServiceWorkerFetchEventResult fetch_result,
@@ -265,7 +266,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
bool fall_back_required_;
// ResourceRequestBody has a collection of BlobDataHandles attached to it
// using the userdata mechanism. So we have to keep it not to free the blobs.
- scoped_refptr<ResourceRequestBody> body_;
+ scoped_refptr<ResourceRequestBodyImpl> body_;
std::unique_ptr<storage::BlobDataHandle> request_body_blob_data_handle_;
scoped_refptr<ServiceWorkerVersion> streaming_version_;
ServiceWorkerFetchType fetch_type_;
@@ -276,8 +277,13 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
bool response_is_in_cache_storage_ = false;
std::string response_cache_storage_cache_name_;
+ ServiceWorkerHeaderList cors_exposed_header_names_;
+
std::unique_ptr<BlobConstructionWaiter> blob_construction_waiter_;
+ bool worker_already_activated_ = false;
+ EmbeddedWorkerStatus initial_worker_status_ = EmbeddedWorkerStatus::STOPPED;
+
base::WeakPtrFactory<ServiceWorkerURLRequestJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJob);
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 489a4579b01..e23535fc24f 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
@@ -30,7 +30,7 @@
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_context.h"
#include "content/browser/streams/stream_registry.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/common/request_context_frame_type.h"
@@ -40,11 +40,11 @@
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/io_buffer.h"
-#include "net/base/test_data_directory.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/ssl/ssl_info.h"
#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory_impl.h"
@@ -76,10 +76,13 @@ class MockHttpProtocolHandler
resource_context_(resource_context),
blob_storage_context_(blob_storage_context),
job_(nullptr),
- delegate_(delegate) {}
+ delegate_(delegate),
+ resource_type_(RESOURCE_TYPE_MAIN_FRAME) {}
~MockHttpProtocolHandler() override {}
+ void set_resource_type(ResourceType type) { resource_type_ = type; }
+
net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override {
@@ -94,13 +97,14 @@ class MockHttpProtocolHandler
request, network_delegate, provider_host_->client_uuid(),
blob_storage_context_, resource_context_, FETCH_REQUEST_MODE_NO_CORS,
FETCH_CREDENTIALS_MODE_OMIT, FetchRedirectMode::FOLLOW_MODE,
- RESOURCE_TYPE_MAIN_FRAME, REQUEST_CONTEXT_TYPE_HYPERLINK,
+ resource_type_, REQUEST_CONTEXT_TYPE_HYPERLINK,
REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
- scoped_refptr<ResourceRequestBody>(), ServiceWorkerFetchType::FETCH,
+ scoped_refptr<ResourceRequestBodyImpl>(), ServiceWorkerFetchType::FETCH,
delegate_);
job_->ForwardToServiceWorker();
return job_;
}
+ ServiceWorkerURLRequestJob* job() { return job_; }
private:
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
@@ -108,6 +112,7 @@ class MockHttpProtocolHandler
base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
mutable ServiceWorkerURLRequestJob* job_;
ServiceWorkerURLRequestJob::Delegate* delegate_;
+ ResourceType resource_type_;
};
// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
@@ -194,11 +199,12 @@ class ServiceWorkerURLRequestJobTest
chrome_blob_storage_context->context();
url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
- url_request_job_factory_->SetProtocolHandler(
- "https",
- base::WrapUnique(new MockHttpProtocolHandler(
- provider_host->AsWeakPtr(), browser_context_->GetResourceContext(),
- blob_storage_context->AsWeakPtr(), this)));
+ std::unique_ptr<MockHttpProtocolHandler> handler(
+ new MockHttpProtocolHandler(provider_host->AsWeakPtr(),
+ browser_context_->GetResourceContext(),
+ blob_storage_context->AsWeakPtr(), this));
+ http_protocol_handler_ = handler.get();
+ url_request_job_factory_->SetProtocolHandler("https", std::move(handler));
url_request_job_factory_->SetProtocolHandler(
"blob", CreateMockBlobProtocolHandler(blob_storage_context));
url_request_context_.set_job_factory(url_request_job_factory_.get());
@@ -247,9 +253,7 @@ class ServiceWorkerURLRequestJobTest
expected_response, expect_valid_ssl);
}
- bool HasInflightRequests() {
- return version_->HasInflightRequests();
- }
+ bool HasWork() { return version_->HasWork(); }
// ServiceWorkerURLRequestJob::Delegate implementation:
void OnPrepareToRestart() override { times_prepare_to_restart_invoked_++; }
@@ -282,6 +286,31 @@ class ServiceWorkerURLRequestJobTest
provider_host_->NotifyControllerLost();
}
+ // Runs a request where the active worker starts a request in ACTIVATING state
+ // and fails to reach ACTIVATED.
+ void RunFailToActivateTest(ResourceType resource_type) {
+ http_protocol_handler_->set_resource_type(resource_type);
+
+ // Start a request with an activating worker.
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
+ request_ = url_request_context_.CreateRequest(
+ GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
+ &url_request_delegate_);
+ request_->set_method("GET");
+ request_->Start();
+
+ // Proceed until the job starts waiting for the worker to activate.
+ base::RunLoop().RunUntilIdle();
+
+ // Simulate another worker kicking out the incumbent worker. PostTask since
+ // it might respond synchronously, and the MockURLRequestDelegate would
+ // complain that the message loop isn't being run.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ServiceWorkerVersion::SetStatus, version_,
+ ServiceWorkerVersion::REDUNDANT));
+ base::RunLoop().RunUntilIdle();
+ }
+
TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<TestBrowserContext> browser_context_;
@@ -298,6 +327,8 @@ class ServiceWorkerURLRequestJobTest
int times_prepare_to_restart_invoked_ = 0;
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+ // Not owned.
+ MockHttpProtocolHandler* http_protocol_handler_;
private:
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJobTest);
@@ -329,18 +360,23 @@ class ProviderDeleteHelper : public EmbeddedWorkerTestHelper {
protected:
void OnFetchEvent(int embedded_worker_id,
- int request_id,
+ int response_id,
+ int event_finish_id,
const ServiceWorkerFetchRequest& request) override {
context()->RemoveProviderHost(mock_render_process_id(), kProviderID);
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id, request_id,
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
+ embedded_worker_id, response_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
ServiceWorkerHeaderMap(), std::string(), 0, GURL(),
blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */)));
+ std::string() /* response_cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */)));
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
+ embedded_worker_id, event_finish_id,
+ blink::WebServiceWorkerEventResultCompleted));
}
private:
@@ -408,17 +444,22 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
protected:
void OnFetchEvent(int embedded_worker_id,
- int request_id,
+ int response_id,
+ int event_finish_id,
const ServiceWorkerFetchRequest& request) override {
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id, request_id,
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
+ embedded_worker_id, response_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
ServiceWorkerHeaderMap(), blob_uuid_, blob_size_, GURL(),
blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */)));
+ std::string() /* response_cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */)));
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
+ embedded_worker_id, event_finish_id,
+ blink::WebServiceWorkerEventResultCompleted));
}
std::string blob_uuid_;
@@ -486,17 +527,22 @@ class StreamResponder : public EmbeddedWorkerTestHelper {
protected:
void OnFetchEvent(int embedded_worker_id,
- int request_id,
+ int response_id,
+ int event_finish_id,
const ServiceWorkerFetchRequest& request) override {
- SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id, request_id,
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
+ embedded_worker_id, response_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
ServiceWorkerHeaderMap(), "", 0, stream_url_,
blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
false /* response_is_in_cache_storage */,
- std::string() /* response_cache_storage_cache_name */)));
+ std::string() /* response_cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */)));
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
+ embedded_worker_id, event_finish_id,
+ blink::WebServiceWorkerEventResultCompleted));
}
const GURL stream_url_;
@@ -528,9 +574,9 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse) {
}
stream->Finalize();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(HasInflightRequests());
+ EXPECT_TRUE(HasWork());
EXPECT_TRUE(request_->status().is_success());
EXPECT_EQ(200,
request_->response_headers()->response_code());
@@ -551,7 +597,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse) {
EXPECT_FALSE(info->service_worker_ready_time().is_null());
request_.reset();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
}
TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_DelayedRegistration) {
@@ -578,9 +624,9 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_DelayedRegistration) {
}
stream->Finalize();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(HasInflightRequests());
+ EXPECT_TRUE(HasWork());
EXPECT_TRUE(request_->status().is_success());
EXPECT_EQ(200,
request_->response_headers()->response_code());
@@ -601,7 +647,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_DelayedRegistration) {
EXPECT_FALSE(info->service_worker_ready_time().is_null());
request_.reset();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
}
@@ -627,9 +673,9 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_QuickFinalize) {
&url_request_delegate_);
request_->set_method("GET");
request_->Start();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(HasInflightRequests());
+ EXPECT_TRUE(HasWork());
EXPECT_TRUE(request_->status().is_success());
EXPECT_EQ(200,
request_->response_headers()->response_code());
@@ -650,10 +696,9 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_QuickFinalize) {
EXPECT_FALSE(info->service_worker_ready_time().is_null());
request_.reset();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
}
-
TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_Flush) {
const GURL stream_url("blob://stream");
StreamContext* stream_context =
@@ -717,9 +762,9 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponseAndCancel) {
&url_request_delegate_);
request_->set_method("GET");
request_->Start();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(HasInflightRequests());
+ EXPECT_TRUE(HasWork());
std::string expected_response;
expected_response.reserve((sizeof(kTestData) - 1) * 1024);
@@ -729,7 +774,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponseAndCancel) {
}
ASSERT_TRUE(stream_context->registry()->GetStream(stream_url).get());
request_->Cancel();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
ASSERT_FALSE(stream_context->registry()->GetStream(stream_url).get());
for (int i = 0; i < 512; ++i) {
expected_response += kTestData;
@@ -767,11 +812,11 @@ TEST_F(ServiceWorkerURLRequestJobTest,
&url_request_delegate_);
request_->set_method("GET");
request_->Start();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(HasInflightRequests());
+ EXPECT_TRUE(HasWork());
request_->Cancel();
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
scoped_refptr<Stream> stream =
new Stream(stream_context->registry(), nullptr, stream_url);
@@ -796,7 +841,8 @@ class FailFetchHelper : public EmbeddedWorkerTestHelper {
protected:
void OnFetchEvent(int embedded_worker_id,
- int request_id,
+ int response_id,
+ int event_finish_id,
const ServiceWorkerFetchRequest& request) override {
SimulateWorkerStopped(embedded_worker_id);
}
@@ -820,7 +866,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, FailFetchDispatch) {
// We should have fallen back to network.
EXPECT_EQ(200, request_->GetResponseCode());
EXPECT_EQ("PASS", url_request_delegate_.response_data());
- EXPECT_FALSE(HasInflightRequests());
+ EXPECT_FALSE(HasWork());
ServiceWorkerProviderHost* host = helper_->context()->GetProviderHost(
helper_->mock_render_process_id(), kProviderID);
ASSERT_TRUE(host);
@@ -862,6 +908,170 @@ TEST_F(ServiceWorkerURLRequestJobTest, MainScriptHTTPResponseInfoNotSet) {
EXPECT_FALSE(info->service_worker_ready_time().is_null());
}
+TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_MainResource) {
+ RunFailToActivateTest(RESOURCE_TYPE_MAIN_FRAME);
+
+ // The load should fail and we should have fallen back to network because
+ // this is a main resource request.
+ EXPECT_TRUE(request_->status().is_success());
+ EXPECT_EQ(200, request_->GetResponseCode());
+ EXPECT_EQ("PASS", url_request_delegate_.response_data());
+
+ // The controller should be reset since the main resource request failed.
+ ServiceWorkerProviderHost* host = helper_->context()->GetProviderHost(
+ helper_->mock_render_process_id(), kProviderID);
+ ASSERT_TRUE(host);
+ EXPECT_EQ(host->controlling_version(), nullptr);
+}
+
+TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_Subresource) {
+ RunFailToActivateTest(RESOURCE_TYPE_IMAGE);
+
+ // The load should fail and we should not fall back to network because
+ // this is a subresource request.
+ EXPECT_TRUE(request_->status().is_success());
+ EXPECT_EQ(500, request_->GetResponseCode());
+ EXPECT_EQ("Service Worker Response Error",
+ request_->response_headers()->GetStatusText());
+
+ // The controller should still be set after a subresource request fails.
+ ServiceWorkerProviderHost* host = helper_->context()->GetProviderHost(
+ helper_->mock_render_process_id(), kProviderID);
+ ASSERT_TRUE(host);
+ EXPECT_EQ(host->controlling_version(), version_);
+}
+
+class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
+ public:
+ EarlyResponseHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+ ~EarlyResponseHelper() override {}
+
+ void FinishWaitUntil() {
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
+ embedded_worker_id_, event_finish_id_,
+ blink::WebServiceWorkerEventResultCompleted));
+ }
+
+ 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;
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
+ embedded_worker_id, response_id,
+ SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
+ ServiceWorkerResponse(
+ GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
+ ServiceWorkerHeaderMap(), std::string(), 0, GURL(),
+ blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* response_is_in_cache_storage */,
+ std::string() /* response_cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */)));
+ }
+
+ private:
+ int embedded_worker_id_ = 0;
+ int event_finish_id_ = 0;
+ 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) {
+ EarlyResponseHelper* helper = new EarlyResponseHelper;
+ SetUpWithHelper(helper);
+
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ TestRequest(200, "OK", std::string(), true /* expect_valid_ssl */);
+
+ EXPECT_EQ(0, times_prepare_to_restart_invoked_);
+ ServiceWorkerResponseInfo* info =
+ ServiceWorkerResponseInfo::ForRequest(request_.get());
+ ASSERT_TRUE(info);
+ EXPECT_TRUE(info->was_fetched_via_service_worker());
+ EXPECT_FALSE(info->was_fallback_required());
+ EXPECT_EQ(GURL(), info->original_url_via_service_worker());
+ EXPECT_EQ(blink::WebServiceWorkerResponseTypeDefault,
+ info->response_type_via_service_worker());
+ EXPECT_FALSE(info->service_worker_start_time().is_null());
+ EXPECT_FALSE(info->service_worker_ready_time().is_null());
+ EXPECT_FALSE(info->response_is_in_cache_storage());
+ EXPECT_EQ(std::string(), info->response_cache_storage_cache_name());
+
+ EXPECT_TRUE(version_->HasWork());
+ helper->FinishWaitUntil();
+ EXPECT_FALSE(version_->HasWork());
+}
+
+// Helper for controlling when to respond to a fetch event.
+class DelayedResponseHelper : public EmbeddedWorkerTestHelper {
+ public:
+ DelayedResponseHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+ ~DelayedResponseHelper() override {}
+
+ void Respond() {
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventResponse(
+ embedded_worker_id_, response_id_,
+ SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
+ ServiceWorkerResponse(
+ GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
+ ServiceWorkerHeaderMap(), std::string(), 0, GURL(),
+ blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* response_is_in_cache_storage */,
+ std::string() /* response_cache_storage_cache_name */,
+ ServiceWorkerHeaderList() /* cors_exposed_header_names */)));
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
+ embedded_worker_id_, event_finish_id_,
+ blink::WebServiceWorkerEventResultCompleted));
+ }
+
+ protected:
+ void OnFetchEvent(int embedded_worker_id,
+ int response_id,
+ int event_finish_id,
+ const ServiceWorkerFetchRequest& request) override {
+ embedded_worker_id_ = embedded_worker_id;
+ response_id_ = response_id;
+ event_finish_id_ = event_finish_id;
+ }
+
+ private:
+ int embedded_worker_id_ = 0;
+ int response_id_ = 0;
+ int event_finish_id_ = 0;
+ DISALLOW_COPY_AND_ASSIGN(DelayedResponseHelper);
+};
+
+// Test cancelling the URLRequest while the fetch event is in flight.
+TEST_F(ServiceWorkerURLRequestJobTest, CancelRequest) {
+ DelayedResponseHelper* helper = new DelayedResponseHelper;
+ SetUpWithHelper(helper);
+
+ // Start the URL request. The job will be waiting for the
+ // worker to respond to the fetch event.
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ request_ = url_request_context_.CreateRequest(
+ GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
+ &url_request_delegate_);
+ request_->set_method("GET");
+ request_->Start();
+ base::RunLoop().RunUntilIdle();
+
+ // Cancel the URL request.
+ request_->Cancel();
+ base::RunLoop().RunUntilIdle();
+
+ // Respond to the fetch event.
+ EXPECT_TRUE(version_->HasWork());
+ helper->Respond();
+ base::RunLoop().RunUntilIdle();
+
+ // The fetch event request should no longer be in-flight.
+ EXPECT_FALSE(version_->HasWork());
+}
+
// TODO(kinuko): Add more tests with different response data and also for
// FallbackToNetwork case.
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index f3f506d67da..8f4ee9d0939 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -28,6 +28,7 @@
#include "content/browser/message_port_service.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_client_utils.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -43,9 +44,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
-#include "content/public/common/service_registry.h"
#include "mojo/common/common_type_converters.h"
-#include "mojo/common/url_type_converters.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
@@ -103,7 +102,7 @@ void RunTaskAfterStartWorker(
error_callback.Run(status);
return;
}
- if (version->running_status() != ServiceWorkerVersion::RUNNING) {
+ if (version->running_status() != EmbeddedWorkerStatus::RUNNING) {
// We've tried to start the worker (and it has succeeded), but
// it looks it's not running yet.
NOTREACHED() << "The worker's not running after successful StartWorker";
@@ -326,8 +325,10 @@ ServiceWorkerVersion::~ServiceWorkerVersion() {
if (context_)
context_->RemoveLiveVersion(version_id_);
- if (running_status() == STARTING || running_status() == RUNNING)
+ if (running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::RUNNING) {
embedded_worker_->Stop();
+ }
embedded_worker_->RemoveListener(this);
}
@@ -335,21 +336,31 @@ void ServiceWorkerVersion::SetStatus(Status status) {
if (status_ == status)
return;
- status_ = status;
+ TRACE_EVENT2("ServiceWorker", "ServiceWorkerVersion::SetStatus", "Script URL",
+ script_url_.spec(), "New Status", VersionStatusToString(status));
+ status_ = status;
if (skip_waiting_ && status_ == ACTIVATED) {
for (int request_id : pending_skip_waiting_requests_)
DidSkipWaiting(request_id);
pending_skip_waiting_requests_.clear();
}
+ // OnVersionStateChanged() invokes updates of the status using state
+ // change IPC at ServiceWorkerHandle (for JS-land on renderer process) and
+ // ServiceWorkerContextCore (for devtools and serviceworker-internals).
+ // This should be done before using the new status by
+ // |status_change_callbacks_| which sends the IPC for resolving the .ready
+ // property.
+ // TODO(shimazu): Clarify the dependency of OnVersionStateChanged and
+ // |status_change_callbacks_|
+ FOR_EACH_OBSERVER(Listener, listeners_, OnVersionStateChanged(this));
+
std::vector<base::Closure> callbacks;
callbacks.swap(status_change_callbacks_);
for (const auto& callback : callbacks)
callback.Run();
- FOR_EACH_OBSERVER(Listener, listeners_, OnVersionStateChanged(this));
-
if (status == INSTALLED)
embedded_worker_->OnWorkerVersionInstalled();
else if (status == REDUNDANT)
@@ -436,7 +447,7 @@ void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) {
TRACE_EVENT_SCOPE_THREAD, "Script", script_url_.spec(),
"Status", VersionStatusToString(status_));
- if (running_status() == STOPPED) {
+ if (running_status() == EmbeddedWorkerStatus::STOPPED) {
RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
return;
}
@@ -499,7 +510,7 @@ int ServiceWorkerVersion::StartRequestWithCustomTimeout(
const base::TimeDelta& timeout,
TimeoutBehavior timeout_behavior) {
OnBeginEvent();
- DCHECK_EQ(RUNNING, running_status())
+ DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status())
<< "Can only start a request with a running worker.";
DCHECK(event_type == ServiceWorkerMetrics::EventType::INSTALL ||
event_type == ServiceWorkerMetrics::EventType::ACTIVATE ||
@@ -534,11 +545,9 @@ bool ServiceWorkerVersion::FinishRequest(int request_id, bool was_handled) {
TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
request, "Handled", was_handled);
custom_requests_.Remove(request_id);
- if (is_redundant()) {
- // The stop should be already scheduled, but try to stop immediately, in
- // order to release worker resources soon.
- StopWorkerIfIdle();
- }
+ if (!HasWork())
+ FOR_EACH_OBSERVER(Listener, listeners_, OnNoWork(this));
+
return true;
}
@@ -546,7 +555,7 @@ void ServiceWorkerVersion::RunAfterStartWorker(
ServiceWorkerMetrics::EventType purpose,
const base::Closure& task,
const StatusCallback& error_callback) {
- if (running_status() == RUNNING) {
+ if (running_status() == EmbeddedWorkerStatus::RUNNING) {
DCHECK(start_callbacks_.empty());
task.Run();
return;
@@ -556,6 +565,27 @@ void ServiceWorkerVersion::RunAfterStartWorker(
error_callback, task));
}
+void ServiceWorkerVersion::DispatchEvent(const std::vector<int>& request_ids,
+ const IPC::Message& message) {
+ DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status());
+
+ const ServiceWorkerStatusCode status = embedded_worker_->SendMessage(message);
+
+ for (int request_id : request_ids) {
+ PendingRequest<StatusCallback>* request =
+ custom_requests_.Lookup(request_id);
+ DCHECK(request) << "Invalid request id";
+ DCHECK(!request->is_dispatched)
+ << "Request already dispatched an IPC event";
+ if (status != SERVICE_WORKER_OK) {
+ RunSoon(base::Bind(request->callback, status));
+ custom_requests_.Remove(request_id);
+ } else {
+ request->is_dispatched = true;
+ }
+ }
+}
+
void ServiceWorkerVersion::AddControllee(
ServiceWorkerProviderHost* provider_host) {
const std::string& uuid = provider_host->client_uuid();
@@ -575,9 +605,8 @@ void ServiceWorkerVersion::RemoveControllee(
controllee_map_.erase(uuid);
FOR_EACH_OBSERVER(Listener, listeners_,
OnControlleeRemoved(this, provider_host));
- if (HasControllee())
- return;
- FOR_EACH_OBSERVER(Listener, listeners_, OnNoControllees(this));
+ if (!HasControllee())
+ FOR_EACH_OBSERVER(Listener, listeners_, OnNoControllees(this));
}
void ServiceWorkerVersion::AddStreamingURLRequestJob(
@@ -590,8 +619,8 @@ void ServiceWorkerVersion::AddStreamingURLRequestJob(
void ServiceWorkerVersion::RemoveStreamingURLRequestJob(
const ServiceWorkerURLRequestJob* request_job) {
streaming_url_request_jobs_.erase(request_job);
- if (is_redundant())
- StopWorkerIfIdle();
+ if (!HasWork())
+ FOR_EACH_OBSERVER(Listener, listeners_, OnNoWork(this));
}
void ServiceWorkerVersion::AddListener(Listener* listener) {
@@ -620,7 +649,8 @@ void ServiceWorkerVersion::SetStartWorkerStatusCode(
void ServiceWorkerVersion::Doom() {
DCHECK(!HasControllee());
SetStatus(REDUNDANT);
- if (running_status() == STARTING || running_status() == RUNNING) {
+ if (running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::RUNNING) {
if (embedded_worker()->devtools_attached())
stop_when_devtools_detached_ = true;
else
@@ -637,8 +667,10 @@ void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
embedded_worker()->set_devtools_attached(attached);
if (stop_when_devtools_detached_ && !attached) {
DCHECK_EQ(REDUNDANT, status());
- if (running_status() == STARTING || running_status() == RUNNING)
+ if (running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::RUNNING) {
embedded_worker_->Stop();
+ }
return;
}
if (attached) {
@@ -657,8 +689,9 @@ void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
if (!start_callbacks_.empty()) {
// Reactivate the timer for start timeout.
DCHECK(timeout_timer_.IsRunning());
- DCHECK(running_status() == STARTING || running_status() == STOPPING)
- << running_status();
+ DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::STOPPING)
+ << static_cast<int>(running_status());
RestartTick(&start_time_);
}
@@ -730,7 +763,7 @@ ServiceWorkerVersion::BaseMojoServiceWrapper::~BaseMojoServiceWrapper() {
}
void ServiceWorkerVersion::OnThreadStarted() {
- DCHECK_EQ(STARTING, running_status());
+ DCHECK_EQ(EmbeddedWorkerStatus::STARTING, running_status());
// Activate ping/pong now that JavaScript execution will start.
ping_controller_->Activate();
}
@@ -740,7 +773,7 @@ void ServiceWorkerVersion::OnStarting() {
}
void ServiceWorkerVersion::OnStarted() {
- DCHECK_EQ(RUNNING, running_status());
+ DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status());
RestartTick(&idle_time_);
// Fire all start callbacks.
@@ -765,8 +798,7 @@ void ServiceWorkerVersion::OnStopping() {
FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this));
}
-void ServiceWorkerVersion::OnStopped(
- EmbeddedWorkerInstance::Status old_status) {
+void ServiceWorkerVersion::OnStopped(EmbeddedWorkerStatus old_status) {
if (IsInstalled(status())) {
ServiceWorkerMetrics::RecordWorkerStopped(
ServiceWorkerMetrics::StopStatus::NORMAL);
@@ -777,8 +809,7 @@ void ServiceWorkerVersion::OnStopped(
OnStoppedInternal(old_status);
}
-void ServiceWorkerVersion::OnDetached(
- EmbeddedWorkerInstance::Status old_status) {
+void ServiceWorkerVersion::OnDetached(EmbeddedWorkerStatus old_status) {
if (IsInstalled(status())) {
ServiceWorkerMetrics::RecordWorkerStopped(
ServiceWorkerMetrics::StopStatus::DETACH_BY_REGISTRY);
@@ -889,8 +920,10 @@ void ServiceWorkerVersion::OnGetClientFinished(
// When Clients.get() is called on the script evaluation phase, the running
// status can be STARTING here.
- if (running_status() != STARTING && running_status() != RUNNING)
+ if (running_status() != EmbeddedWorkerStatus::STARTING &&
+ running_status() != EmbeddedWorkerStatus::RUNNING) {
return;
+ }
embedded_worker_->SendMessage(
ServiceWorkerMsg_DidGetClient(request_id, client_info));
@@ -917,8 +950,10 @@ void ServiceWorkerVersion::OnGetClientsFinished(int request_id,
// When Clients.matchAll() is called on the script evaluation phase, the
// running status can be STARTING here.
- if (running_status() != STARTING && running_status() != RUNNING)
+ if (running_status() != EmbeddedWorkerStatus::STARTING &&
+ running_status() != EmbeddedWorkerStatus::RUNNING) {
return;
+ }
embedded_worker_->SendMessage(
ServiceWorkerMsg_DidGetClients(request_id, *clients));
@@ -983,7 +1018,7 @@ void ServiceWorkerVersion::OnOpenWindowFinished(
const ServiceWorkerClientInfo& client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (running_status() != RUNNING)
+ if (running_status() != EmbeddedWorkerStatus::RUNNING)
return;
if (status != SERVICE_WORKER_OK) {
@@ -1091,7 +1126,7 @@ void ServiceWorkerVersion::OnFocusClientFinished(
const ServiceWorkerClientInfo& client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (running_status() != RUNNING)
+ if (running_status() != EmbeddedWorkerStatus::RUNNING)
return;
embedded_worker_->SendMessage(
@@ -1147,7 +1182,7 @@ void ServiceWorkerVersion::OnNavigateClientFinished(
const ServiceWorkerClientInfo& client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (running_status() != RUNNING)
+ if (running_status() != EmbeddedWorkerStatus::RUNNING)
return;
if (status != SERVICE_WORKER_OK) {
@@ -1177,8 +1212,10 @@ void ServiceWorkerVersion::OnSkipWaiting(int request_id) {
}
void ServiceWorkerVersion::DidSkipWaiting(int request_id) {
- if (running_status() == STARTING || running_status() == RUNNING)
+ if (running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::RUNNING) {
embedded_worker_->SendMessage(ServiceWorkerMsg_DidSkipWaiting(request_id));
+ }
}
void ServiceWorkerVersion::OnClaimClients(int request_id) {
@@ -1277,14 +1314,14 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
MarkIfStale();
switch (running_status()) {
- case RUNNING:
+ case EmbeddedWorkerStatus::RUNNING:
RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
return;
- case STARTING:
+ case EmbeddedWorkerStatus::STARTING:
DCHECK(!start_callbacks_.empty());
break;
- case STOPPING:
- case STOPPED:
+ case EmbeddedWorkerStatus::STOPPING:
+ case EmbeddedWorkerStatus::STOPPED:
if (start_callbacks_.empty()) {
int trace_id = NextTraceId();
TRACE_EVENT_ASYNC_BEGIN2(
@@ -1303,13 +1340,13 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
start_callbacks_.push_back(
base::Bind(&RunStartWorkerCallback, callback, protect));
- if (running_status() == STOPPED)
+ if (running_status() == EmbeddedWorkerStatus::STOPPED)
StartWorkerInternal();
DCHECK(timeout_timer_.IsRunning());
}
void ServiceWorkerVersion::StartWorkerInternal() {
- DCHECK_EQ(STOPPED, running_status());
+ DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, running_status());
DCHECK(!metrics_);
metrics_.reset(new Metrics(this));
@@ -1375,9 +1412,10 @@ void ServiceWorkerVersion::SetTimeoutTimerInterval(base::TimeDelta interval) {
}
void ServiceWorkerVersion::OnTimeoutTimer() {
- DCHECK(running_status() == STARTING || running_status() == RUNNING ||
- running_status() == STOPPING)
- << running_status();
+ DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::RUNNING ||
+ running_status() == EmbeddedWorkerStatus::STOPPING)
+ << static_cast<int>(running_status());
if (!context_)
return;
@@ -1387,7 +1425,7 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
// Stopping the worker hasn't finished within a certain period.
if (GetTickDuration(stop_time_) >
base::TimeDelta::FromSeconds(kStopWorkerTimeoutSeconds)) {
- DCHECK_EQ(STOPPING, running_status());
+ DCHECK_EQ(EmbeddedWorkerStatus::STOPPING, running_status());
if (IsInstalled(status())) {
ServiceWorkerMetrics::RecordWorkerStopped(
ServiceWorkerMetrics::StopStatus::TIMEOUT);
@@ -1403,7 +1441,7 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
embedded_worker_->AddListener(this);
// Call OnStoppedInternal to fail callbacks and possibly restart.
- OnStoppedInternal(EmbeddedWorkerInstance::STOPPING);
+ OnStoppedInternal(EmbeddedWorkerStatus::STOPPING);
return;
}
@@ -1422,11 +1460,12 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
? base::TimeDelta::FromSeconds(kStartInstalledWorkerTimeoutSeconds)
: base::TimeDelta::FromMinutes(kStartNewWorkerTimeoutMinutes);
if (GetTickDuration(start_time_) > start_limit) {
- DCHECK(running_status() == STARTING || running_status() == STOPPING)
- << running_status();
+ DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::STOPPING)
+ << static_cast<int>(running_status());
scoped_refptr<ServiceWorkerVersion> protect(this);
RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT);
- if (running_status() == STARTING)
+ if (running_status() == EmbeddedWorkerStatus::STARTING)
embedded_worker_->Stop();
return;
}
@@ -1444,12 +1483,12 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
}
requests_.pop();
}
- if (stop_for_timeout && running_status() != STOPPING)
+ if (stop_for_timeout && running_status() != EmbeddedWorkerStatus::STOPPING)
embedded_worker_->Stop();
// For the timeouts below, there are no callbacks to timeout so there is
// nothing more to do if the worker is already stopping.
- if (running_status() == STOPPING)
+ if (running_status() == EmbeddedWorkerStatus::STOPPING)
return;
// The worker has been idle for longer than a certain period.
@@ -1464,12 +1503,14 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
}
ServiceWorkerStatusCode ServiceWorkerVersion::PingWorker() {
- DCHECK(running_status() == STARTING || running_status() == RUNNING);
+ DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::RUNNING);
return embedded_worker_->SendMessage(ServiceWorkerMsg_Ping());
}
void ServiceWorkerVersion::OnPingTimeout() {
- DCHECK(running_status() == STARTING || running_status() == RUNNING);
+ DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::RUNNING);
// TODO(falken): Show a message to the developer that the SW was stopped due
// to timeout (crbug.com/457968). Also, change the error code to
// SERVICE_WORKER_ERROR_TIMEOUT.
@@ -1477,9 +1518,10 @@ void ServiceWorkerVersion::OnPingTimeout() {
}
void ServiceWorkerVersion::StopWorkerIfIdle() {
- if (HasInflightRequests() && !ping_controller_->IsTimedOut())
+ if (HasWork() && !ping_controller_->IsTimedOut())
return;
- if (running_status() == STOPPED || running_status() == STOPPING ||
+ if (running_status() == EmbeddedWorkerStatus::STOPPED ||
+ running_status() == EmbeddedWorkerStatus::STOPPING ||
!stop_callbacks_.empty()) {
return;
}
@@ -1487,8 +1529,9 @@ void ServiceWorkerVersion::StopWorkerIfIdle() {
embedded_worker_->StopIfIdle();
}
-bool ServiceWorkerVersion::HasInflightRequests() const {
- return !custom_requests_.IsEmpty() || !streaming_url_request_jobs_.empty();
+bool ServiceWorkerVersion::HasWork() const {
+ return !custom_requests_.IsEmpty() || !streaming_url_request_jobs_.empty() ||
+ !start_callbacks_.empty();
}
void ServiceWorkerVersion::RecordStartWorkerResult(
@@ -1516,18 +1559,19 @@ void ServiceWorkerVersion::RecordStartWorkerResult(
ServiceWorkerMetrics::RecordStartWorkerTime(
GetTickDuration(start_time), IsInstalled(prestart_status),
ServiceWorkerMetrics::GetStartSituation(
- is_browser_startup_complete, embedded_worker_->is_new_process()));
+ is_browser_startup_complete, embedded_worker_->is_new_process()),
+ purpose);
}
if (status != SERVICE_WORKER_ERROR_TIMEOUT)
return;
EmbeddedWorkerInstance::StartingPhase phase =
EmbeddedWorkerInstance::NOT_STARTING;
- EmbeddedWorkerInstance::Status running_status = embedded_worker_->status();
+ EmbeddedWorkerStatus running_status = embedded_worker_->status();
// Build an artifical JavaScript exception to show in the ServiceWorker
// log for developers; it's not user-facing so it's not a localized resource.
std::string message = "ServiceWorker startup timed out. ";
- if (running_status != EmbeddedWorkerInstance::STARTING) {
+ if (running_status != EmbeddedWorkerStatus::STARTING) {
message.append("The worker had unexpected status: ");
message.append(EmbeddedWorkerInstance::StatusToString(running_status));
} else {
@@ -1626,9 +1670,8 @@ void ServiceWorkerVersion::FoundRegistrationForUpdate(
false /* force_bypass_cache */);
}
-void ServiceWorkerVersion::OnStoppedInternal(
- EmbeddedWorkerInstance::Status old_status) {
- DCHECK_EQ(STOPPED, running_status());
+void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
+ DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, running_status());
scoped_refptr<ServiceWorkerVersion> protect;
if (!in_dtor_)
protect = this;
@@ -1637,7 +1680,7 @@ void ServiceWorkerVersion::OnStoppedInternal(
metrics_.reset();
bool should_restart = !is_redundant() && !start_callbacks_.empty() &&
- (old_status != EmbeddedWorkerInstance::STARTING) &&
+ (old_status != EmbeddedWorkerStatus::STARTING) &&
!in_dtor_ && !ping_controller_->IsTimedOut();
if (!stop_time_.is_null()) {
@@ -1679,9 +1722,10 @@ void ServiceWorkerVersion::OnStoppedInternal(
streaming_url_request_jobs_.clear();
FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this));
-
if (should_restart)
StartWorkerInternal();
+ else if (!HasWork())
+ FOR_EACH_OBSERVER(Listener, listeners_, OnNoWork(this));
}
void ServiceWorkerVersion::OnMojoConnectionError(const char* service_name) {
@@ -1691,7 +1735,8 @@ void ServiceWorkerVersion::OnMojoConnectionError(const char* service_name) {
}
void ServiceWorkerVersion::OnBeginEvent() {
- if (should_exclude_from_uma_ || running_status() != RUNNING ||
+ if (should_exclude_from_uma_ ||
+ running_status() != EmbeddedWorkerStatus::RUNNING ||
idle_time_.is_null()) {
return;
}
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index d2ed73600c9..240e838a2fc 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -26,13 +26,14 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_script_cache_map.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/service_registry.h"
#include "ipc/ipc_message.h"
+#include "services/shell/public/cpp/interface_provider.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerEventResult.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -65,14 +66,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
: NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerVersion>),
public EmbeddedWorkerInstance::Listener {
public:
- typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
-
- enum RunningStatus {
- STOPPED = EmbeddedWorkerInstance::STOPPED,
- STARTING = EmbeddedWorkerInstance::STARTING,
- RUNNING = EmbeddedWorkerInstance::RUNNING,
- STOPPING = EmbeddedWorkerInstance::STOPPING,
- };
+ using StatusCallback = base::Callback<void(ServiceWorkerStatusCode)>;
// Current version status; some of the status (e.g. INSTALLED and ACTIVATED)
// should be persisted unlike running status.
@@ -115,8 +109,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
virtual void OnControlleeRemoved(ServiceWorkerVersion* version,
ServiceWorkerProviderHost* provider_host) {
}
- // Fires when a version transitions from having a controllee to not.
virtual void OnNoControllees(ServiceWorkerVersion* version) {}
+ virtual void OnNoWork(ServiceWorkerVersion* version) {}
virtual void OnCachedMetadataUpdated(ServiceWorkerVersion* version) {}
protected:
@@ -132,11 +126,15 @@ class CONTENT_EXPORT ServiceWorkerVersion
int64_t registration_id() const { return registration_id_; }
const GURL& script_url() const { return script_url_; }
const GURL& scope() const { return scope_; }
- RunningStatus running_status() const {
- return static_cast<RunningStatus>(embedded_worker_->status());
+ EmbeddedWorkerStatus running_status() const {
+ return embedded_worker_->status();
}
ServiceWorkerVersionInfo GetInfo();
Status status() const { return status_; }
+ bool has_fetch_handler() const { return has_fetch_handler_; }
+ void set_has_fetch_handler(bool has_fetch_handler) {
+ has_fetch_handler_ = has_fetch_handler;
+ }
const std::vector<GURL>& foreign_fetch_scopes() const {
return foreign_fetch_scopes_;
@@ -194,12 +192,18 @@ class CONTENT_EXPORT ServiceWorkerVersion
const StatusCallback& error_callback);
// Call this while the worker is running before dispatching an event to the
- // worker. This informs ServiceWorkerVersion about the event in progress.
- // Returns a request id, which should later be passed to FinishRequest when
- // the event finished.
+ // worker. This informs ServiceWorkerVersion about the event in progress. The
+ // worker attempts to keep running until the event finishes.
+ //
+ // Returns a request id, which must later be passed to FinishRequest when the
+ // event finished. The caller is responsible for ensuring FinishRequest is
+ // called. If FinishRequest is not called the request will eventually time
+ // out and the worker will be forcibly terminated.
+ //
// The |error_callback| is called if either ServiceWorkerVersion decides the
// event is taking too long, or if for some reason the worker stops or is
- // killed before the request finishes.
+ // killed before the request finishes. In this case, the caller should not
+ // call FinishRequest.
int StartRequest(ServiceWorkerMetrics::EventType event_type,
const StatusCallback& error_callback);
@@ -228,19 +232,40 @@ class CONTENT_EXPORT ServiceWorkerVersion
template <typename Interface>
base::WeakPtr<Interface> GetMojoServiceForRequest(int request_id);
- // Dispatches an event. If dispatching the event fails, the error callback
- // associated with the |request_id| is called. Any messages sent back in
- // response to this event are passed on to the response |callback|.
+ // Dispatches an event. If dispatching the event fails, all of the error
+ // callbacks that were associated with |request_ids| via StartRequest are
+ // called.
+ // Use RegisterRequestCallback or RegisterSimpleRequest to register a callback
+ // to receive messages sent back in response to this event before calling this
+ // method.
+ // This must be called when the worker is running.
+ void DispatchEvent(const std::vector<int>& request_ids,
+ const IPC::Message& message);
+
+ // This method registers a callback to receive messages sent back from the
+ // service worker in response to |request_id|.
// ResponseMessage is the type of the IPC message that is used for the
// response, and its first argument MUST be the request_id.
- // This must be called when the worker is running.
+ // Callback registration should be done once for one request_id.
template <typename ResponseMessage, typename ResponseCallbackType>
- void DispatchEvent(int request_id,
- const IPC::Message& message,
- const ResponseCallbackType& callback);
+ void RegisterRequestCallback(int request_id,
+ const ResponseCallbackType& callback);
+
+ // You can use this method instead of RegisterRequestCallback when the
+ // response message sent back from the service worker consists of just
+ // a request_id and a blink::WebServiceWorkerEventResult field. The result
+ // field is converted to a ServiceWorkerStatusCode and passed to the error
+ // handler associated with the request_id which is registered by StartRequest.
+ // Additionally if you use this method, FinishRequest will be called before
+ // passing the reply to the callback.
+ // Callback registration should be done once for one request_id.
+ template <typename ResponseMessage>
+ void RegisterSimpleRequest(int request_id);
- // For simple events where the full functionality of DispatchEvent is not
- // needed, this method can be used instead. The ResponseMessage must consist
+ // This is a wrapper method equivalent to one RegisterSimpleRequest and one
+ // DispatchEvent. For simple events where the full functionality of
+ // RegisterRequestCallback/DispatchEvent is not needed, this method can be
+ // used instead. The ResponseMessage must consist
// of just a request_id and a blink::WebServiceWorkerEventResult field. The
// result is converted to a ServiceWorkerStatusCode and passed to the error
// handler associated with the request. Additionally this methods calls
@@ -249,8 +274,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
void DispatchSimpleEvent(int request_id, const IPC::Message& message);
// Adds and removes |provider_host| as a controllee of this ServiceWorker.
- // A potential controllee is a host having the version as its .installing
- // or .waiting version.
void AddControllee(ServiceWorkerProviderHost* provider_host);
void RemoveControllee(ServiceWorkerProviderHost* provider_host);
@@ -291,6 +314,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
bool skip_waiting() const { return skip_waiting_; }
void set_skip_waiting(bool skip_waiting) { skip_waiting_ = skip_waiting; }
+ bool skip_recording_startup_time() const {
+ return skip_recording_startup_time_;
+ }
+
bool force_bypass_cache_for_scripts() const {
return force_bypass_cache_for_scripts_;
}
@@ -315,6 +342,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Simulate ping timeout. Should be used for tests-only.
void SimulatePingTimeoutForTesting();
+ // Returns true if the service worker has work to do: it has pending
+ // requests, in-progress streaming URLRequestJobs, or pending start callbacks.
+ bool HasWork() const;
+
private:
friend class base::RefCounted<ServiceWorkerVersion>;
friend class ServiceWorkerMetrics;
@@ -349,6 +380,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
RequestCustomizedTimeoutKill);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, MixedRequestTimeouts);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerURLRequestJobTest, EarlyResponse);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerURLRequestJobTest, CancelRequest);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerActivationTest, SkipWaiting);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerActivationTest,
+ SkipWaitingWithInflightRequest);
class Metrics;
class PingController;
@@ -382,6 +418,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
// this would be Interface::Name_ for some mojo interface.
const char* mojo_service = nullptr;
std::unique_ptr<EmbeddedWorkerInstance::Listener> listener;
+ bool is_dispatched = false;
};
// Base class to enable storing a list of mojo interface pointers for
@@ -426,6 +463,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
std::priority_queue<RequestInfo,
std::vector<RequestInfo>,
std::greater<RequestInfo>>;
+ using WebStatusCallback =
+ base::Callback<void(int, blink::WebServiceWorkerEventResult)>;
// EmbeddedWorkerInstance Listener implementation which calls a callback
// on receiving a particular IPC message. ResponseMessage is the type of
@@ -472,8 +511,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
void OnStarting() override;
void OnStarted() override;
void OnStopping() override;
- void OnStopped(EmbeddedWorkerInstance::Status old_status) override;
- void OnDetached(EmbeddedWorkerInstance::Status old_status) override;
+ void OnStopped(EmbeddedWorkerStatus old_status) override;
+ void OnDetached(EmbeddedWorkerStatus old_status) override;
void OnScriptLoaded() override;
void OnScriptLoadFailed() override;
void OnReportException(const base::string16& error_message,
@@ -560,7 +599,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Stops the worker if it is idle (has no in-flight requests) or timed out
// ping.
void StopWorkerIfIdle();
- bool HasInflightRequests() const;
// RecordStartWorkerResult is added as a start callback by StartTimeoutTimer
// and records metrics about startup.
@@ -587,7 +625,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration);
- void OnStoppedInternal(EmbeddedWorkerInstance::Status old_status);
+ void OnStoppedInternal(EmbeddedWorkerStatus old_status);
// Called when the remote side of a connection to a mojo service is lost.
void OnMojoConnectionError(const char* service_name);
@@ -603,6 +641,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
const GURL scope_;
std::vector<GURL> foreign_fetch_scopes_;
std::vector<url::Origin> foreign_fetch_origins_;
+ bool has_fetch_handler_ = true;
Status status_ = NEW;
std::unique_ptr<EmbeddedWorkerInstance> embedded_worker_;
@@ -680,7 +719,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
template <typename Interface>
base::WeakPtr<Interface> ServiceWorkerVersion::GetMojoServiceForRequest(
int request_id) {
- DCHECK_EQ(RUNNING, running_status());
+ DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status());
PendingRequest<StatusCallback>* request = custom_requests_.Lookup(request_id);
DCHECK(request) << "Invalid request id";
DCHECK(!request->mojo_service)
@@ -691,8 +730,7 @@ base::WeakPtr<Interface> ServiceWorkerVersion::GetMojoServiceForRequest(
mojo_services_.get(Interface::Name_));
if (!service) {
mojo::InterfacePtr<Interface> interface;
- embedded_worker_->GetServiceRegistry()->ConnectToRemoteService(
- mojo::GetProxy(&interface));
+ embedded_worker_->GetRemoteInterfaces()->GetInterface(&interface);
interface.set_connection_error_handler(
base::Bind(&ServiceWorkerVersion::OnMojoConnectionError,
weak_factory_.GetWeakPtr(), Interface::Name_));
@@ -703,32 +741,30 @@ base::WeakPtr<Interface> ServiceWorkerVersion::GetMojoServiceForRequest(
return service->GetWeakPtr();
}
+template <typename ResponseMessage>
+void ServiceWorkerVersion::DispatchSimpleEvent(int request_id,
+ const IPC::Message& message) {
+ RegisterSimpleRequest<ResponseMessage>(request_id);
+ DispatchEvent({request_id}, message);
+}
+
template <typename ResponseMessage, typename ResponseCallbackType>
-void ServiceWorkerVersion::DispatchEvent(int request_id,
- const IPC::Message& message,
- const ResponseCallbackType& callback) {
- DCHECK_EQ(RUNNING, running_status());
+void ServiceWorkerVersion::RegisterRequestCallback(
+ int request_id,
+ const ResponseCallbackType& callback) {
PendingRequest<StatusCallback>* request = custom_requests_.Lookup(request_id);
DCHECK(request) << "Invalid request id";
- DCHECK(!request->listener) << "Request already dispatched an IPC event";
-
- ServiceWorkerStatusCode status = embedded_worker_->SendMessage(message);
- if (status != SERVICE_WORKER_OK) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(request->callback, status));
- custom_requests_.Remove(request_id);
- } else {
- request->listener.reset(
- new EventResponseHandler<ResponseMessage, ResponseCallbackType>(
- embedded_worker()->AsWeakPtr(), request_id, callback));
- }
+ DCHECK(!request->listener) << "Callback was already registered";
+ DCHECK(!request->is_dispatched) << "Request already dispatched an IPC event";
+ request->listener.reset(
+ new EventResponseHandler<ResponseMessage, ResponseCallbackType>(
+ embedded_worker()->AsWeakPtr(), request_id, callback));
}
template <typename ResponseMessage>
-void ServiceWorkerVersion::DispatchSimpleEvent(int request_id,
- const IPC::Message& message) {
- DispatchEvent<ResponseMessage>(
- request_id, message,
+void ServiceWorkerVersion::RegisterSimpleRequest(int request_id) {
+ RegisterRequestCallback<ResponseMessage>(
+ request_id,
base::Bind(&ServiceWorkerVersion::OnSimpleEventResponse, this));
}
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 f2b175ee68e..ea76b51478d 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -5,11 +5,13 @@
#include "content/browser/service_worker/service_worker_version.h"
#include <stdint.h>
+#include <tuple>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_registration.h"
@@ -33,6 +35,7 @@ IPC_MESSAGE_CONTROL0(TestMsg_Message)
IPC_MESSAGE_ROUTED1(TestMsg_MessageFromWorker, int)
IPC_MESSAGE_CONTROL1(TestMsg_TestEvent, int)
+IPC_MESSAGE_CONTROL2(TestMsg_TestEvent_Multiple, int, int)
IPC_MESSAGE_ROUTED2(TestMsg_TestEventResult, int, std::string)
IPC_MESSAGE_ROUTED2(TestMsg_TestSimpleEventResult,
int,
@@ -128,9 +131,7 @@ class MessageReceiverFromWorker : public EmbeddedWorkerInstance::Listener {
~MessageReceiverFromWorker() override { instance_->RemoveListener(this); }
void OnStarted() override { NOTREACHED(); }
- void OnStopped(EmbeddedWorkerInstance::Status old_status) override {
- NOTREACHED();
- }
+ void OnStopped(EmbeddedWorkerStatus old_status) override { NOTREACHED(); }
bool OnMessageReceived(const IPC::Message& message) override {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MessageReceiverFromWorker, message)
@@ -164,6 +165,14 @@ class TestMojoServiceImpl : public mojom::TestMojoService {
callback.Run();
}
+ void DoTerminateProcess(const DoTerminateProcessCallback& callback) override {
+ NOTREACHED();
+ }
+
+ void CreateFolder(const CreateFolderCallback& callback) override {
+ NOTREACHED();
+ }
+
void GetRequestorName(const GetRequestorNameCallback& callback) override {
callback.Run(mojo::String(""));
}
@@ -181,12 +190,12 @@ class TestMojoServiceImpl : public mojom::TestMojoService {
class ServiceWorkerVersionTest : public testing::Test {
protected:
struct RunningStateListener : public ServiceWorkerVersion::Listener {
- RunningStateListener() : last_status(ServiceWorkerVersion::STOPPED) {}
+ RunningStateListener() : last_status(EmbeddedWorkerStatus::STOPPED) {}
~RunningStateListener() override {}
void OnRunningStateChanged(ServiceWorkerVersion* version) override {
last_status = version->running_status();
}
- ServiceWorkerVersion::RunningStatus last_status;
+ EmbeddedWorkerStatus last_status;
};
ServiceWorkerVersionTest()
@@ -249,7 +258,7 @@ class ServiceWorkerVersionTest : public testing::Test {
CreateReceiverOnCurrentThread(&status));
runner->Run();
EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Start request, as if an event is being dispatched.
int request_id = version_->StartRequest(
@@ -355,8 +364,8 @@ class MessageReceiverMojoTestService : public MessageReceiver {
MessageReceiverMojoTestService() : MessageReceiver() {}
~MessageReceiverMojoTestService() override {}
- void OnSetupMojo(ServiceRegistry* service_registry) override {
- service_registry->AddService(base::Bind(&TestMojoServiceImpl::Create));
+ void OnSetupMojo(shell::InterfaceRegistry* registry) override {
+ registry->AddInterface(base::Bind(&TestMojoServiceImpl::Create));
}
private:
@@ -385,9 +394,9 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status2));
- EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Call StartWorker() after it's started.
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
@@ -405,9 +414,9 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
version_->StopWorker(CreateReceiverOnCurrentThread(&status1));
version_->StopWorker(CreateReceiverOnCurrentThread(&status2));
- EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
// All StopWorker should just succeed.
EXPECT_EQ(SERVICE_WORKER_OK, status1);
@@ -421,9 +430,9 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status1));
- EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Call StopWorker()
status2 = SERVICE_WORKER_ERROR_FAILED;
@@ -433,9 +442,9 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status3));
- EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// All should just succeed.
EXPECT_EQ(SERVICE_WORKER_OK, status1);
@@ -444,14 +453,14 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
}
TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
// Dispatch an event without starting the worker.
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
// The worker should be now started.
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Stop the worker, and then dispatch an event immediately after that.
ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
@@ -460,7 +469,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
// The worker should be now started again.
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
@@ -469,7 +478,7 @@ TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
// Delete the registration.
@@ -494,7 +503,7 @@ TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
SimulateDispatchEvent(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
// The worker should be now started again.
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
@@ -502,10 +511,10 @@ TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
- EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
MessageReceiverFromWorker receiver(version_->embedded_worker());
@@ -650,7 +659,7 @@ TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
- ASSERT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+ ASSERT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
ASSERT_TRUE(version_->timeout_timer_.IsRunning());
ASSERT_FALSE(version_->start_time_.is_null());
@@ -672,7 +681,7 @@ TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
@@ -684,11 +693,11 @@ TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, listener.last_status);
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, listener.last_status);
version_ = nullptr;
- EXPECT_EQ(ServiceWorkerVersion::STOPPING, listener.last_status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, listener.last_status);
}
// Test that update isn't triggered for a non-stale worker.
@@ -812,7 +821,7 @@ TEST_F(ServiceWorkerVersionTest, RequestTimeout) {
// Callback has not completed yet.
EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Simulate timeout.
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
@@ -820,7 +829,7 @@ TEST_F(ServiceWorkerVersionTest, RequestTimeout) {
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
EXPECT_FALSE(version_->FinishRequest(request_id, true));
}
@@ -847,7 +856,7 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
EXPECT_FALSE(version_->FinishRequest(request_id, true));
// CONTINUE_ON_TIMEOUT timeouts don't stop the service worker.
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeoutKill) {
@@ -873,7 +882,7 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeoutKill) {
EXPECT_FALSE(version_->FinishRequest(request_id, true));
// KILL_ON_TIMEOUT timeouts should stop the service worker.
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
}
TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
@@ -907,7 +916,7 @@ TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, fetch_status);
// Background sync timeouts don't stop the service worker.
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Gracefully handle the sync event finishing after the timeout.
EXPECT_FALSE(version_->FinishRequest(sync_request_id, true));
@@ -922,7 +931,7 @@ TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
EXPECT_FALSE(version_->FinishRequest(fetch_request_id, true));
// Other timeouts do stop the service worker.
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
}
TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
@@ -933,7 +942,7 @@ TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
// Callback has not completed yet.
EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
- EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
// Simulate renderer crash: do what
// ServiceWorkerDispatcherHost::OnFilterRemoved does.
@@ -945,7 +954,7 @@ TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
// Callback completed.
EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
}
TEST_F(ServiceWorkerFailToStartTest, Timeout) {
@@ -958,7 +967,7 @@ TEST_F(ServiceWorkerFailToStartTest, Timeout) {
// Callback has not completed yet.
EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
- EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
// Simulate timeout.
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
@@ -969,7 +978,7 @@ TEST_F(ServiceWorkerFailToStartTest, Timeout) {
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
}
// Test that a service worker stalled in stopping will timeout and not get in a
@@ -981,12 +990,12 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Try to stop the worker.
status = SERVICE_WORKER_ERROR_FAILED;
version_->StopWorker(CreateReceiverOnCurrentThread(&status));
- EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
base::RunLoop().RunUntilIdle();
// Worker is now stalled in stopping. Verify a fast timeout is in place.
@@ -1003,7 +1012,7 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
version_->timeout_timer_.user_task().Run();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
// Try to start the worker again. It should work.
status = SERVICE_WORKER_ERROR_FAILED;
@@ -1011,7 +1020,7 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// The timeout interval should be reset to normal.
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
@@ -1029,12 +1038,12 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Try to stop the worker.
status = SERVICE_WORKER_ERROR_FAILED;
version_->StopWorker(CreateReceiverOnCurrentThread(&status));
- EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
// Worker is now stalled in stopping. Add a start worker requset.
ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
@@ -1051,7 +1060,7 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(SERVICE_WORKER_OK, start_status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
TEST_F(ServiceWorkerVersionTest, RegisterForeignFetchScopes) {
@@ -1062,7 +1071,7 @@ TEST_F(ServiceWorkerVersionTest, RegisterForeignFetchScopes) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
EXPECT_EQ(0, helper_->mock_render_process_host()->bad_msg_count());
GURL valid_scope_1("http://www.example.com/test/subscope");
@@ -1138,7 +1147,7 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
int request_id =
version_->StartRequest(ServiceWorkerMetrics::EventType::SYNC,
@@ -1158,7 +1167,7 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
// Callback completed.
EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
// Request already failed, calling finsh should return false.
EXPECT_FALSE(version_->FinishRequest(request_id, true));
@@ -1172,7 +1181,7 @@ TEST_F(ServiceWorkerVersionWithMojoTest, MojoService) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
int request_id = version_->StartRequest(
@@ -1197,7 +1206,7 @@ TEST_F(ServiceWorkerVersionTest, NonExistentMojoService) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
int request_id = version_->StartRequest(
@@ -1223,7 +1232,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchEvent) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Start request and dispatch test event.
scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
@@ -1232,10 +1241,10 @@ TEST_F(ServiceWorkerVersionTest, DispatchEvent) {
CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
int received_request_id = 0;
std::string received_data;
- version_->DispatchEvent<TestMsg_TestEventResult>(
- request_id, TestMsg_TestEvent(request_id),
- base::Bind(&ReceiveTestEventResult, &received_request_id, &received_data,
- runner->QuitClosure()));
+ version_->RegisterRequestCallback<TestMsg_TestEventResult>(
+ request_id, base::Bind(&ReceiveTestEventResult, &received_request_id,
+ &received_data, runner->QuitClosure()));
+ version_->DispatchEvent({request_id}, TestMsg_TestEvent(request_id));
// Verify event got dispatched to worker.
base::RunLoop().RunUntilIdle();
@@ -1327,7 +1336,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Start first request and dispatch test event.
scoped_refptr<MessageLoopRunner> runner1(new MessageLoopRunner);
@@ -1337,10 +1346,10 @@ TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
CreateReceiverOnCurrentThread(&status1, runner1->QuitClosure()));
int received_request_id1 = 0;
std::string received_data1;
- version_->DispatchEvent<TestMsg_TestEventResult>(
- request_id1, TestMsg_TestEvent(request_id1),
- base::Bind(&ReceiveTestEventResult, &received_request_id1,
- &received_data1, runner1->QuitClosure()));
+ version_->RegisterRequestCallback<TestMsg_TestEventResult>(
+ request_id1, base::Bind(&ReceiveTestEventResult, &received_request_id1,
+ &received_data1, runner1->QuitClosure()));
+ version_->DispatchEvent({request_id1}, TestMsg_TestEvent(request_id1));
// Start second request and dispatch test event.
scoped_refptr<MessageLoopRunner> runner2(new MessageLoopRunner);
@@ -1350,10 +1359,10 @@ TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
CreateReceiverOnCurrentThread(&status2, runner2->QuitClosure()));
int received_request_id2 = 0;
std::string received_data2;
- version_->DispatchEvent<TestMsg_TestEventResult>(
- request_id2, TestMsg_TestEvent(request_id2),
- base::Bind(&ReceiveTestEventResult, &received_request_id2,
- &received_data2, runner2->QuitClosure()));
+ version_->RegisterRequestCallback<TestMsg_TestEventResult>(
+ request_id2, base::Bind(&ReceiveTestEventResult, &received_request_id2,
+ &received_data2, runner2->QuitClosure()));
+ version_->DispatchEvent({request_id2}, TestMsg_TestEvent(request_id2));
// Make sure events got dispatched in same order.
base::RunLoop().RunUntilIdle();
@@ -1362,11 +1371,11 @@ TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
ASSERT_EQ(TestMsg_TestEvent::ID, msg->type());
TestMsg_TestEvent::Param params;
TestMsg_TestEvent::Read(msg, &params);
- EXPECT_EQ(request_id1, base::get<0>(params));
+ EXPECT_EQ(request_id1, std::get<0>(params));
msg = helper_->inner_ipc_sink()->GetMessageAt(1);
ASSERT_EQ(TestMsg_TestEvent::ID, msg->type());
TestMsg_TestEvent::Read(msg, &params);
- EXPECT_EQ(request_id2, base::get<0>(params));
+ EXPECT_EQ(request_id2, std::get<0>(params));
// Reply to second event.
std::string reply2("foobar");
@@ -1405,7 +1414,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Completed) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Start request and dispatch test event.
status = SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
@@ -1442,7 +1451,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Rejected) {
CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Start request and dispatch test event.
status = SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
@@ -1469,4 +1478,71 @@ TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Rejected) {
EXPECT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
}
+TEST_F(ServiceWorkerVersionTest, DispatchEvent_MultipleResponse) {
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+
+ // Activate and start worker.
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
+
+ // Start request and dispatch test event.
+ scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
+ int request_id1 = version_->StartRequest(
+ ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
+ CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
+ int request_id2 = version_->StartRequest(
+ ServiceWorkerMetrics::EventType::FETCH_WAITUNTIL,
+ CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
+ int received_request_id1 = 0;
+ int received_request_id2 = 0;
+ std::string received_data1;
+ std::string received_data2;
+ version_->RegisterRequestCallback<TestMsg_TestEventResult>(
+ request_id1, base::Bind(&ReceiveTestEventResult, &received_request_id1,
+ &received_data1, runner->QuitClosure()));
+ version_->RegisterRequestCallback<TestMsg_TestEventResult>(
+ request_id2, base::Bind(&ReceiveTestEventResult, &received_request_id2,
+ &received_data2, runner->QuitClosure()));
+ version_->DispatchEvent({request_id1, request_id2},
+ TestMsg_TestEvent_Multiple(request_id1, request_id2));
+
+ // Verify event got dispatched to worker.
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(1u, helper_->inner_ipc_sink()->message_count());
+ const IPC::Message* msg = helper_->inner_ipc_sink()->GetMessageAt(0);
+ EXPECT_EQ(TestMsg_TestEvent_Multiple::ID, msg->type());
+
+ // Simulate sending reply to event.
+ std::string reply1("foobar1");
+ std::string reply2("foobar2");
+ helper_->SimulateSendEventResult(
+ version_->embedded_worker()->embedded_worker_id(), request_id1, reply1);
+ runner->Run();
+
+ // Verify message callback got called with correct reply.
+ EXPECT_EQ(request_id1, received_request_id1);
+ EXPECT_EQ(reply1, received_data1);
+ EXPECT_NE(request_id2, received_request_id2);
+ EXPECT_NE(reply2, received_data2);
+
+ // Simulate sending reply to event.
+ helper_->SimulateSendEventResult(
+ version_->embedded_worker()->embedded_worker_id(), request_id2, reply2);
+ runner->Run();
+
+ // Verify message callback got called with correct reply.
+ EXPECT_EQ(request_id2, received_request_id2);
+ EXPECT_EQ(reply2, received_data2);
+
+ // Should not have timed out, so error callback should not have been
+ // called and FinishRequest should return true.
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_TRUE(version_->FinishRequest(request_id1, true));
+ EXPECT_TRUE(version_->FinishRequest(request_id2, true));
+}
+
} // namespace content
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 b63291fd378..509dd9bd73e 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
@@ -21,7 +21,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_test_utils.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -312,7 +312,8 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
provider_id, false, FETCH_REQUEST_MODE_NO_CORS,
FETCH_CREDENTIALS_MODE_OMIT, FetchRedirectMode::FOLLOW_MODE,
RESOURCE_TYPE_SERVICE_WORKER, REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
- REQUEST_CONTEXT_FRAME_TYPE_NONE, scoped_refptr<ResourceRequestBody>());
+ REQUEST_CONTEXT_FRAME_TYPE_NONE,
+ scoped_refptr<ResourceRequestBodyImpl>());
}
int NextProviderId() { return next_provider_id_++; }
diff --git a/chromium/content/browser/session_history_browsertest.cc b/chromium/content/browser/session_history_browsertest.cc
index aae42f62521..4f801271466 100644
--- a/chromium/content/browser/session_history_browsertest.cc
+++ b/chromium/content/browser/session_history_browsertest.cc
@@ -15,8 +15,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_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
@@ -51,7 +53,10 @@ class SessionHistoryTest : public ContentBrowserTest {
SessionHistoryTest() {}
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"));
@@ -464,26 +469,20 @@ IN_PROC_BROWSER_TEST_F(SessionHistoryTest, LocationChangeInSubframe) {
IN_PROC_BROWSER_TEST_F(SessionHistoryTest, HistoryLength) {
int length;
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(history.length)",
- &length));
+ shell(), "domAutomationController.send(history.length)", &length));
EXPECT_EQ(1, length);
NavigateToURL(shell(), GetURL("title1.html"));
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(history.length)",
- &length));
+ shell(), "domAutomationController.send(history.length)", &length));
EXPECT_EQ(2, length);
// Now test that history.length is updated when the navigation is committed.
NavigateToURL(shell(), GetURL("record_length.html"));
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(history.length)",
- &length));
+ shell(), "domAutomationController.send(history.length)", &length));
EXPECT_EQ(3, length);
GoBack();
@@ -493,10 +492,69 @@ IN_PROC_BROWSER_TEST_F(SessionHistoryTest, HistoryLength) {
NavigateToURL(shell(), GetURL("title2.html"));
ASSERT_TRUE(ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(history.length)",
- &length));
+ shell(), "domAutomationController.send(history.length)", &length));
EXPECT_EQ(2, length);
}
+// Test that verifies that a cross-process transfer doesn't lose session
+// history state - https://crbug.com/613004.
+//
+// Trigerring a cross-process transfer via embedded_test_server requires use of
+// a HTTP redirect response (to preserve port number). Therefore the test ends
+// up accidentally testing redirection logic as well - in particular, the test
+// uses 307 (rather than 302) redirect to preserve the body of HTTP POST across
+// redirects (as mandated by https://tools.ietf.org/html/rfc7231#section-6.4.7).
+IN_PROC_BROWSER_TEST_F(SessionHistoryTest, GoBackToCrossSitePostWithRedirect) {
+ GURL form_url(embedded_test_server()->GetURL(
+ "a.com", "/form_that_posts_cross_site.html"));
+ GURL redirect_target_url(embedded_test_server()->GetURL("x.com", "/echoall"));
+ GURL page_to_go_back_from(
+ embedded_test_server()->GetURL("c.com", "/title1.html"));
+
+ // Navigate to the page with form that posts via 307 redirection to
+ // |redirect_target_url| (cross-site from |form_url|).
+ EXPECT_TRUE(NavigateToURL(shell(), form_url));
+
+ // Submit the form.
+ TestNavigationObserver form_post_observer(shell()->web_contents(), 1);
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "document.getElementById('text-form').submit();"));
+ form_post_observer.Wait();
+
+ // Verify that we arrived at the expected, redirected location.
+ EXPECT_EQ(redirect_target_url,
+ shell()->web_contents()->GetLastCommittedURL());
+
+ // Verify that POST body got preserved by 307 redirect. This expectation
+ // comes from: https://tools.ietf.org/html/rfc7231#section-6.4.7
+ std::string body;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell(),
+ "window.domAutomationController.send("
+ "document.getElementsByTagName('pre')[0].innerText);",
+ &body));
+ EXPECT_EQ("text=value\n", body);
+
+ // Navigate to a page from yet another site.
+ EXPECT_TRUE(NavigateToURL(shell(), page_to_go_back_from));
+
+ // Go back - this should resubmit form's post data.
+ TestNavigationObserver back_nav_observer(shell()->web_contents(), 1);
+ shell()->web_contents()->GetController().GoBack();
+ back_nav_observer.Wait();
+
+ // Again verify that we arrived at the expected, redirected location.
+ EXPECT_EQ(redirect_target_url,
+ shell()->web_contents()->GetLastCommittedURL());
+
+ // Again verify that POST body got preserved by 307 redirect.
+ std::string body_after_back_navigation;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell(),
+ "window.domAutomationController.send("
+ "document.getElementsByTagName('pre')[0].innerText);",
+ &body_after_back_navigation));
+ EXPECT_EQ("text=value\n", body_after_back_navigation);
+}
+
} // namespace content
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.cc b/chromium/content/browser/shared_worker/shared_worker_host.cc
index bf32f774623..708e7edcfd4 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host.cc
@@ -224,8 +224,8 @@ void SharedWorkerHost::RelayMessage(
WorkerMsg_Connect::Param param;
if (!WorkerMsg_Connect::Read(&message, &param))
return;
- int sent_message_port_id = base::get<0>(param);
- int new_routing_id = base::get<1>(param);
+ int sent_message_port_id = std::get<0>(param);
+ int new_routing_id = std::get<1>(param);
DCHECK(container_render_filter_);
new_routing_id = container_render_filter_->GetNextRoutingID();
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
index 1bc7946ce57..57cca3d7296 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
@@ -9,6 +9,7 @@
#include <map>
#include <memory>
#include <set>
+#include <tuple>
#include <vector>
#include "base/atomic_sequence_num.h"
@@ -332,13 +333,13 @@ void CheckWorkerProcessMsgCreateWorker(
int* route_id) {
std::unique_ptr<IPC::Message> msg(renderer_host->PopMessage());
EXPECT_EQ(WorkerProcessMsg_CreateWorker::ID, msg->type());
- base::Tuple<WorkerProcessMsg_CreateWorker_Params> param;
+ std::tuple<WorkerProcessMsg_CreateWorker_Params> param;
EXPECT_TRUE(WorkerProcessMsg_CreateWorker::Read(msg.get(), &param));
- EXPECT_EQ(GURL(expected_url), base::get<0>(param).url);
- EXPECT_EQ(base::ASCIIToUTF16(expected_name), base::get<0>(param).name);
+ EXPECT_EQ(GURL(expected_url), std::get<0>(param).url);
+ EXPECT_EQ(base::ASCIIToUTF16(expected_name), std::get<0>(param).name);
EXPECT_EQ(expected_security_policy_type,
- base::get<0>(param).security_policy_type);
- *route_id = base::get<0>(param).route_id;
+ std::get<0>(param).security_policy_type);
+ *route_id = std::get<0>(param).route_id;
}
void CheckViewMsgWorkerCreated(MockRendererProcessHost* renderer_host,
@@ -364,8 +365,8 @@ void CheckWorkerMsgConnect(MockRendererProcessHost* renderer_host,
EXPECT_EQ(expected_msg_route_id, msg->routing_id());
WorkerMsg_Connect::Param params;
EXPECT_TRUE(WorkerMsg_Connect::Read(msg.get(), &params));
- int port_id = base::get<0>(params);
- *routing_id = base::get<1>(params);
+ int port_id = std::get<0>(params);
+ *routing_id = std::get<1>(params);
EXPECT_EQ(expected_sent_message_port_id, port_id);
}
@@ -377,7 +378,7 @@ void CheckMessagePortMsgMessage(MockRendererProcessHost* renderer_host,
EXPECT_EQ(expected_msg_route_id, msg->routing_id());
MessagePortMsg_Message::Param params;
EXPECT_TRUE(MessagePortMsg_Message::Read(msg.get(), &params));
- base::string16 data = base::get<0>(params);
+ base::string16 data = std::get<0>(params);
EXPECT_EQ(base::ASCIIToUTF16(expected_data), data);
}
diff --git a/chromium/content/browser/shared_worker/worker_browsertest.cc b/chromium/content/browser/shared_worker/worker_browsertest.cc
index 278d0eb877a..6d9e3708c15 100644
--- a/chromium/content/browser/shared_worker/worker_browsertest.cc
+++ b/chromium/content/browser/shared_worker/worker_browsertest.cc
@@ -22,10 +22,10 @@
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
#include "net/base/escape.h"
-#include "net/base/test_data_directory.h"
#include "net/ssl/ssl_server_config.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/test_data_directory.h"
#include "url/gurl.h"
namespace content {
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index da719353a17..be2a3eea4dc 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_vector.h"
+#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/browsing_instance.h"
@@ -136,7 +137,7 @@ class SiteInstanceTest : public testing::Test {
// We don't just do this in TearDown() because we create TestBrowserContext
// objects in each test, which will be destructed before
// TearDown() is called.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
message_loop_.RunUntilIdle();
}
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index 3801b0d00c1..12caec4560d 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -13,6 +13,7 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/pattern.h"
#include "base/strings/stringprintf.h"
@@ -20,6 +21,7 @@
#include "base/test/test_timeouts.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
+#include "components/network_session_configurator/switches.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
@@ -56,6 +58,7 @@
#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/WebInsecureRequestPolicy.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
#include "ui/display/display_switches.h"
@@ -88,7 +91,7 @@ void PostMessageAndWaitForReply(FrameTreeNode* sender_ftn,
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- sender_ftn->current_frame_host(),
+ sender_ftn,
"window.domAutomationController.send(" + post_message_script + ");",
&success));
EXPECT_TRUE(success);
@@ -106,8 +109,7 @@ void PostMessageAndWaitForReply(FrameTreeNode* sender_ftn,
int GetReceivedMessages(FrameTreeNode* ftn) {
int received_messages = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- ftn->current_frame_host(),
- "window.domAutomationController.send(window.receivedMessages);",
+ ftn, "window.domAutomationController.send(window.receivedMessages);",
&received_messages));
return received_messages;
}
@@ -142,8 +144,7 @@ void SimulateMouseClick(RenderWidgetHost* rwh, int x, int y) {
std::string GetDocumentOrigin(FrameTreeNode* ftn) {
std::string origin;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- ftn->current_frame_host(),
- "domAutomationController.send(document.origin)", &origin));
+ ftn, "domAutomationController.send(document.origin)", &origin));
return origin;
}
@@ -177,6 +178,33 @@ class RenderWidgetHostMouseEventMonitor {
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostMouseEventMonitor);
};
+class TestInputEventObserver : public RenderWidgetHost::InputEventObserver {
+ public:
+ explicit TestInputEventObserver(RenderWidgetHost* host)
+ : host_(host),
+ event_received_(false),
+ last_event_type_(blink::WebInputEvent::Undefined) {
+ host_->AddInputEventObserver(this);
+ }
+
+ ~TestInputEventObserver() override { host_->RemoveInputEventObserver(this); }
+
+ bool EventWasReceived() const { return event_received_; }
+ void ResetEventReceived() { event_received_ = false; }
+ blink::WebInputEvent::Type EventType() const { return last_event_type_; }
+
+ void OnInputEvent(const blink::WebInputEvent& event) override {
+ event_received_ = true;
+ last_event_type_ = event.type;
+ };
+
+ RenderWidgetHost* host_;
+ bool event_received_;
+ blink::WebInputEvent::Type last_event_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestInputEventObserver);
+};
+
// Helper function that performs a surface hittest.
void SurfaceHitTestTestHelper(
Shell* shell,
@@ -462,58 +490,6 @@ void FocusFrame(FrameTreeNode* frame) {
focus_observer.Wait();
}
-// A WebContentsDelegate that catches messages sent to the console.
-class ConsoleObserverDelegate : public WebContentsDelegate {
- public:
- ConsoleObserverDelegate(WebContents* web_contents, const std::string& filter)
- : web_contents_(web_contents),
- filter_(filter),
- message_(""),
- message_loop_runner_(new MessageLoopRunner) {}
-
- ~ConsoleObserverDelegate() override {}
-
- bool AddMessageToConsole(WebContents* source,
- int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) override;
-
- std::string message() { return message_; }
-
- void Wait();
-
- private:
- WebContents* web_contents_;
- std::string filter_;
- std::string message_;
-
- // The MessageLoopRunner used to spin the message loop.
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(ConsoleObserverDelegate);
-};
-
-void ConsoleObserverDelegate::Wait() {
- message_loop_runner_->Run();
-}
-
-bool ConsoleObserverDelegate::AddMessageToConsole(
- WebContents* source,
- int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) {
- DCHECK(source == web_contents_);
-
- std::string ascii_message = base::UTF16ToASCII(message);
- if (base::MatchPattern(ascii_message, filter_)) {
- message_ = ascii_message;
- message_loop_runner_->Quit();
- }
- return false;
-}
-
// A BrowserMessageFilter that drops SwapOut ACK messages.
class SwapoutACKMessageFilter : public BrowserMessageFilter {
public:
@@ -785,6 +761,44 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
DepictFrameTree(root));
}
+// Ensure that title updates affect the correct NavigationEntry after a new
+// subframe navigation with an out-of-process iframe. https://crbug.com/616609.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, TitleAfterCrossSiteIframe) {
+ // Start at an initial page.
+ GURL initial_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), initial_url));
+
+ // Navigate to a same-site page with a same-site iframe.
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Make the main frame update its title after the subframe loads.
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "document.querySelector('iframe').onload = "
+ " function() { document.title = 'loaded'; };"));
+ EXPECT_TRUE(
+ ExecuteScript(shell()->web_contents(), "document.title = 'not loaded';"));
+ base::string16 expected_title(base::UTF8ToUTF16("loaded"));
+ TitleWatcher title_watcher(shell()->web_contents(), expected_title);
+
+ // Navigate the iframe cross-site.
+ TestNavigationObserver load_observer(shell()->web_contents());
+ GURL frame_url = embedded_test_server()->GetURL("b.com", "/title2.html");
+ EXPECT_TRUE(
+ ExecuteScript(root->child_at(0)->current_frame_host(),
+ "window.location.href = '" + frame_url.spec() + "';"));
+ load_observer.Wait();
+
+ // Wait for the title to update and ensure it affects the right NavEntry.
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+ NavigationEntry* entry =
+ shell()->web_contents()->GetController().GetLastCommittedEntry();
+ EXPECT_EQ(expected_title, entry->GetTitle());
+}
+
// Class to sniff incoming IPCs for FrameHostMsg_FrameRectChanged messages.
class FrameRectChangedMessageFilter : public content::BrowserMessageFilter {
public:
@@ -903,7 +917,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
scroll_event.y = 110;
scroll_event.deltaX = 0.0f;
scroll_event.deltaY = -30.0f;
- rwhv_root->ProcessMouseWheelEvent(scroll_event);
+ rwhv_root->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
filter->Wait();
@@ -989,7 +1003,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
scroll_event.y = 1;
scroll_event.deltaX = 0.0f;
scroll_event.deltaY = -5.0f;
- rwhv_parent->ProcessMouseWheelEvent(scroll_event);
+ rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
// Ensure that the view position is propagated to the child properly.
filter->Wait();
@@ -1001,7 +1015,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The upscroll exceeds the amount that the frame was initially scrolled
// down to account for rounding.
scroll_event.deltaY = 6.0f;
- rwhv_nested->ProcessMouseWheelEvent(scroll_event);
+ rwhv_nested->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
filter->Wait();
// This loop isn't great, but it accounts for the possibility of multiple
@@ -1024,7 +1038,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Scroll the parent down again in order to test scroll bubbling from
// gestures.
scroll_event.deltaY = -5.0f;
- rwhv_parent->ProcessMouseWheelEvent(scroll_event);
+ rwhv_parent->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
// Ensure ensuing offset change is received, and then reset the filter.
filter->Wait();
@@ -1062,6 +1076,59 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
}
+// Test that an ET_SCROLL event sent to an out-of-process iframe correctly
+// results in a scroll. This is only handled by RenderWidgetHostViewAura
+// and is needed for trackpad scrolling on Chromebooks.
+#if !defined(USE_AURA)
+#define MAYBE_ScrollEventToOOPIF DISABLED_ScrollEventToOOPIF
+#else
+#define MAYBE_ScrollEventToOOPIF ScrollEventToOOPIF
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_ScrollEventToOOPIF) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_frame.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* child_node = root->child_at(0);
+ GURL site_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
+ EXPECT_EQ(site_url, child_node->current_url());
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ child_node->current_frame_host()->GetSiteInstance());
+
+ RenderWidgetHostViewAura* rwhv_parent =
+ static_cast<RenderWidgetHostViewAura*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child));
+ notifier.WaitForSurfaceReady();
+
+ // Create listener for input events.
+ TestInputEventObserver child_frame_monitor(
+ child_node->current_frame_host()->GetRenderWidgetHost());
+
+ // Send a ui::ScrollEvent that will hit test to the child frame.
+ ui::ScrollEvent scroll_event(ui::ET_SCROLL, gfx::Point(75, 75),
+ ui::EventTimeForNow(), ui::EF_NONE,
+ 0, 10, // Offsets
+ 0, 10, // Offset ordinals
+ 2);
+ rwhv_parent->OnScrollEvent(&scroll_event);
+
+ // Verify that this a mouse wheel event was sent to the child frame renderer.
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived());
+ EXPECT_EQ(child_frame_monitor.EventType(), blink::WebInputEvent::MouseWheel);
+}
+
// Test that mouse events are being routed to the correct RenderWidgetHostView
// based on coordinates.
#if defined(OS_ANDROID) || defined(THREAD_SANITIZER)
@@ -1310,7 +1377,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CleanupCrossSiteIframe) {
// Use Javascript in the parent to remove one of the frames and ensure that
// the subframe goes away.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ EXPECT_TRUE(ExecuteScript(shell(),
"document.body.removeChild("
"document.querySelectorAll('iframe')[0])"));
ASSERT_EQ(1U, root->child_count());
@@ -1572,7 +1639,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
"window.domAutomationController.send("
"window.location.href = 'about:blank');");
TestFrameNavigationObserver frame_observer(child);
- EXPECT_TRUE(ExecuteScript(child->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(child, script));
frame_observer.Wait();
EXPECT_EQ(about_blank_url, child->current_url());
@@ -1993,7 +2060,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Add a new child frame to the third subframe.
RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 1);
EXPECT_TRUE(ExecuteScript(
- root->child_at(2)->current_frame_host(),
+ root->child_at(2),
"document.body.appendChild(document.createElement('iframe'));"));
frame_observer.Wait();
@@ -2049,8 +2116,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Open a popup and navigate it cross-process to b.com.
ShellAddedObserver new_shell_observer;
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(),
- "popup = window.open('about:blank');"));
+ EXPECT_TRUE(ExecuteScript(root, "popup = window.open('about:blank');"));
Shell* popup = new_shell_observer.GetShell();
GURL popup_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
EXPECT_TRUE(NavigateToURL(popup, popup_url));
@@ -2096,8 +2162,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Add a new child frame on the popup.
RenderFrameHostCreatedObserver frame_observer(popup->web_contents(), 1);
EXPECT_TRUE(ExecuteScript(
- popup->web_contents(),
- "document.body.appendChild(document.createElement('iframe'));"));
+ popup, "document.body.appendChild(document.createElement('iframe'));"));
frame_observer.Wait();
// Both the child frame's and its parent's proxies should still not be live.
@@ -2279,9 +2344,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CreateProxiesForNewFrames) {
// Add a new child frame to the top-level frame.
RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 1);
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.domAutomationController.send("
- " addFrame('data:text/html,foo'));"));
+ EXPECT_TRUE(ExecuteScript(shell(), "addFrame('data:text/html,foo');"));
frame_observer.Wait();
// The new frame should have a proxy in Site B, for use by the old frame.
@@ -2732,7 +2795,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
std::string margin_width;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- child->current_frame_host(),
+ child,
"window.domAutomationController.send("
"document.body.getAttribute('marginwidth'));",
&margin_width));
@@ -2740,7 +2803,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
std::string margin_height;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- child->current_frame_host(),
+ child,
"window.domAutomationController.send("
"document.body.getAttribute('marginheight'));",
&margin_height));
@@ -2765,21 +2828,21 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
for (size_t i = 0; i < arraysize(urls); ++i) {
// Change marginwidth and marginheight before navigating.
EXPECT_TRUE(ExecuteScript(
- root->current_frame_host(),
- base::StringPrintf(
- "document.getElementById('child-1').setAttribute("
- " 'marginwidth', '%d');", current_margin_width)));
+ root,
+ base::StringPrintf("document.getElementById('child-1').setAttribute("
+ " 'marginwidth', '%d');",
+ current_margin_width)));
EXPECT_TRUE(ExecuteScript(
- root->current_frame_host(),
- base::StringPrintf(
- "document.getElementById('child-1').setAttribute("
- " 'marginheight', '%d');", current_margin_height)));
+ root,
+ base::StringPrintf("document.getElementById('child-1').setAttribute("
+ " 'marginheight', '%d');",
+ current_margin_height)));
NavigateFrameToURL(child, urls[i]);
std::string actual_margin_width;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- child->current_frame_host(),
+ child,
"window.domAutomationController.send("
"document.body.getAttribute('marginwidth'));",
&actual_margin_width));
@@ -2787,7 +2850,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
std::string actual_margin_height;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- child->current_frame_host(),
+ child,
"window.domAutomationController.send("
"document.body.getAttribute('marginheight'));",
&actual_margin_height));
@@ -2832,13 +2895,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginReplication) {
// b.com's process.
int ancestor_origins_length = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- tiptop_child->current_frame_host(),
+ tiptop_child,
"window.domAutomationController.send(location.ancestorOrigins.length);",
&ancestor_origins_length));
EXPECT_EQ(1, ancestor_origins_length);
std::string result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- tiptop_child->current_frame_host(),
+ tiptop_child,
"window.domAutomationController.send(location.ancestorOrigins[0]);",
&result));
EXPECT_EQ(a_origin, result + "/");
@@ -2849,17 +2912,17 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginReplication) {
// should be replicated as part of FrameMsg_NewFrameProxy sent for b.com's
// frame in c.com's process.
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- middle_child->current_frame_host(),
+ middle_child,
"window.domAutomationController.send(location.ancestorOrigins.length);",
&ancestor_origins_length));
EXPECT_EQ(2, ancestor_origins_length);
EXPECT_TRUE(ExecuteScriptAndExtractString(
- middle_child->current_frame_host(),
+ middle_child,
"window.domAutomationController.send(location.ancestorOrigins[0]);",
&result));
EXPECT_EQ(b_origin, result + "/");
EXPECT_TRUE(ExecuteScriptAndExtractString(
- middle_child->current_frame_host(),
+ middle_child,
"window.domAutomationController.send(location.ancestorOrigins[1]);",
&result));
EXPECT_EQ(a_origin, result + "/");
@@ -2867,22 +2930,22 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginReplication) {
// Check that the nested a.com frame's location.ancestorOrigins contains the
// correct origin for its three ancestors.
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- lowest_child->current_frame_host(),
+ lowest_child,
"window.domAutomationController.send(location.ancestorOrigins.length);",
&ancestor_origins_length));
EXPECT_EQ(3, ancestor_origins_length);
EXPECT_TRUE(ExecuteScriptAndExtractString(
- lowest_child->current_frame_host(),
+ lowest_child,
"window.domAutomationController.send(location.ancestorOrigins[0]);",
&result));
EXPECT_EQ(c_origin, result + "/");
EXPECT_TRUE(ExecuteScriptAndExtractString(
- lowest_child->current_frame_host(),
+ lowest_child,
"window.domAutomationController.send(location.ancestorOrigins[1]);",
&result));
EXPECT_EQ(b_origin, result + "/");
EXPECT_TRUE(ExecuteScriptAndExtractString(
- lowest_child->current_frame_host(),
+ lowest_child,
"window.domAutomationController.send(location.ancestorOrigins[2]);",
&result));
EXPECT_EQ(a_origin, result + "/");
@@ -2919,7 +2982,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsReplication) {
// Opening a popup in the sandboxed foo.com iframe should fail.
bool success = false;
EXPECT_TRUE(
- ExecuteScriptAndExtractBool(root->child_at(1)->current_frame_host(),
+ ExecuteScriptAndExtractBool(root->child_at(1),
"window.domAutomationController.send("
"!window.open('data:text/html,dataurl'));",
&success));
@@ -2930,22 +2993,22 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsReplication) {
// Here, bar.com frame's sandboxed parent frame is a remote frame in
// bar.com's process.
success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1)->child_at(0)->current_frame_host(),
- "window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
- &success));
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractBool(root->child_at(1)->child_at(0),
+ "window.domAutomationController.send("
+ "!window.open('data:text/html,dataurl'));",
+ &success));
EXPECT_TRUE(success);
EXPECT_EQ(1u, Shell::windows().size());
// Same, but now try the case where bar.com frame's sandboxed parent is a
// local frame in bar.com's process.
success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(2)->child_at(0)->current_frame_host(),
- "window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
- &success));
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractBool(root->child_at(2)->child_at(0),
+ "window.domAutomationController.send("
+ "!window.open('data:text/html,dataurl'));",
+ &success));
EXPECT_TRUE(success);
EXPECT_EQ(1u, Shell::windows().size());
@@ -2953,13 +3016,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsReplication) {
// origin for the parent, which should be unaffected by sandboxing.
int ancestor_origins_length = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(1)->current_frame_host(),
+ root->child_at(1),
"window.domAutomationController.send(location.ancestorOrigins.length);",
&ancestor_origins_length));
EXPECT_EQ(1, ancestor_origins_length);
std::string result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(1)->current_frame_host(),
+ root->child_at(1),
"window.domAutomationController.send(location.ancestorOrigins[0]);",
&result));
EXPECT_EQ(result + "/", main_url.GetOrigin().spec());
@@ -2969,17 +3032,17 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsReplication) {
// the top frame should match |main_url|.
FrameTreeNode* bottom_child = root->child_at(1)->child_at(0);
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- bottom_child->current_frame_host(),
+ bottom_child,
"window.domAutomationController.send(location.ancestorOrigins.length);",
&ancestor_origins_length));
EXPECT_EQ(2, ancestor_origins_length);
EXPECT_TRUE(ExecuteScriptAndExtractString(
- bottom_child->current_frame_host(),
+ bottom_child,
"window.domAutomationController.send(location.ancestorOrigins[0]);",
&result));
EXPECT_EQ("null", result);
EXPECT_TRUE(ExecuteScriptAndExtractString(
- bottom_child->current_frame_host(),
+ bottom_child,
"window.domAutomationController.send(location.ancestorOrigins[1]);",
&result));
EXPECT_EQ(main_url.GetOrigin().spec(), result + "/");
@@ -3018,10 +3081,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
root->child_at(1)->effective_sandbox_flags());
// Dynamically update sandbox flags for the first frame.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.domAutomationController.send("
- "document.querySelector('iframe').sandbox="
- "'allow-scripts');"));
+ EXPECT_TRUE(ExecuteScript(
+ shell(),
+ "document.querySelector('iframe').sandbox='allow-scripts';"));
// Check that updated sandbox flags are propagated to browser process.
// The new flags should be reflected in pending_sandbox_flags(), while
@@ -3063,11 +3125,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
// Opening a popup in the now-sandboxed frame should fail.
bool success = false;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
- &success));
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ root->child_at(0),
+ "window.domAutomationController.send("
+ " !window.open('data:text/html,dataurl'));",
+ &success));
EXPECT_TRUE(success);
EXPECT_EQ(1u, Shell::windows().size());
@@ -3094,9 +3156,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
// Opening a popup in the child of a sandboxed frame should fail.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0)->child_at(0)->current_frame_host(),
+ root->child_at(0)->child_at(0),
"window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
+ " !window.open('data:text/html,dataurl'));",
&success));
EXPECT_TRUE(success);
EXPECT_EQ(1u, Shell::windows().size());
@@ -3126,10 +3188,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
root->child_at(1)->current_url());
// Update the second frame's sandbox flags.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.domAutomationController.send("
- "document.querySelectorAll('iframe')[1].sandbox="
- "'allow-scripts');"));
+ EXPECT_TRUE(ExecuteScript(
+ shell(),
+ "document.querySelectorAll('iframe')[1].sandbox='allow-scripts'"));
// Check that the current sandbox flags are updated but the effective
// sandbox flags are not.
@@ -3154,11 +3215,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Opening a popup in the sandboxed second frame should fail.
bool success = false;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(root->child_at(1)->current_frame_host(),
- "window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
- &success));
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ root->child_at(1),
+ "window.domAutomationController.send("
+ " !window.open('data:text/html,dataurl'));",
+ &success));
EXPECT_TRUE(success);
EXPECT_EQ(1u, Shell::windows().size());
@@ -3166,9 +3227,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// now-sandboxed parent frame.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1)->child_at(0)->current_frame_host(),
+ root->child_at(1)->child_at(0),
"window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
+ " !window.open('data:text/html,dataurl'));",
&success));
EXPECT_TRUE(success);
EXPECT_EQ(1u, Shell::windows().size());
@@ -3198,10 +3259,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
root->child_at(0)->effective_sandbox_flags());
// Dynamically update the frame's sandbox flags.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.domAutomationController.send("
- "document.querySelector('iframe').sandbox="
- "'allow-scripts');"));
+ EXPECT_TRUE(ExecuteScript(
+ shell(), "document.querySelector('iframe').sandbox='allow-scripts';"));
// Check that updated sandbox flags are propagated to browser process.
// The new flags should be set in pending_sandbox_flags(), while
@@ -3219,8 +3278,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Perform a renderer-initiated same-site navigation in the first frame. The
// new sandbox flags should take effect.
TestFrameNavigationObserver frame_observer(root->child_at(0));
- ASSERT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
- "window.location.href='/title2.html'"));
+ ASSERT_TRUE(
+ ExecuteScript(root->child_at(0), "window.location.href='/title2.html'"));
frame_observer.Wait();
EXPECT_EQ(embedded_test_server()->GetURL("baz.com", "/title2.html"),
root->child_at(0)->current_url());
@@ -3232,11 +3291,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Opening a popup in the now-sandboxed frame should fail.
bool success = false;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
- &success));
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ root->child_at(0),
+ "window.domAutomationController.send("
+ " !window.open('data:text/html,dataurl'));",
+ &success));
EXPECT_TRUE(success);
EXPECT_EQ(1u, Shell::windows().size());
}
@@ -3278,11 +3337,9 @@ IN_PROC_BROWSER_TEST_F(
// the new sandboxed local frame, its child (while it's still local), and a
// pending RFH when starting the cross-site navigation to baz.com.
RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 3);
- EXPECT_TRUE(
- ExecuteScript(root->current_frame_host(),
- "window.domAutomationController.send("
- " addFrame('/frame_tree/page_with_one_frame.html',"
- " 'allow-scripts allow-same-origin'))"));
+ EXPECT_TRUE(ExecuteScript(root,
+ "addFrame('/frame_tree/page_with_one_frame.html',"
+ " 'allow-scripts allow-same-origin'))"));
frame_observer.Wait();
// Wait for the cross-site navigation to baz.com in the grandchild to finish.
@@ -3303,13 +3360,13 @@ IN_PROC_BROWSER_TEST_F(
// correct origin for its parent.
int ancestor_origins_length = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- bottom_child->current_frame_host(),
+ bottom_child,
"window.domAutomationController.send(location.ancestorOrigins.length);",
&ancestor_origins_length));
EXPECT_EQ(2, ancestor_origins_length);
std::string parent_origin;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- bottom_child->current_frame_host(),
+ bottom_child,
"window.domAutomationController.send(location.ancestorOrigins[0]);",
&parent_origin));
EXPECT_EQ(main_url.GetOrigin().spec(), parent_origin + "/");
@@ -3327,11 +3384,11 @@ IN_PROC_BROWSER_TEST_F(
// should not be able to create popups.
EXPECT_EQ(expected_flags, bottom_child->effective_sandbox_flags());
bool success = false;
- EXPECT_TRUE(
- ExecuteScriptAndExtractBool(bottom_child->current_frame_host(),
- "window.domAutomationController.send("
- "!window.open('data:text/html,dataurl'));",
- &success));
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ bottom_child,
+ "window.domAutomationController.send("
+ " !window.open('data:text/html,dataurl'));",
+ &success));
EXPECT_TRUE(success);
EXPECT_EQ(1u, Shell::windows().size());
}
@@ -3361,8 +3418,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, WindowNameReplication) {
// specified by its parent in the iframe tag.
std::string result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send(window.name);", &result));
+ root->child_at(0), "window.domAutomationController.send(window.name);",
+ &result));
EXPECT_EQ("3-1-name", result);
}
@@ -3388,9 +3445,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicWindowName) {
EXPECT_EQ(root->child_at(0)->frame_name(), "3-1-name");
// Update the child frame's window.name.
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send("
- "window.name = 'updated-name');"));
+ EXPECT_TRUE(
+ ExecuteScript(root->child_at(0), "window.name = 'updated-name';"));
// The change should propagate to the browser process.
EXPECT_EQ(root->child_at(0)->frame_name(), "updated-name");
@@ -3399,9 +3455,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicWindowName) {
// Check that it can reference the child frame by its new name.
bool success = false;
EXPECT_TRUE(
- ExecuteScriptAndExtractBool(shell()->web_contents(),
+ ExecuteScriptAndExtractBool(shell(),
"window.domAutomationController.send("
- "frames['updated-name'] == frames[0]);",
+ " frames['updated-name'] == frames[0]);",
&success));
EXPECT_TRUE(success);
@@ -3413,11 +3469,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicWindowName) {
// and a more complicated frame hierarchy (https://crbug.com/463742)
TestFrameNavigationObserver frame_observer(root->child_at(0));
GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
- std::string script = base::StringPrintf(
- "window.domAutomationController.send("
- "frames['updated-name'].location.href = '%s');",
- foo_url.spec().c_str());
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+ EXPECT_TRUE(ExecuteScript(
+ shell(),
+ base::StringPrintf("frames['updated-name'].location.href = '%s';",
+ foo_url.spec().c_str())));
frame_observer.Wait();
EXPECT_EQ(foo_url, root->child_at(0)->current_url());
}
@@ -3461,9 +3516,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginUpdatesReachProxies) {
// frames[1] can't be used due to a bug where RemoteFrames are created out of
// order (https://crbug.com/478792). Instead, target second frame by name.
EXPECT_TRUE(ExecuteScript(
- root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send("
- " parent.frames['frame2'].location.href = 'data:text/html,foo');"));
+ root->child_at(0),
+ "parent.frames['frame2'].location.href = 'data:text/html,foo'"));
console_delegate->Wait();
std::string frame_origin = root->child_at(1)->current_origin().Serialize();
@@ -3683,9 +3737,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Now, navigate the opener cross-process using the popup while it still has
// an interstitial. This should not crash.
TestNavigationObserver navigation_observer(opener_contents);
- EXPECT_TRUE(
- ExecuteScript(popup->web_contents(),
- "window.domAutomationController.send(navigateOpener());"));
+ EXPECT_TRUE(ExecuteScript(popup, "navigateOpener();"));
navigation_observer.Wait();
}
@@ -3715,8 +3767,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Open a popup from the first subframe (so that popup's window.opener points
// to the subframe) and navigate it to bar.com.
ShellAddedObserver new_shell_observer;
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
- "openPopup('about:blank');"));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), "openPopup('about:blank');"));
Shell* popup = new_shell_observer.GetShell();
GURL popup_url(
embedded_test_server()->GetURL("bar.com", "/post_message.html"));
@@ -3726,8 +3777,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// check that the whole opener chain is processed when creating proxies and
// not just an immediate opener.
ShellAddedObserver new_shell_observer2;
- EXPECT_TRUE(
- ExecuteScript(popup->web_contents(), "openPopup('about:blank');"));
+ EXPECT_TRUE(ExecuteScript(popup, "openPopup('about:blank');"));
Shell* popup2 = new_shell_observer2.GetShell();
GURL popup2_url(
embedded_test_server()->GetURL("baz.com", "/post_message.html"));
@@ -3770,7 +3820,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// reaches subframe1. This verifies that the subframe opener information
// propagated to the popup's RenderFrame. Wait for subframe1 to send a reply
// message to the popup.
- EXPECT_TRUE(ExecuteScript(popup->web_contents(), "window.name = 'popup';"));
+ EXPECT_TRUE(ExecuteScript(popup, "window.name = 'popup';"));
PostMessageAndWaitForReply(popup_root, "postToOpener('subframe-msg', '*')",
"\"done-popup\"");
@@ -3781,7 +3831,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
static_cast<WebContentsImpl*>(popup2->web_contents())
->GetFrameTree()
->root();
- EXPECT_TRUE(ExecuteScript(popup2->web_contents(), "window.name = 'popup2';"));
+ EXPECT_TRUE(ExecuteScript(popup2, "window.name = 'popup2';"));
PostMessageAndWaitForReply(popup2_root,
"postToOpenerOfOpener('subframe-msg', '*')",
"\"done-popup2\"");
@@ -3837,21 +3887,21 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, IndexedFrameAccess) {
// Check that each subframe sees itself at correct index in parent.frames.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- child0->current_frame_host(),
+ child0,
"window.domAutomationController.send(window === parent.frames[0]);",
&success));
EXPECT_TRUE(success);
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- child1->current_frame_host(),
+ child1,
"window.domAutomationController.send(window === parent.frames[1]);",
&success));
EXPECT_TRUE(success);
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- child2->current_frame_host(),
+ child2,
"window.domAutomationController.send(window === parent.frames[2]);",
&success));
EXPECT_TRUE(success);
@@ -3947,8 +3997,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenPopupWithRemoteParent) {
NavigateFrameToURL(root->child_at(0), frame_url);
// Open a popup from the first child.
- Shell* new_shell = OpenPopup(root->child_at(0)->current_frame_host(),
- GURL(url::kAboutBlankURL), "");
+ Shell* new_shell =
+ OpenPopup(root->child_at(0), GURL(url::kAboutBlankURL), "");
EXPECT_TRUE(new_shell);
// Check that the popup's opener is correct on both the browser and renderer
@@ -3961,7 +4011,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenPopupWithRemoteParent) {
std::string opener_url;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- popup_root->current_frame_host(),
+ popup_root,
"window.domAutomationController.send(window.opener.location.href);",
&opener_url));
EXPECT_EQ(frame_url.spec(), opener_url);
@@ -3969,8 +4019,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenPopupWithRemoteParent) {
// Now try the same with a cross-site popup and make sure it ends up in a new
// process and with a correct opener.
GURL popup_url(embedded_test_server()->GetURL("c.com", "/title2.html"));
- Shell* cross_site_popup =
- OpenPopup(root->child_at(0)->current_frame_host(), popup_url, "");
+ Shell* cross_site_popup = OpenPopup(root->child_at(0), popup_url, "");
EXPECT_TRUE(cross_site_popup);
FrameTreeNode* cross_site_popup_root =
@@ -3990,7 +4039,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenPopupWithRemoteParent) {
// we can't check the opener's location as above since it's cross-origin.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- cross_site_popup_root->current_frame_host(),
+ cross_site_popup_root,
"window.domAutomationController.send("
" window.opener === window.opener.top.frames[0]);",
&success));
@@ -4006,7 +4055,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigatePopupToIllegalURL) {
// Open a cross-site popup.
GURL popup_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
- Shell* popup = OpenPopup(shell()->web_contents(), popup_url, "foo");
+ Shell* popup = OpenPopup(shell(), popup_url, "foo");
EXPECT_TRUE(popup);
EXPECT_NE(popup->web_contents()->GetSiteInstance(),
shell()->web_contents()->GetSiteInstance());
@@ -4014,7 +4063,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigatePopupToIllegalURL) {
// From the opener, navigate the popup to a file:/// URL. This should be
// disallowed and result in an about:blank navigation.
GURL file_url("file:///");
- NavigateNamedFrame(shell()->web_contents(), file_url, "foo");
+ NavigateNamedFrame(shell(), file_url, "foo");
EXPECT_TRUE(WaitForLoadStop(popup->web_contents()));
EXPECT_EQ(GURL(url::kAboutBlankURL),
popup->web_contents()->GetLastCommittedURL());
@@ -4027,7 +4076,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigatePopupToIllegalURL) {
// Now try the same test with a chrome:// URL.
GURL chrome_url(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
- NavigateNamedFrame(shell()->web_contents(), chrome_url, "foo");
+ NavigateNamedFrame(shell(), chrome_url, "foo");
EXPECT_TRUE(WaitForLoadStop(popup->web_contents()));
EXPECT_EQ(GURL(url::kAboutBlankURL),
popup->web_contents()->GetLastCommittedURL());
@@ -4049,8 +4098,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
NavigateFrameToURL(root->child_at(0), frame_url);
// Open a popup named "foo" from the first child.
- Shell* foo_shell = OpenPopup(root->child_at(0)->current_frame_host(),
- GURL(url::kAboutBlankURL), "foo");
+ Shell* foo_shell =
+ OpenPopup(root->child_at(0), GURL(url::kAboutBlankURL), "foo");
EXPECT_TRUE(foo_shell);
// Check that a proxy was created for the "foo" popup in a.com.
@@ -4067,7 +4116,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// window.open targets the correct frame, the "foo" popup's current URL
// should be updated to |named_frame_url|.
GURL named_frame_url(embedded_test_server()->GetURL("c.com", "/title2.html"));
- NavigateNamedFrame(shell()->web_contents(), named_frame_url, "foo");
+ NavigateNamedFrame(shell(), named_frame_url, "foo");
EXPECT_TRUE(WaitForLoadStop(foo_shell->web_contents()));
EXPECT_EQ(named_frame_url, foo_root->current_url());
@@ -4076,7 +4125,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
GURL d_url(embedded_test_server()->GetURL("d.com", "/title3.html"));
NavigateToURL(foo_shell, d_url);
EXPECT_EQ(d_url, foo_root->current_url());
- NavigateNamedFrame(shell()->web_contents(), named_frame_url, "foo");
+ NavigateNamedFrame(shell(), named_frame_url, "foo");
EXPECT_TRUE(WaitForLoadStop(foo_shell->web_contents()));
EXPECT_EQ(named_frame_url, foo_root->current_url());
}
@@ -4097,8 +4146,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Open a same-site popup from the main frame.
GURL a_com_url(embedded_test_server()->GetURL("a.com", "/title3.html"));
- Shell* a_com_shell =
- OpenPopup(root->child_at(0)->current_frame_host(), a_com_url, "");
+ Shell* a_com_shell = OpenPopup(root->child_at(0), a_com_url, "");
EXPECT_TRUE(a_com_shell);
// Navigate first child on main frame cross-site.
@@ -4106,8 +4154,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
NavigateFrameToURL(root->child_at(0), frame_url);
// Open an unnamed popup from the first child frame.
- Shell* foo_shell = OpenPopup(root->child_at(0)->current_frame_host(),
- GURL(url::kAboutBlankURL), "");
+ Shell* foo_shell =
+ OpenPopup(root->child_at(0), GURL(url::kAboutBlankURL), "");
EXPECT_TRUE(foo_shell);
// There should be no proxy created for the "foo" popup in a.com, since
@@ -4121,7 +4169,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
foo_root->render_manager()->GetRenderFrameProxyHost(site_instance_a));
// Set window.name in the popup's frame.
- EXPECT_TRUE(ExecuteScript(foo_shell->web_contents(), "window.name = 'foo'"));
+ EXPECT_TRUE(ExecuteScript(foo_shell, "window.name = 'foo'"));
// A proxy for the popup should now exist in a.com.
EXPECT_TRUE(
@@ -4129,7 +4177,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Verify that the a.com popup can now find the "foo" popup by name.
GURL named_frame_url(embedded_test_server()->GetURL("c.com", "/title2.html"));
- NavigateNamedFrame(a_com_shell->web_contents(), named_frame_url, "foo");
+ NavigateNamedFrame(a_com_shell, named_frame_url, "foo");
EXPECT_TRUE(WaitForLoadStop(foo_shell->web_contents()));
EXPECT_EQ(named_frame_url, foo_root->current_url());
}
@@ -4156,8 +4204,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, UpdateSubframeOpener) {
// From the top frame, open a popup and navigate it to a cross-site page with
// two subframes.
- Shell* popup_shell =
- OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "popup");
+ Shell* popup_shell = OpenPopup(shell(), GURL(url::kAboutBlankURL), "popup");
EXPECT_TRUE(popup_shell);
GURL popup_url(embedded_test_server()->GetURL(
"bar.com", "/frame_tree/page_with_post_message_frames.html"));
@@ -4176,7 +4223,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, UpdateSubframeOpener) {
// is same-origin with the top frame, i.e., foo.com).
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1)->current_frame_host(),
+ root->child_at(1),
"window.domAutomationController.send(!!window.open('','popup'));",
&success));
EXPECT_TRUE(success);
@@ -4187,7 +4234,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, UpdateSubframeOpener) {
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_shell->web_contents(),
+ popup_shell,
"window.domAutomationController.send("
" window.opener === window.opener.parent.frames['frame2']);",
&success));
@@ -4197,7 +4244,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, UpdateSubframeOpener) {
// page's first subframe (bar.com).
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0)->current_frame_host(),
+ root->child_at(0),
"window.domAutomationController.send(!!window.open('','subframe2'));",
&success));
EXPECT_TRUE(success);
@@ -4208,7 +4255,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, UpdateSubframeOpener) {
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(1)->current_frame_host(),
+ popup_root->child_at(1),
"window.domAutomationController.send("
" window.opener === window.opener.parent.frames['frame1']);",
&success));
@@ -4229,7 +4276,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Open a popup with a cross-site page that has a subframe.
GURL popup_url(embedded_test_server()->GetURL(
"b.com", "/cross_site_iframe_factory.html?b(b)"));
- Shell* popup_shell = OpenPopup(shell()->web_contents(), popup_url, "popup");
+ Shell* popup_shell = OpenPopup(shell(), popup_url, "popup");
EXPECT_TRUE(popup_shell);
FrameTreeNode* popup_root =
static_cast<WebContentsImpl*>(popup_shell->web_contents())
@@ -4248,14 +4295,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// parent by sending a postMessage to subframe's parent.opener.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0)->current_frame_host(),
+ popup_root->child_at(0),
"window.domAutomationController.send(!!parent.opener);", &success));
EXPECT_TRUE(success);
base::string16 expected_title = base::ASCIIToUTF16("msg");
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0)->current_frame_host(),
+ popup_root->child_at(0),
"window.domAutomationController.send(postToOpenerOfParent('msg','*'));",
&success));
EXPECT_TRUE(success);
@@ -4281,8 +4328,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateSubframeWithOpener) {
// Update the first (cross-site) subframe's opener to root frame.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->current_frame_host(),
- "window.domAutomationController.send(!!window.open('','frame1'));",
+ root, "window.domAutomationController.send(!!window.open('','frame1'));",
&success));
EXPECT_TRUE(success);
@@ -4292,7 +4338,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateSubframeWithOpener) {
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0)->current_frame_host(),
+ root->child_at(0),
"window.domAutomationController.send(window.opener === window.parent);",
&success));
EXPECT_TRUE(success);
@@ -4304,7 +4350,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateSubframeWithOpener) {
// Check that the subframe still sees correct opener in its new process.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(0)->current_frame_host(),
+ root->child_at(0),
"window.domAutomationController.send(window.opener === window.parent);",
&success));
EXPECT_TRUE(success);
@@ -4316,7 +4362,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateSubframeWithOpener) {
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->child_at(1)->current_frame_host(),
+ root->child_at(1),
"window.domAutomationController.send("
" parent.frames['frame1'].opener === parent);",
&success));
@@ -4339,7 +4385,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Open a popup with a cross-site page that has two subframes.
GURL popup_url(embedded_test_server()->GetURL(
"bar.com", "/frame_tree/page_with_post_message_frames.html"));
- Shell* popup_shell = OpenPopup(shell()->web_contents(), popup_url, "popup");
+ Shell* popup_shell = OpenPopup(shell(), popup_url, "popup");
EXPECT_TRUE(popup_shell);
FrameTreeNode* popup_root =
static_cast<WebContentsImpl*>(popup_shell->web_contents())
@@ -4358,7 +4404,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// root frame.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- root->current_frame_host(),
+ root,
"window.domAutomationController.send(!!window.open('','subframe2'));",
&success));
EXPECT_TRUE(success);
@@ -4368,7 +4414,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(root, popup_root->child_at(1)->opener());
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0)->current_frame_host(),
+ popup_root->child_at(0),
"window.domAutomationController.send("
" parent.frames['subframe2'].opener && "
" parent.frames['subframe2'].opener === parent.opener);",
@@ -4384,7 +4430,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// subframe's new process. Verify it both in JS and with a postMessage.
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0)->current_frame_host(),
+ popup_root->child_at(0),
"window.domAutomationController.send("
" parent.frames['subframe2'].opener && "
" parent.frames['subframe2'].opener === parent.opener);",
@@ -4394,7 +4440,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
base::string16 expected_title = base::ASCIIToUTF16("msg");
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- popup_root->child_at(0)->current_frame_host(),
+ popup_root->child_at(0),
"window.domAutomationController.send("
" postToOpenerOfSibling('subframe2', 'msg', '*'));",
&success));
@@ -4485,7 +4531,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
" var start = Date.now();"
" while (Date.now() - start < 1000);"
"}";
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+ EXPECT_TRUE(ExecuteScript(shell(), script));
// Navigating cross-site with an iframe to the original site shouldn't crash.
GURL second_url(embedded_test_server()->GetURL(
@@ -4524,8 +4570,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Focus the main frame's text field. The return value "input-focus"
// indicates that the focus event was fired correctly.
std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(shell()->web_contents(),
- "focusInputField()", &result));
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractString(shell(), "focusInputField()", &result));
EXPECT_EQ(result, "input-focus");
// The main frame should be focused.
@@ -4675,14 +4721,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SubframeWindowFocus) {
" domAutomationController.send('%s-lost-focus');"
"});";
std::string script = base::StringPrintf(kSetupFocusEvents, "main", "main");
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+ EXPECT_TRUE(ExecuteScript(shell(), script));
script = base::StringPrintf(kSetupFocusEvents, "child1", "child1");
- EXPECT_TRUE(ExecuteScript(child1->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(child1, script));
script = base::StringPrintf(kSetupFocusEvents, "child2", "child2");
- EXPECT_TRUE(ExecuteScript(child2->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(child2, script));
// Execute window.focus on the B subframe from the A main frame.
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "frames[0].focus()"));
+ EXPECT_TRUE(ExecuteScript(root, "frames[0].focus()"));
// Helper to wait for two specified messages to arrive on the specified
// DOMMessageQueue, assuming that the two messages can arrive in any order.
@@ -4712,7 +4758,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SubframeWindowFocus) {
// Now, execute window.focus on the C subframe from A main frame. This
// checks that we can shift focus from one remote frame to another.
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), "frames[1].focus()"));
+ EXPECT_TRUE(ExecuteScript(root, "frames[1].focus()"));
// Wait for the two subframes (B and C) to fire blur and focus events.
wait_for_two_messages(&msg_queue, "\"child1-lost-focus\"",
@@ -4722,7 +4768,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SubframeWindowFocus) {
EXPECT_EQ(child2, root->frame_tree()->GetFocusedFrame());
// window.focus the main frame from the C subframe.
- EXPECT_TRUE(ExecuteScript(child2->current_frame_host(), "parent.focus()"));
+ EXPECT_TRUE(ExecuteScript(child2, "parent.focus()"));
// Wait for the C subframe to blur and main frame to focus.
wait_for_two_messages(&msg_queue, "\"child2-lost-focus\"",
@@ -4821,13 +4867,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenerSetLocation) {
// Load cross-site page into a new window.
GURL cross_url = embedded_test_server()->GetURL("foo.com", "/title1.html");
- Shell* popup = OpenPopup(shell()->web_contents(), cross_url, "");
+ Shell* popup = OpenPopup(shell(), cross_url, "");
EXPECT_EQ(popup->web_contents()->GetLastCommittedURL(), cross_url);
// Use new window to navigate main window.
std::string script =
"window.opener.location.href = '" + cross_url.spec() + "'";
- EXPECT_TRUE(ExecuteScript(popup->web_contents(), script));
+ EXPECT_TRUE(ExecuteScript(popup, script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), cross_url);
}
@@ -4871,7 +4917,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Verify touch handler in subframe was invoked
std::string result;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0)->current_frame_host(),
+ root->child_at(0),
"window.domAutomationController.send(getLastTouchEvent());", &result));
EXPECT_EQ("touchstart", result);
}
@@ -4980,15 +5026,18 @@ void SendTouchTapWithExpectedTarget(
void SendGestureTapSequenceWithExpectedTarget(
RenderWidgetHostViewBase* root_view,
- gfx::Point gesture_point,
+ const gfx::Point& gesture_point,
RenderWidgetHostViewBase*& router_gesture_target,
const RenderWidgetHostViewBase* old_expected_target,
const RenderWidgetHostViewBase* expected_target) {
auto root_view_aura = static_cast<RenderWidgetHostViewAura*>(root_view);
- ui::GestureEvent gesture_begin_event(
- gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_BEGIN));
+ ui::GestureEventDetails gesture_begin_details(ui::ET_GESTURE_BEGIN);
+ gesture_begin_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent gesture_begin_event(gesture_point.x(), gesture_point.y(), 0,
+ ui::EventTimeForNow(),
+ gesture_begin_details);
root_view_aura->OnGestureEvent(&gesture_begin_event);
// We expect to still have the old gesture target in place for the
// GestureFlingCancel that will be inserted before GestureTapDown.
@@ -4997,33 +5046,94 @@ void SendGestureTapSequenceWithExpectedTarget(
// explicitly add it here.
EXPECT_EQ(old_expected_target, router_gesture_target);
- ui::GestureEvent gesture_tap_down_event(
- gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
+ ui::GestureEventDetails gesture_tap_down_details(ui::ET_GESTURE_TAP_DOWN);
+ gesture_tap_down_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent gesture_tap_down_event(gesture_point.x(), gesture_point.y(),
+ 0, ui::EventTimeForNow(),
+ gesture_tap_down_details);
root_view_aura->OnGestureEvent(&gesture_tap_down_event);
EXPECT_EQ(expected_target, router_gesture_target);
+ ui::GestureEventDetails gesture_show_press_details(ui::ET_GESTURE_SHOW_PRESS);
+ gesture_show_press_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
ui::GestureEvent gesture_show_press_event(
gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS));
+ gesture_show_press_details);
root_view_aura->OnGestureEvent(&gesture_show_press_event);
EXPECT_EQ(expected_target, router_gesture_target);
ui::GestureEventDetails gesture_tap_details(ui::ET_GESTURE_TAP);
+ gesture_tap_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
gesture_tap_details.set_tap_count(1);
- ui::GestureEvent gesture_tap_event(
- gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
- gesture_tap_details);
+ ui::GestureEvent gesture_tap_event(gesture_point.x(), gesture_point.y(), 0,
+ ui::EventTimeForNow(),
+ gesture_tap_details);
root_view_aura->OnGestureEvent(&gesture_tap_event);
EXPECT_EQ(expected_target, router_gesture_target);
- ui::GestureEvent gesture_end_event(
- gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_END));
+ ui::GestureEventDetails gesture_end_details(ui::ET_GESTURE_END);
+ gesture_end_details.set_device_type(
+ ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ ui::GestureEvent gesture_end_event(gesture_point.x(), gesture_point.y(), 0,
+ ui::EventTimeForNow(),
+ gesture_end_details);
root_view_aura->OnGestureEvent(&gesture_end_event);
EXPECT_EQ(expected_target, router_gesture_target);
}
+void SendTouchpadPinchSequenceWithExpectedTarget(
+ RenderWidgetHostViewBase* root_view,
+ const gfx::Point& gesture_point,
+ RenderWidgetHostViewBase*& router_touchpad_gesture_target,
+ RenderWidgetHostViewBase* expected_target) {
+ auto root_view_aura = static_cast<RenderWidgetHostViewAura*>(root_view);
+
+ ui::GestureEventDetails pinch_begin_details(ui::ET_GESTURE_PINCH_BEGIN);
+ pinch_begin_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+ ui::GestureEvent pinch_begin(gesture_point.x(), gesture_point.y(), 0,
+ ui::EventTimeForNow(), pinch_begin_details);
+ root_view_aura->OnGestureEvent(&pinch_begin);
+ EXPECT_EQ(expected_target, router_touchpad_gesture_target);
+
+ ui::GestureEventDetails pinch_update_details(ui::ET_GESTURE_PINCH_UPDATE);
+ pinch_update_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+ ui::GestureEvent pinch_update(gesture_point.x(), gesture_point.y(), 0,
+ ui::EventTimeForNow(), pinch_update_details);
+ root_view_aura->OnGestureEvent(&pinch_update);
+ EXPECT_EQ(expected_target, router_touchpad_gesture_target);
+
+ ui::GestureEventDetails pinch_end_details(ui::ET_GESTURE_PINCH_END);
+ pinch_end_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+ ui::GestureEvent pinch_end(gesture_point.x(), gesture_point.y(), 0,
+ ui::EventTimeForNow(), pinch_end_details);
+ root_view_aura->OnGestureEvent(&pinch_end);
+ EXPECT_EQ(expected_target, router_touchpad_gesture_target);
+}
+
+#if !defined(OS_WIN)
+// Sending touchpad fling events is not supported on Windows.
+void SendTouchpadFlingSequenceWithExpectedTarget(
+ RenderWidgetHostViewBase* root_view,
+ const gfx::Point& gesture_point,
+ RenderWidgetHostViewBase*& router_touchpad_gesture_target,
+ RenderWidgetHostViewBase* expected_target) {
+ auto root_view_aura = static_cast<RenderWidgetHostViewAura*>(root_view);
+
+ ui::ScrollEvent fling_start(ui::ET_SCROLL_FLING_START, gesture_point,
+ ui::EventTimeForNow(), 0, 1, 0, 1, 0, 1);
+ root_view_aura->OnScrollEvent(&fling_start);
+ EXPECT_EQ(expected_target, router_touchpad_gesture_target);
+
+ ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, gesture_point,
+ ui::EventTimeForNow(), 0, 1, 0, 1, 0, 1);
+ root_view_aura->OnScrollEvent(&fling_cancel);
+ EXPECT_EQ(expected_target, router_touchpad_gesture_target);
+}
+#endif
+
} // namespace anonymous
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
@@ -5055,58 +5165,126 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
contents->GetRenderWidgetHostView());
RenderWidgetHostInputEventRouter* router = contents->GetInputEventRouter();
- EXPECT_TRUE(router->gesture_target_queue_.empty());
- EXPECT_EQ(nullptr, router->gesture_target_);
+ EXPECT_TRUE(router->touchscreen_gesture_target_queue_.empty());
+ EXPECT_EQ(nullptr, router->touchscreen_gesture_target_.target);
// Send touch sequence to main-frame.
gfx::Point main_frame_point(25, 25);
SendTouchTapWithExpectedTarget(rwhv_parent, main_frame_point,
- router->touch_target_, rwhv_parent);
- EXPECT_EQ(1LU, router->gesture_target_queue_.size());
- EXPECT_EQ(nullptr, router->gesture_target_);
-
+ router->touch_target_.target, rwhv_parent);
+ EXPECT_EQ(1LU, router->touchscreen_gesture_target_queue_.size());
+ EXPECT_EQ(nullptr, router->touchscreen_gesture_target_.target);
// Send touch sequence to child.
gfx::Point child_center(150, 150);
SendTouchTapWithExpectedTarget(rwhv_parent, child_center,
- router->touch_target_, rwhv_child);
- EXPECT_EQ(2LU, router->gesture_target_queue_.size());
- EXPECT_EQ(nullptr, router->gesture_target_);
+ router->touch_target_.target, rwhv_child);
+ EXPECT_EQ(2LU, router->touchscreen_gesture_target_queue_.size());
+ EXPECT_EQ(nullptr, router->touchscreen_gesture_target_.target);
// Send another touch sequence to main frame.
SendTouchTapWithExpectedTarget(rwhv_parent, main_frame_point,
- router->touch_target_, rwhv_parent);
- EXPECT_EQ(3LU, router->gesture_target_queue_.size());
- EXPECT_EQ(nullptr, router->gesture_target_);
+ router->touch_target_.target, rwhv_parent);
+ EXPECT_EQ(3LU, router->touchscreen_gesture_target_queue_.size());
+ EXPECT_EQ(nullptr, router->touchscreen_gesture_target_.target);
// Send Gestures to clear GestureTargetQueue.
// The first touch sequence should generate a GestureTapDown, sent to the
// main frame.
- SendGestureTapSequenceWithExpectedTarget(rwhv_parent, main_frame_point,
- router->gesture_target_, nullptr,
- rwhv_parent);
- EXPECT_EQ(2LU, router->gesture_target_queue_.size());
+ SendGestureTapSequenceWithExpectedTarget(
+ rwhv_parent, main_frame_point, router->touchscreen_gesture_target_.target,
+ nullptr, rwhv_parent);
+ EXPECT_EQ(2LU, router->touchscreen_gesture_target_queue_.size());
// Note: rwhv_parent is the target used for GestureFlingCancel sent by
// RenderWidgetHostViewAura::OnGestureEvent() at the start of the next gesture
// sequence; the sequence itself goes to rwhv_child.
- EXPECT_EQ(rwhv_parent, router->gesture_target_);
+ EXPECT_EQ(rwhv_parent, router->touchscreen_gesture_target_.target);
// The second touch sequence should generate a GestureTapDown, sent to the
// child frame.
- SendGestureTapSequenceWithExpectedTarget(rwhv_parent, child_center,
- router->gesture_target_, rwhv_parent,
- rwhv_child);
- EXPECT_EQ(1LU, router->gesture_target_queue_.size());
- EXPECT_EQ(rwhv_child, router->gesture_target_);
+ SendGestureTapSequenceWithExpectedTarget(
+ rwhv_parent, child_center, router->touchscreen_gesture_target_.target,
+ rwhv_parent, rwhv_child);
+ EXPECT_EQ(1LU, router->touchscreen_gesture_target_queue_.size());
+ EXPECT_EQ(rwhv_child, router->touchscreen_gesture_target_.target);
// The third touch sequence should generate a GestureTapDown, sent to the
// main frame.
- SendGestureTapSequenceWithExpectedTarget(rwhv_parent, main_frame_point,
- router->gesture_target_, rwhv_child,
- rwhv_parent);
- EXPECT_EQ(0LU, router->gesture_target_queue_.size());
- EXPECT_EQ(rwhv_parent, router->gesture_target_);
+ SendGestureTapSequenceWithExpectedTarget(
+ rwhv_parent, main_frame_point, router->touchscreen_gesture_target_.target,
+ rwhv_child, rwhv_parent);
+ EXPECT_EQ(0LU, router->touchscreen_gesture_target_queue_.size());
+ EXPECT_EQ(rwhv_parent, router->touchscreen_gesture_target_.target);
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ InputEventRouterTouchpadGestureTargetTest) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_nested_frames.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ WebContentsImpl* contents = web_contents();
+ FrameTreeNode* root = contents->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ GURL frame_url(
+ embedded_test_server()->GetURL("b.com", "/page_with_click_handler.html"));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+ auto child_frame_host = root->child_at(0)->current_frame_host();
+
+ // Synchronize with the child and parent renderers to guarantee that the
+ // surface information required for event hit testing is ready.
+ auto rwhv_child =
+ static_cast<RenderWidgetHostViewBase*>(child_frame_host->GetView());
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child));
+ notifier.WaitForSurfaceReady();
+
+ // All touches & gestures are sent to the main frame's view, and should be
+ // routed appropriately from there.
+ auto rwhv_parent = static_cast<RenderWidgetHostViewBase*>(
+ contents->GetRenderWidgetHostView());
+
+ RenderWidgetHostInputEventRouter* router = contents->GetInputEventRouter();
+ EXPECT_EQ(nullptr, router->touchpad_gesture_target_.target);
+
+ gfx::Point main_frame_point(25, 25);
+ gfx::Point child_center(150, 150);
+
+ // Send touchpad pinch sequence to main-frame.
+ SendTouchpadPinchSequenceWithExpectedTarget(
+ rwhv_parent, main_frame_point, router->touchpad_gesture_target_.target,
+ rwhv_parent);
+
+ // Send touchpad pinch sequence to child.
+ SendTouchpadPinchSequenceWithExpectedTarget(
+ rwhv_parent, child_center, router->touchpad_gesture_target_.target,
+ rwhv_child);
+
+ // Send another touchpad pinch sequence to main frame.
+ SendTouchpadPinchSequenceWithExpectedTarget(
+ rwhv_parent, main_frame_point, router->touchpad_gesture_target_.target,
+ rwhv_parent);
+
+#if !defined(OS_WIN)
+ // Sending touchpad fling events is not supported on Windows.
+
+ // Send touchpad fling sequence to main-frame.
+ SendTouchpadFlingSequenceWithExpectedTarget(
+ rwhv_parent, main_frame_point, router->touchpad_gesture_target_.target,
+ rwhv_parent);
+
+ // Send touchpad fling sequence to child.
+ SendTouchpadFlingSequenceWithExpectedTarget(
+ rwhv_parent, child_center, router->touchpad_gesture_target_.target,
+ rwhv_child);
+
+ // Send another touchpad fling sequence to main frame.
+ SendTouchpadFlingSequenceWithExpectedTarget(
+ rwhv_parent, main_frame_point, router->touchpad_gesture_target_.target,
+ rwhv_parent);
+#endif
}
#endif // defined(USE_AURA)
@@ -5349,12 +5527,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_PopupMenuTest) {
click_event.x = 15;
click_event.y = 15;
click_event.clickCount = 1;
- rwhv_child->ProcessMouseEvent(click_event);
+ rwhv_child->ProcessMouseEvent(click_event, ui::LatencyInfo());
// Dismiss the popup.
click_event.x = 1;
click_event.y = 1;
- rwhv_child->ProcessMouseEvent(click_event);
+ rwhv_child->ProcessMouseEvent(click_event, ui::LatencyInfo());
filter->Wait();
gfx::Rect popup_rect = filter->last_initial_rect();
@@ -5424,12 +5602,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NestedPopupMenuTest) {
click_event.x = 15;
click_event.y = 15;
click_event.clickCount = 1;
- rwhv_c_node->ProcessMouseEvent(click_event);
+ rwhv_c_node->ProcessMouseEvent(click_event, ui::LatencyInfo());
// Prompt the WebContents to dismiss the popup by clicking elsewhere.
click_event.x = 1;
click_event.y = 1;
- rwhv_c_node->ProcessMouseEvent(click_event);
+ rwhv_c_node->ProcessMouseEvent(click_event, ui::LatencyInfo());
filter->Wait();
@@ -5454,7 +5632,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NestedPopupMenuTest) {
"iframe.style.position = 'absolute';"
"iframe.style.left = 150;"
"iframe.style.top = 150;";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
filter->Reset();
@@ -5474,11 +5652,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NestedPopupMenuTest) {
click_event.x = 15;
click_event.y = 15;
click_event.clickCount = 1;
- rwhv_c_node->ProcessMouseEvent(click_event);
+ rwhv_c_node->ProcessMouseEvent(click_event, ui::LatencyInfo());
click_event.x = 1;
click_event.y = 1;
- rwhv_c_node->ProcessMouseEvent(click_event);
+ rwhv_c_node->ProcessMouseEvent(click_event, ui::LatencyInfo());
filter->Wait();
@@ -5515,7 +5693,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
"var f = document.querySelector('iframe');"
"f.contentWindow.location.href = 'about:blank';"
"setTimeout(function() { document.body.removeChild(f); }, 0);";
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root, script));
observer.Wait();
EXPECT_EQ(1U, root->child_count());
@@ -5523,9 +5701,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// navigation to the frame that's already been deleted.
int child_count = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->current_frame_host(),
- "domAutomationController.send(frames.length)",
- &child_count));
+ root, "domAutomationController.send(frames.length)", &child_count));
EXPECT_EQ(1, child_count);
}
@@ -5557,17 +5733,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// previous navigation starts but before it commits.
FrameDeletedObserver observer(child);
EXPECT_TRUE(ExecuteScript(
- root->current_frame_host(),
- "document.body.removeChild(document.querySelector('iframe'));"));
+ root, "document.body.removeChild(document.querySelector('iframe'));"));
observer.Wait();
EXPECT_EQ(1U, root->child_count());
// Make sure the a.com renderer does not crash.
int child_count = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->current_frame_host(),
- "domAutomationController.send(frames.length)",
- &child_count));
+ root, "domAutomationController.send(frames.length)", &child_count));
EXPECT_EQ(1, child_count);
}
@@ -5589,16 +5762,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateAboutBlankAndDetach) {
// Navigate the child frame to "about:blank" from the parent document.
TestNavigationObserver observer(shell()->web_contents());
- EXPECT_TRUE(
- ExecuteScript(root->current_frame_host(),
- base::StringPrintf("f.src = '%s'", url::kAboutBlankURL)));
+ EXPECT_TRUE(ExecuteScript(
+ root, base::StringPrintf("f.src = '%s'", url::kAboutBlankURL)));
observer.Wait();
// Make sure the a.com renderer does not crash and the frame is removed.
int child_count = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->current_frame_host(), "domAutomationController.send(frames.length)",
- &child_count));
+ root, "domAutomationController.send(frames.length)", &child_count));
EXPECT_EQ(0, child_count);
}
@@ -5636,8 +5807,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Tell main frame A to delete its subframe B.
FrameDeletedObserver observer(root->child_at(0));
EXPECT_TRUE(ExecuteScript(
- root->current_frame_host(),
- "document.body.removeChild(document.querySelector('iframe'));"));
+ root, "document.body.removeChild(document.querySelector('iframe'));"));
// 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
@@ -5653,9 +5823,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Make sure process A did not crash.
int child_count = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->current_frame_host(),
- "domAutomationController.send(frames.length)",
- &child_count));
+ root, "domAutomationController.send(frames.length)", &child_count));
EXPECT_EQ(0, child_count);
}
@@ -5827,13 +5995,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, VisibilityChanged) {
// Verify that hiding leads to a notification from RenderWidgetHost.
RenderWidgetHostVisibilityObserver hide_observer(
root->child_at(0)->current_frame_host()->GetRenderWidgetHost(), false);
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), hide_script));
+ EXPECT_TRUE(ExecuteScript(shell(), hide_script));
EXPECT_TRUE(hide_observer.WaitUntilSatisfied());
// Verify showing leads to a notification as well.
RenderWidgetHostVisibilityObserver show_observer(
root->child_at(0)->current_frame_host()->GetRenderWidgetHost(), true);
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), show_script));
+ EXPECT_TRUE(ExecuteScript(shell(), show_script));
EXPECT_TRUE(show_observer.WaitUntilSatisfied());
}
@@ -5849,8 +6017,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsInheritance) {
// Set sandbox flags for child frame.
EXPECT_TRUE(ExecuteScript(
- root->current_frame_host(),
- "document.querySelector('iframe').sandbox = 'allow-scripts';"));
+ root, "document.querySelector('iframe').sandbox = 'allow-scripts';"));
// Calculate expected flags. Note that "allow-scripts" resets both
// WebSandboxFlags::Scripts and WebSandboxFlags::AutomaticFeatures bits per
@@ -5902,8 +6069,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Set sandbox flags for child frame.
EXPECT_TRUE(ExecuteScript(
- root->current_frame_host(),
- "document.querySelector('iframe').sandbox = 'allow-scripts';"));
+ root, "document.querySelector('iframe').sandbox = 'allow-scripts';"));
// These flags should be pending but not take effect, since there's been no
// navigation.
@@ -5917,8 +6083,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Add a new grandchild frame and navigate it cross-site.
RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 1);
EXPECT_TRUE(ExecuteScript(
- child->current_frame_host(),
- "document.body.appendChild(document.createElement('iframe'));"));
+ child, "document.body.appendChild(document.createElement('iframe'));"));
frame_observer.Wait();
FrameTreeNode* grandchild = child->child_at(0);
@@ -5951,7 +6116,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
// Set sandbox flags for child frame.
- EXPECT_TRUE(ExecuteScript(root->current_frame_host(),
+ EXPECT_TRUE(ExecuteScript(root,
"document.querySelector('iframe').sandbox = "
" 'allow-scripts allow-popups';"));
@@ -5976,8 +6141,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ("null", GetDocumentOrigin(root->child_at(0)));
// Open a popup named "foo" from the sandboxed child frame.
- Shell* foo_shell = OpenPopup(root->child_at(0)->current_frame_host(),
- GURL(url::kAboutBlankURL), "foo");
+ Shell* foo_shell =
+ OpenPopup(root->child_at(0), GURL(url::kAboutBlankURL), "foo");
EXPECT_TRUE(foo_shell);
FrameTreeNode* foo_root =
@@ -5996,8 +6161,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// inherited sandbox flags.
GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
TestFrameNavigationObserver popup_observer(foo_root);
- EXPECT_TRUE(ExecuteScript(foo_root->current_frame_host(),
- "location.href = '" + c_url.spec() + "';"));
+ EXPECT_TRUE(
+ ExecuteScript(foo_root, "location.href = '" + c_url.spec() + "';"));
popup_observer.Wait();
EXPECT_EQ(c_url, foo_shell->web_contents()->GetLastCommittedURL());
@@ -6022,7 +6187,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Set sandbox flags for child frame, specifying that popups opened from it
// should not be sandboxed.
EXPECT_TRUE(ExecuteScript(
- root->current_frame_host(),
+ root,
"document.querySelector('iframe').sandbox = "
" 'allow-scripts allow-popups allow-popups-to-escape-sandbox';"));
@@ -6045,8 +6210,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Open a cross-site popup named "foo" from the child frame.
GURL b_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
- Shell* foo_shell =
- OpenPopup(root->child_at(0)->current_frame_host(), b_url, "foo");
+ Shell* foo_shell = OpenPopup(root->child_at(0), b_url, "foo");
EXPECT_TRUE(foo_shell);
FrameTreeNode* foo_root =
@@ -6061,8 +6225,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The popup's origin should match |b_url|, since it's not sandboxed.
std::string popup_origin;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- foo_root->current_frame_host(),
- "domAutomationController.send(document.origin)",
+ foo_root, "domAutomationController.send(document.origin)",
&popup_origin));
EXPECT_EQ(b_url.GetOrigin().spec(), popup_origin + "/");
}
@@ -6119,28 +6282,67 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
- EXPECT_TRUE(root->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
- EXPECT_TRUE(root->child_at(0)
- ->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
+ EXPECT_EQ(blink::kBlockAllMixedContent,
+ root->current_replication_state().insecure_request_policy);
+ EXPECT_EQ(
+ blink::kBlockAllMixedContent,
+ root->child_at(0)->current_replication_state().insecure_request_policy);
// When the subframe navigates, it should still be marked as enforcing
// strict mixed content.
GURL navigate_url(https_server.GetURL("/title1.html"));
NavigateFrameToURL(root->child_at(0), navigate_url);
- EXPECT_TRUE(root->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
- EXPECT_TRUE(root->child_at(0)
- ->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
+ EXPECT_EQ(blink::kBlockAllMixedContent,
+ root->current_replication_state().insecure_request_policy);
+ EXPECT_EQ(
+ blink::kBlockAllMixedContent,
+ root->child_at(0)->current_replication_state().insecure_request_policy);
// When the main frame navigates, it should no longer be marked as
// enforcing strict mixed content.
EXPECT_TRUE(
NavigateToURL(shell(), https_server.GetURL("b.com", "/title1.html")));
- EXPECT_FALSE(root->current_replication_state()
- .should_enforce_strict_mixed_content_checking);
+ EXPECT_EQ(blink::kLeaveInsecureRequestsAlone,
+ root->current_replication_state().insecure_request_policy);
+}
+
+// Tests that, when a parent frame is set to upgrade insecure requests
+// via Content Security Policy, child OOPIFs will upgrade as well.
+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);
+
+ 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(shell()->web_contents()->DisplayedInsecureContent());
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ EXPECT_EQ(blink::kUpgradeInsecureRequests,
+ root->current_replication_state().insecure_request_policy);
+ EXPECT_EQ(
+ blink::kUpgradeInsecureRequests,
+ root->child_at(0)->current_replication_state().insecure_request_policy);
+
+ // When the subframe navigates, it should still be marked as upgrading
+ // insecure requests.
+ GURL navigate_url(https_server.GetURL("/title1.html"));
+ NavigateFrameToURL(root->child_at(0), navigate_url);
+ EXPECT_EQ(blink::kUpgradeInsecureRequests,
+ root->current_replication_state().insecure_request_policy);
+ EXPECT_EQ(
+ blink::kUpgradeInsecureRequests,
+ root->child_at(0)->current_replication_state().insecure_request_policy);
+
+ // When the main frame navigates, it should no longer be marked as
+ // upgrading insecure requests.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), https_server.GetURL("b.com", "/title1.html")));
+ EXPECT_EQ(blink::kLeaveInsecureRequestsAlone,
+ root->current_replication_state().insecure_request_policy);
}
// Tests that active mixed content is blocked in an OOPIF. The test
@@ -6245,9 +6447,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframeDisplayNone) {
root->current_frame_host()->GetRenderWidgetHost();
// Set the iframe to display: none.
- EXPECT_TRUE(
- ExecuteScript(shell()->web_contents(),
- "document.querySelector('iframe').style.display = 'none'"));
+ EXPECT_TRUE(ExecuteScript(
+ shell(), "document.querySelector('iframe').style.display = 'none'"));
// Waits until pending frames are done.
std::unique_ptr<MainThreadFrameObserver> observer(
@@ -6255,8 +6456,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframeDisplayNone) {
observer->Wait();
// Force the renderer to generate a new frame.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "document.body.style.background = 'black'"));
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "document.body.style.background = 'black'"));
// Waits for the next frame.
observer->Wait();
@@ -6273,7 +6474,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
// Add a load event handler for the iframe element.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ EXPECT_TRUE(ExecuteScript(shell(),
"document.querySelector('iframe').onload = "
" function() { document.title = 'loaded'; };"));
@@ -6283,16 +6484,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
};
for (size_t i = 0; i < arraysize(blocked_urls); ++i) {
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "document.title = 'not loaded';"));
+ EXPECT_TRUE(ExecuteScript(shell(), "document.title = 'not loaded';"));
base::string16 expected_title(base::UTF8ToUTF16("loaded"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
// Navigate the subframe to a blocked URL.
TestNavigationObserver load_observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(
- shell()->web_contents(),
- "frames[0].location.href = '" + blocked_urls[i].spec() + "';"));
+ EXPECT_TRUE(ExecuteScript(shell(), "frames[0].location.href = '" +
+ blocked_urls[i].spec() + "';"));
load_observer.Wait();
// The blocked frame's origin should become unique.
@@ -6315,8 +6514,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// isn't active anymore (both of these pages have non-empty titles).
std::string frame_title;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0)->current_frame_host(),
- "domAutomationController.send(document.title)", &frame_title));
+ root->child_at(0), "domAutomationController.send(document.title)",
+ &frame_title));
EXPECT_EQ("", frame_title);
// Navigate the subframe to another cross-origin page and ensure that this
@@ -6359,20 +6558,18 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ("frame-src 'self' http://b.com:*", root_csp[0].header_value);
// Monitor subframe's load events via main frame's title.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ EXPECT_TRUE(ExecuteScript(shell(),
"document.querySelector('iframe').onload = "
" function() { document.title = 'loaded'; };"));
- EXPECT_TRUE(
- ExecuteScript(shell()->web_contents(), "document.title = 'not loaded';"));
+ EXPECT_TRUE(ExecuteScript(shell(), "document.title = 'not loaded';"));
base::string16 expected_title(base::UTF8ToUTF16("loaded"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
// Try to navigate the subframe to a blocked URL.
TestNavigationObserver load_observer(shell()->web_contents());
GURL blocked_url = embedded_test_server()->GetURL("c.com", "/title3.html");
- EXPECT_TRUE(
- ExecuteScript(root->child_at(0)->current_frame_host(),
- "window.location.href = '" + blocked_url.spec() + "';"));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), "window.location.href = '" +
+ blocked_url.spec() + "';"));
// The blocked frame should still fire a load event in its parent's process.
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
@@ -6389,8 +6586,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The blocked frame should keep the old title.
std::string frame_title;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0)->current_frame_host(),
- "domAutomationController.send(document.title)", &frame_title));
+ root->child_at(0), "domAutomationController.send(document.title)",
+ &frame_title));
EXPECT_EQ("Title Of Awesomeness", frame_title);
// Navigate to a URL without CSP.
@@ -6420,7 +6617,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Add frame-src CSP via a new <meta> element.
EXPECT_TRUE(ExecuteScript(
- shell()->web_contents(),
+ shell(),
"var meta = document.createElement('meta');"
"meta.httpEquiv = 'Content-Security-Policy';"
"meta.content = 'frame-src https://a.com:*';"
@@ -6436,20 +6633,18 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ("frame-src https://a.com:*", root_csp[0].header_value);
// Monitor subframe's load events via main frame's title.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ EXPECT_TRUE(ExecuteScript(shell(),
"document.querySelector('iframe').onload = "
" function() { document.title = 'loaded'; };"));
- EXPECT_TRUE(
- ExecuteScript(shell()->web_contents(), "document.title = 'not loaded';"));
+ EXPECT_TRUE(ExecuteScript(shell(), "document.title = 'not loaded';"));
base::string16 expected_title(base::UTF8ToUTF16("loaded"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
// Try to navigate the subframe to a blocked URL.
TestNavigationObserver load_observer2(shell()->web_contents());
GURL blocked_url = embedded_test_server()->GetURL("c.com", "/title3.html");
- EXPECT_TRUE(
- ExecuteScript(root->child_at(0)->current_frame_host(),
- "window.location.href = '" + blocked_url.spec() + "';"));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), "window.location.href = '" +
+ blocked_url.spec() + "';"));
// The blocked frame should still fire a load event in its parent's process.
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
@@ -6466,8 +6661,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The blocked frame should keep the old title.
std::string frame_title;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- root->child_at(0)->current_frame_host(),
- "domAutomationController.send(document.title)", &frame_title));
+ root->child_at(0), "domAutomationController.send(document.title)",
+ &frame_title));
EXPECT_EQ("Title Of Awesomeness", frame_title);
}
@@ -6502,25 +6697,23 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Monitor navigating_frame's load events via srcdoc_frame posting
// a message to the parent frame.
EXPECT_TRUE(
- ExecuteScript(root->current_frame_host(),
+ ExecuteScript(root,
"window.addEventListener('message', function(event) {"
" document.title = event.data;"
"});"));
EXPECT_TRUE(ExecuteScript(
- srcdoc_frame->current_frame_host(),
+ srcdoc_frame,
"document.querySelector('iframe').onload = "
" function() { window.top.postMessage('loaded', '*'); };"));
- EXPECT_TRUE(
- ExecuteScript(shell()->web_contents(), "document.title = 'not loaded';"));
+ EXPECT_TRUE(ExecuteScript(shell(), "document.title = 'not loaded';"));
base::string16 expected_title(base::UTF8ToUTF16("loaded"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
// Try to navigate the subframe to a blocked URL.
TestNavigationObserver load_observer2(shell()->web_contents());
GURL blocked_url = embedded_test_server()->GetURL("c.com", "/title3.html");
- EXPECT_TRUE(
- ExecuteScript(navigating_frame->current_frame_host(),
- "window.location.href = '" + blocked_url.spec() + "';"));
+ EXPECT_TRUE(ExecuteScript(navigating_frame, "window.location.href = '" +
+ blocked_url.spec() + "';"));
// The blocked frame should still fire a load event in its parent's process.
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
@@ -6537,8 +6730,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The blocked frame should keep the old title.
std::string frame_title;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- navigating_frame->current_frame_host(),
- "domAutomationController.send(document.title)", &frame_title));
+ navigating_frame, "domAutomationController.send(document.title)",
+ &frame_title));
EXPECT_EQ("Title Of Awesomeness", frame_title);
// Navigate the subframe to a URL without CSP.
@@ -6568,11 +6761,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScreenCoordinates) {
script += ");";
int root_value = 1;
int child_value = 2;
- EXPECT_TRUE(ExecuteScriptAndExtractInt(root->current_frame_host(),
- script.c_str(), &root_value));
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(root, script.c_str(), &root_value));
- EXPECT_TRUE(ExecuteScriptAndExtractInt(child->current_frame_host(),
- script.c_str(), &child_value));
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractInt(child, script.c_str(), &child_value));
EXPECT_EQ(root_value, child_value);
}
@@ -6658,7 +6850,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
b_url.spec().c_str());
TestFrameNavigationObserver frame_observer(root);
- EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
frame_observer.Wait();
EXPECT_EQ(b_url, root->current_url());
@@ -6899,8 +7091,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DetachInUnloadHandler) {
int child_count = 0;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send(frames.length);", &child_count));
+ root->child_at(0), "window.domAutomationController.send(frames.length);",
+ &child_count));
EXPECT_EQ(1, child_count);
RenderFrameDeletedObserver deleted_observer(
@@ -6909,7 +7101,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DetachInUnloadHandler) {
// Add an unload handler to the grandchild that causes it to be synchronously
// detached, then navigate it.
EXPECT_TRUE(ExecuteScript(
- root->child_at(0)->child_at(0)->current_frame_host(),
+ root->child_at(0)->child_at(0),
"window.onunload=function(e){\n"
" window.parent.document.getElementById('child-0').remove();\n"
"};\n"));
@@ -6919,14 +7111,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DetachInUnloadHandler) {
->GetURL("c.com", "/cross_site_iframe_factory.html?c")
.spec() +
"\"";
- EXPECT_TRUE(
- ExecuteScript(root->child_at(0)->current_frame_host(), script.c_str()));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), script.c_str()));
deleted_observer.WaitUntilDeleted();
EXPECT_TRUE(ExecuteScriptAndExtractInt(
- root->child_at(0)->current_frame_host(),
- "window.domAutomationController.send(frames.length);", &child_count));
+ root->child_at(0), "window.domAutomationController.send(frames.length);",
+ &child_count));
EXPECT_EQ(0, child_count);
EXPECT_EQ(
@@ -6937,4 +7128,365 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DetachInUnloadHandler) {
DepictFrameTree(root));
}
+// Helper filter class to wait for a ShowView or ShowWidget message, record the
+// routing ID from the message, and then drop the message.
+class PendingWidgetMessageFilter : public BrowserMessageFilter {
+ public:
+ PendingWidgetMessageFilter()
+ : BrowserMessageFilter(ViewMsgStart),
+ routing_id_(MSG_ROUTING_NONE),
+ message_loop_runner_(new MessageLoopRunner) {}
+
+ bool OnMessageReceived(const IPC::Message& message) override {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PendingWidgetMessageFilter, message)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShowView, OnShowView)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+ }
+
+ void Wait() {
+ message_loop_runner_->Run();
+ }
+
+ int routing_id() { return routing_id_; }
+
+ private:
+ ~PendingWidgetMessageFilter() override {}
+
+ void OnShowView(int routing_id,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_rect,
+ bool user_gesture) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&PendingWidgetMessageFilter::OnReceivedRoutingIDOnUI, this,
+ routing_id));
+ }
+
+ void OnShowWidget(int routing_id, const gfx::Rect& initial_rect) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&PendingWidgetMessageFilter::OnReceivedRoutingIDOnUI, this,
+ routing_id));
+ }
+
+ void OnReceivedRoutingIDOnUI(int routing_id) {
+ routing_id_ = routing_id;
+ message_loop_runner_->Quit();
+ }
+
+ int routing_id_;
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(PendingWidgetMessageFilter);
+};
+
+// Test for https://crbug.com/612276. Simultaneously open two new windows from
+// two subframes in different processes, where each subframe process's next
+// routing ID is the same. Make sure that both windows are created properly.
+//
+// Each new window requires two IPCs to first create it (handled by
+// CreateNewWindow) and then show it (ShowCreatedWindow). In the bug, both
+// CreateNewWindow calls arrived before the ShowCreatedWindow calls, resulting
+// in the two pending windows colliding in the pending WebContents map, which
+// used to be keyed only by routing_id.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ TwoSubframesCreatePopupsSimultaneously) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b,c)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* child1 = root->child_at(0);
+ FrameTreeNode* child2 = root->child_at(1);
+ RenderProcessHost* process1 = child1->current_frame_host()->GetProcess();
+ RenderProcessHost* process2 = child2->current_frame_host()->GetProcess();
+
+ // Call window.open simultaneously in both subframes to create two popups.
+ // Wait for and then drop both ViewHostMsg_ShowView messages. This will
+ // ensure that both CreateNewWindow calls happen before either
+ // ShowCreatedWindow call.
+ scoped_refptr<PendingWidgetMessageFilter> filter1 =
+ new PendingWidgetMessageFilter();
+ process1->AddFilter(filter1.get());
+ EXPECT_TRUE(ExecuteScript(child1, "window.open();"));
+ filter1->Wait();
+
+ scoped_refptr<PendingWidgetMessageFilter> filter2 =
+ new PendingWidgetMessageFilter();
+ process2->AddFilter(filter2.get());
+ EXPECT_TRUE(ExecuteScript(child2, "window.open();"));
+ filter2->Wait();
+
+ // At this point, we should have two pending WebContents.
+ EXPECT_TRUE(
+ ContainsKey(web_contents()->pending_contents_,
+ std::make_pair(process1->GetID(), filter1->routing_id())));
+ EXPECT_TRUE(
+ ContainsKey(web_contents()->pending_contents_,
+ std::make_pair(process2->GetID(), filter2->routing_id())));
+
+ // Both subframes were set up in the same way, so the next routing ID for the
+ // new popup windows should match up (this led to the collision in the
+ // pending contents map in the original bug).
+ EXPECT_EQ(filter1->routing_id(), filter2->routing_id());
+
+ // Now, simulate that both ShowView messages arrive by showing both of the
+ // pending WebContents.
+ web_contents()->ShowCreatedWindow(process1->GetID(), filter1->routing_id(),
+ NEW_FOREGROUND_TAB, gfx::Rect(), true);
+ web_contents()->ShowCreatedWindow(process2->GetID(), filter2->routing_id(),
+ NEW_FOREGROUND_TAB, gfx::Rect(), true);
+
+ // Verify that both shells were properly created.
+ EXPECT_EQ(3u, Shell::windows().size());
+}
+
+// Test for https://crbug.com/612276. Similar to
+// TwoSubframesOpenWindowsSimultaneously, but use popup menu widgets instead of
+// windows.
+//
+// The plumbing that this test is verifying is not utilized on Mac/Android,
+// where popup menus don't create a popup RenderWidget, but rather they trigger
+// a FrameHostMsg_ShowPopup to ask the browser to build and display the actual
+// popup using native controls.
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ TwoSubframesCreatePopupMenuWidgetsSimultaneously) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b,c)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* child1 = root->child_at(0);
+ FrameTreeNode* child2 = root->child_at(1);
+ RenderProcessHost* process1 = child1->current_frame_host()->GetProcess();
+ RenderProcessHost* process2 = child2->current_frame_host()->GetProcess();
+
+ // Navigate both subframes to a page with a <select> element.
+ NavigateFrameToURL(child1, embedded_test_server()->GetURL(
+ "b.com", "/site_isolation/page-with-select.html"));
+ NavigateFrameToURL(child2, embedded_test_server()->GetURL(
+ "c.com", "/site_isolation/page-with-select.html"));
+
+ // Open both <select> menus by focusing each item and sending a space key
+ // at the focused node. This creates a popup widget in both processes.
+ // Wait for and then drop the ViewHostMsg_ShowWidget messages, so that both
+ // widgets are left in pending-but-not-shown state.
+ NativeWebKeyboardEvent event;
+ event.text[0] = ' ';
+ event.timeStampSeconds = 100;
+ event.type = blink::WebKeyboardEvent::Char;
+
+ scoped_refptr<PendingWidgetMessageFilter> filter1 =
+ new PendingWidgetMessageFilter();
+ process1->AddFilter(filter1.get());
+ EXPECT_TRUE(ExecuteScript(child1, "focusSelectMenu();"));
+ child1->current_frame_host()->GetRenderWidgetHost()->ForwardKeyboardEvent(
+ event);
+ filter1->Wait();
+
+ scoped_refptr<PendingWidgetMessageFilter> filter2 =
+ new PendingWidgetMessageFilter();
+ process2->AddFilter(filter2.get());
+ EXPECT_TRUE(ExecuteScript(child2, "focusSelectMenu();"));
+ child2->current_frame_host()->GetRenderWidgetHost()->ForwardKeyboardEvent(
+ event);
+ filter2->Wait();
+
+ // At this point, we should have two pending widgets.
+ EXPECT_TRUE(
+ ContainsKey(web_contents()->pending_widget_views_,
+ std::make_pair(process1->GetID(), filter1->routing_id())));
+ EXPECT_TRUE(
+ ContainsKey(web_contents()->pending_widget_views_,
+ std::make_pair(process2->GetID(), filter2->routing_id())));
+
+ // Both subframes were set up in the same way, so the next routing ID for the
+ // new popup widgets should match up (this led to the collision in the
+ // pending widgets map in the original bug).
+ EXPECT_EQ(filter1->routing_id(), filter2->routing_id());
+
+ // Now simulate both widgets being shown.
+ web_contents()->ShowCreatedWidget(process1->GetID(), filter1->routing_id(),
+ false, gfx::Rect());
+ web_contents()->ShowCreatedWidget(process2->GetID(), filter2->routing_id(),
+ false, gfx::Rect());
+ EXPECT_FALSE(
+ ContainsKey(web_contents()->pending_widget_views_,
+ std::make_pair(process1->GetID(), filter1->routing_id())));
+ EXPECT_FALSE(
+ ContainsKey(web_contents()->pending_widget_views_,
+ std::make_pair(process2->GetID(), filter2->routing_id())));
+}
+#endif
+
+// Check that out-of-process frames correctly calculate their ability to enter
+// fullscreen. A frame is allowed enter fullscreen if the allowFullscreen
+// attribute is present in all of its ancestor <iframe> elements. For OOPIF,
+// when a parent frame changes this attribute, the change is replicated to the
+// child frame and its proxies.
+//
+// The test checks the following cases:
+//
+// 1. Static attribute (<iframe allowfullscreen>)
+// 2. Attribute injected dynamically via JavaScript
+// 3. Multiple levels of nesting (A-embed-B-embed-C)
+// 4. Cross-site subframe navigation
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, AllowFullscreen) {
+ // Load a page with a cross-site <iframe allowFullscreen>.
+ GURL url_1(embedded_test_server()->GetURL(
+ "a.com", "/page_with_allowfullscreen_frame.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url_1));
+
+ WebContentsImpl* contents = web_contents();
+ FrameTreeNode* root = contents->GetFrameTree()->root();
+
+ // Helper to check if a frame is allowed to go fullscreen on the renderer
+ // side.
+ auto is_fullscreen_allowed = [](FrameTreeNode* ftn) {
+ bool fullscreen_allowed = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ ftn,
+ "window.domAutomationController.send(document.webkitFullscreenEnabled)",
+ &fullscreen_allowed));
+ return fullscreen_allowed;
+ };
+
+ EXPECT_TRUE(is_fullscreen_allowed(root));
+ EXPECT_TRUE(is_fullscreen_allowed(root->child_at(0)));
+ EXPECT_TRUE(root->child_at(0)->frame_owner_properties().allowFullscreen);
+
+ // Now navigate to a page with two <iframe>'s, both without allowFullscreen.
+ GURL url_2(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b,c)"));
+ EXPECT_TRUE(NavigateToURL(shell(), url_2));
+ EXPECT_FALSE(root->child_at(0)->frame_owner_properties().allowFullscreen);
+ EXPECT_FALSE(root->child_at(1)->frame_owner_properties().allowFullscreen);
+
+ EXPECT_TRUE(is_fullscreen_allowed(root));
+ EXPECT_FALSE(is_fullscreen_allowed(root->child_at(0)));
+ EXPECT_FALSE(is_fullscreen_allowed(root->child_at(1)));
+
+ // Dynamically enable fullscreen for first subframe and check that the
+ // fullscreen property was updated on the FrameTreeNode.
+ EXPECT_TRUE(ExecuteScript(
+ root, "document.getElementById('child-0').allowFullscreen='true'"));
+ EXPECT_TRUE(root->child_at(0)->frame_owner_properties().allowFullscreen);
+
+ // Check that the first subframe is now allowed to go fullscreen. Other
+ // frames shouldn't be affected.
+ EXPECT_TRUE(is_fullscreen_allowed(root));
+ EXPECT_TRUE(is_fullscreen_allowed(root->child_at(0)));
+ EXPECT_FALSE(is_fullscreen_allowed(root->child_at(1)));
+
+ // Now navigate to a page with two levels of nesting.
+ GURL url_3(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c))"));
+ EXPECT_TRUE(NavigateToURL(shell(), url_3));
+
+ EXPECT_TRUE(is_fullscreen_allowed(root));
+ EXPECT_FALSE(is_fullscreen_allowed(root->child_at(0)));
+ EXPECT_FALSE(is_fullscreen_allowed(root->child_at(0)->child_at(0)));
+
+ // Dynamically enable fullscreen for bottom subframe.
+ EXPECT_TRUE(ExecuteScript(
+ root->child_at(0),
+ "document.getElementById('child-0').allowFullscreen='true'"));
+
+ // This still shouldn't allow the bottom child to go fullscreen, since the
+ // top frame hasn't allowed fullscreen for the middle frame.
+ EXPECT_TRUE(is_fullscreen_allowed(root));
+ EXPECT_FALSE(is_fullscreen_allowed(root->child_at(0)));
+ EXPECT_FALSE(is_fullscreen_allowed(root->child_at(0)->child_at(0)));
+
+ // Now allow fullscreen for the middle frame.
+ EXPECT_TRUE(ExecuteScript(
+ root, "document.getElementById('child-0').allowFullscreen='true'"));
+
+ // All frames should be allowed to go fullscreen now.
+ EXPECT_TRUE(is_fullscreen_allowed(root));
+ EXPECT_TRUE(is_fullscreen_allowed(root->child_at(0)));
+ EXPECT_TRUE(is_fullscreen_allowed(root->child_at(0)->child_at(0)));
+
+ // Cross-site navigation should preserve the fullscreen flags.
+ NavigateFrameToURL(root->child_at(0)->child_at(0),
+ embedded_test_server()->GetURL("d.com", "/title1.html"));
+ EXPECT_TRUE(is_fullscreen_allowed(root->child_at(0)->child_at(0)));
+}
+
+// Test for https://crbug.com/615575. It ensures that file chooser triggered
+// by a document in an out-of-process subframe works properly.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FileChooserInSubframe) {
+ EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)")));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ GURL url(embedded_test_server()->GetURL("b.com", "/file_input.html"));
+ NavigateFrameToURL(root->child_at(0), url);
+
+ // Use FileChooserDelegate to avoid showing the actual dialog and to respond
+ // back to the renderer process with predefined file.
+ base::FilePath file;
+ EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
+ file = file.AppendASCII("bar");
+ std::unique_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file));
+ shell()->web_contents()->SetDelegate(delegate.get());
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
+ "document.getElementById('fileinput').click();"));
+ EXPECT_TRUE(delegate->file_chosen());
+
+ // Also, extract the file from the renderer process to ensure that the
+ // response made it over successfully and the proper filename is set.
+ std::string file_name;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ root->child_at(0),
+ "window.domAutomationController.send("
+ "document.getElementById('fileinput').files[0].name);",
+ &file_name));
+ EXPECT_EQ("bar", file_name);
+}
+
+// Tests that an out-of-process iframe receives the visibilitychange event.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, VisibilityChange) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ NavigateToURL(shell(), main_url);
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/",
+ DepictFrameTree(root));
+
+ EXPECT_TRUE(ExecuteScript(
+ root->child_at(0)->current_frame_host(),
+ "var event_fired = 0;\n"
+ "document.addEventListener('visibilitychange',\n"
+ " function() { event_fired++; });\n"));
+
+ shell()->web_contents()->WasHidden();
+
+ int event_fired = 0;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(
+ root->child_at(0)->current_frame_host(),
+ "window.domAutomationController.send(event_fired);", &event_fired));
+ EXPECT_EQ(1, event_fired);
+
+ shell()->web_contents()->WasShown();
+
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(
+ root->child_at(0)->current_frame_host(),
+ "window.domAutomationController.send(event_fired);", &event_fired));
+ EXPECT_EQ(2, event_fired);
+}
+
} // namespace content
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index d8bfdc9fe6f..0bc6261453c 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -48,7 +48,7 @@ class SpeechRecognizerImpl::OnDataConverter
private:
// media::AudioConverter::InputCallback implementation.
- double ProvideInput(AudioBus* dest, base::TimeDelta buffer_delay) override;
+ double ProvideInput(AudioBus* dest, uint32_t frames_delayed) override;
// Handles resampling, buffering, and channel mixing between input and output
// parameters.
@@ -160,7 +160,8 @@ scoped_refptr<AudioChunk> SpeechRecognizerImpl::OnDataConverter::Convert(
}
double SpeechRecognizerImpl::OnDataConverter::ProvideInput(
- AudioBus* dest, base::TimeDelta buffer_delay) {
+ AudioBus* dest,
+ uint32_t frames_delayed) {
// Read from the input bus to feed the converter.
input_bus_->CopyTo(dest);
// Indicate that the recorded audio has in fact been used by the converter.
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
index 6135e4a4874..62eae10247a 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -7,7 +7,9 @@
#include <vector>
+#include "base/run_loop.h"
#include "base/sys_byteorder.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/speech/proto/google_streaming_api.pb.h"
#include "content/browser/speech/speech_recognition_engine.h"
#include "content/browser/speech/speech_recognizer_impl.h"
@@ -59,8 +61,8 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
const int kTestingSessionId = 1;
recognizer_ = new SpeechRecognizerImpl(
this, kTestingSessionId, false, false, sr_engine);
- audio_manager_.reset(new media::MockAudioManager(
- base::MessageLoop::current()->task_runner().get()));
+ audio_manager_.reset(
+ new media::MockAudioManager(base::ThreadTaskRunnerHandle::Get().get()));
recognizer_->SetAudioManagerForTesting(audio_manager_.get());
int audio_packet_length_bytes =
@@ -207,7 +209,7 @@ TEST_F(SpeechRecognizerImplTest, StopNoData) {
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
recognizer_->StopAudioCapture();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
@@ -221,7 +223,7 @@ TEST_F(SpeechRecognizerImplTest, CancelNoData) {
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
recognizer_->AbortRecognition();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
@@ -234,7 +236,7 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) {
// network callback to arrive before completion.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
ASSERT_TRUE(controller);
@@ -246,14 +248,14 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) {
const size_t kNumChunks = 5;
for (size_t i = 0; i < kNumChunks; ++i) {
controller->event_handler()->OnData(controller, audio_bus_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
ASSERT_TRUE(fetcher);
EXPECT_EQ(i + 1, fetcher->upload_chunks().size());
}
recognizer_->StopAudioCapture();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(audio_started_);
EXPECT_TRUE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
@@ -285,7 +287,7 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) {
fetcher->SetResponseString(msg_string);
fetcher->delegate()->OnURLFetchComplete(fetcher);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_ended_);
EXPECT_TRUE(result_received_);
EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
@@ -296,14 +298,14 @@ TEST_F(SpeechRecognizerImplTest, CancelWithData) {
// Start recording, give some data and then cancel.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
ASSERT_TRUE(controller);
controller->event_handler()->OnData(controller, audio_bus_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
recognizer_->AbortRecognition();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0));
EXPECT_TRUE(recognition_started_);
EXPECT_TRUE(audio_started_);
@@ -317,17 +319,17 @@ TEST_F(SpeechRecognizerImplTest, ConnectionError) {
// with a connection error and verify that the recognizer bubbles the error up
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
ASSERT_TRUE(controller);
controller->event_handler()->OnData(controller, audio_bus_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
ASSERT_TRUE(fetcher);
recognizer_->StopAudioCapture();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(audio_started_);
EXPECT_TRUE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
@@ -341,7 +343,7 @@ TEST_F(SpeechRecognizerImplTest, ConnectionError) {
fetcher->set_response_code(0);
fetcher->SetResponseString(std::string());
fetcher->delegate()->OnURLFetchComplete(fetcher);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_ended_);
EXPECT_FALSE(result_received_);
EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_);
@@ -353,17 +355,17 @@ TEST_F(SpeechRecognizerImplTest, ServerError) {
// with a 500 error and verify that the recognizer bubbles the error up
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
ASSERT_TRUE(controller);
controller->event_handler()->OnData(controller, audio_bus_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
ASSERT_TRUE(fetcher);
recognizer_->StopAudioCapture();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(audio_started_);
EXPECT_TRUE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
@@ -376,7 +378,7 @@ TEST_F(SpeechRecognizerImplTest, ServerError) {
fetcher->set_response_code(500);
fetcher->SetResponseString("Internal Server Error");
fetcher->delegate()->OnURLFetchComplete(fetcher);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_ended_);
EXPECT_FALSE(result_received_);
EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_);
@@ -387,13 +389,13 @@ TEST_F(SpeechRecognizerImplTest, AudioControllerErrorNoData) {
// Check if things tear down properly if AudioInputController threw an error.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
ASSERT_TRUE(controller);
controller->event_handler()->OnError(controller,
AudioInputController::UNKNOWN_ERROR);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
@@ -406,14 +408,14 @@ TEST_F(SpeechRecognizerImplTest, AudioControllerErrorWithData) {
// after giving some audio data.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
ASSERT_TRUE(controller);
controller->event_handler()->OnData(controller, audio_bus_.get());
controller->event_handler()->OnError(controller,
AudioInputController::UNKNOWN_ERROR);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0));
EXPECT_TRUE(recognition_started_);
EXPECT_TRUE(audio_started_);
@@ -427,7 +429,7 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackIssued) {
// This should trigger the no-speech detector and issue a callback.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
ASSERT_TRUE(controller);
@@ -438,7 +440,7 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackIssued) {
for (int i = 0; i < num_packets; ++i) {
controller->event_handler()->OnData(controller, audio_bus_.get());
}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_started_);
EXPECT_TRUE(audio_started_);
EXPECT_FALSE(result_received_);
@@ -453,7 +455,7 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackNotIssued) {
// triggered.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
ASSERT_TRUE(controller);
@@ -473,13 +475,13 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackNotIssued) {
controller->event_handler()->OnData(controller, audio_bus_.get());
}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
EXPECT_TRUE(audio_started_);
EXPECT_FALSE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
recognizer_->AbortRecognition();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
CheckFinalEventsConsistency();
}
@@ -490,7 +492,7 @@ TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) {
// samples and proper volume for the loud audio.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
TestAudioInputController* controller =
audio_input_controller_factory_.controller();
ASSERT_TRUE(controller);
@@ -504,17 +506,17 @@ TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) {
for (int i = 0; i < num_packets; ++i) {
controller->event_handler()->OnData(controller, audio_bus_.get());
}
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(-1.0f, volume_); // No audio volume set yet.
// The vector is already filled with zero value samples on create.
controller->event_handler()->OnData(controller, audio_bus_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FLOAT_EQ(0.74939233f, volume_);
FillPacketWithTestWaveform();
controller->event_handler()->OnData(controller, audio_bus_.get());
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_NEAR(0.89926866f, volume_, 0.00001f);
EXPECT_FLOAT_EQ(0.75071919f, noise_volume_);
@@ -522,7 +524,7 @@ TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) {
EXPECT_FALSE(audio_ended_);
EXPECT_FALSE(recognition_ended_);
recognizer_->AbortRecognition();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
CheckFinalEventsConsistency();
}
diff --git a/chromium/content/browser/ssl/ssl_policy.cc b/chromium/content/browser/ssl/ssl_policy.cc
index 06677dc25e9..e710e7c39ac 100644
--- a/chromium/content/browser/ssl/ssl_policy.cc
+++ b/chromium/content/browser/ssl/ssl_policy.cc
@@ -69,6 +69,7 @@ void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
case net::ERR_CERT_WEAK_KEY:
case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION:
case net::ERR_CERT_VALIDITY_TOO_LONG:
+ case net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED:
if (!handler->fatal())
options_mask |= OVERRIDABLE;
else
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index 14cd612065d..1ef698f0f86 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -35,6 +35,10 @@
#include "storage/browser/database/database_tracker.h"
#include "storage/browser/quota/quota_manager.h"
+#if defined(ENABLE_PLUGINS)
+#include "content/browser/plugin_private_storage_helper.h"
+#endif // defined(ENABLE_PLUGINS)
+
namespace content {
namespace {
@@ -315,6 +319,7 @@ struct StoragePartitionImpl::DataDeletionHelper {
storage::QuotaManager* quota_manager,
storage::SpecialStoragePolicy* special_storage_policy,
WebRTCIdentityStore* webrtc_identity_store,
+ storage::FileSystemContext* filesystem_context,
const base::Time begin,
const base::Time end);
@@ -370,7 +375,9 @@ StoragePartitionImpl::StoragePartitionImpl(
storage::SpecialStoragePolicy* special_storage_policy,
HostZoomLevelContext* host_zoom_level_context,
PlatformNotificationContextImpl* platform_notification_context,
- BackgroundSyncContext* background_sync_context)
+ BackgroundSyncContext* background_sync_context,
+ scoped_refptr<webmessaging::BroadcastChannelProvider>
+ broadcast_channel_provider)
: partition_path_(partition_path),
quota_manager_(quota_manager),
appcache_service_(appcache_service),
@@ -385,8 +392,8 @@ StoragePartitionImpl::StoragePartitionImpl(
host_zoom_level_context_(host_zoom_level_context),
platform_notification_context_(platform_notification_context),
background_sync_context_(background_sync_context),
- browser_context_(browser_context) {
-}
+ broadcast_channel_provider_(std::move(broadcast_channel_provider)),
+ browser_context_(browser_context) {}
StoragePartitionImpl::~StoragePartitionImpl() {
browser_context_ = nullptr;
@@ -459,7 +466,7 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
scoped_refptr<DOMStorageContextWrapper> dom_storage_context =
new DOMStorageContextWrapper(
- BrowserContext::GetMojoConnectorFor(context),
+ BrowserContext::GetShellConnectorFor(context),
in_memory ? base::FilePath() : context->GetPath(),
relative_partition_path, context->GetSpecialStoragePolicy());
@@ -512,6 +519,9 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
new BackgroundSyncContext();
background_sync_context->Init(service_worker_context);
+ scoped_refptr<webmessaging::BroadcastChannelProvider>
+ broadcast_channel_provider = new webmessaging::BroadcastChannelProvider();
+
StoragePartitionImpl* storage_partition = new StoragePartitionImpl(
context, partition_path, quota_manager.get(), appcache_service.get(),
filesystem_context.get(), database_tracker.get(),
@@ -519,7 +529,7 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
cache_storage_context.get(), service_worker_context.get(),
webrtc_identity_store.get(), special_storage_policy.get(),
host_zoom_level_context.get(), platform_notification_context.get(),
- background_sync_context.get());
+ background_sync_context.get(), std::move(broadcast_channel_provider));
service_worker_context->set_storage_partition(storage_partition);
@@ -594,6 +604,11 @@ BackgroundSyncContext* StoragePartitionImpl::GetBackgroundSyncContext() {
return background_sync_context_.get();
}
+webmessaging::BroadcastChannelProvider*
+StoragePartitionImpl::GetBroadcastChannelProvider() {
+ return broadcast_channel_provider_.get();
+}
+
void StoragePartitionImpl::OpenLocalStorage(
const url::Origin& origin,
mojom::LevelDBObserverPtr observer,
@@ -621,7 +636,8 @@ void StoragePartitionImpl::ClearDataImpl(
helper->ClearDataOnUIThread(
storage_origin, origin_matcher, cookie_matcher, GetPath(), rq_context,
dom_storage_context_.get(), quota_manager_.get(),
- special_storage_policy_.get(), webrtc_identity_store_.get(), begin, end);
+ special_storage_policy_.get(), webrtc_identity_store_.get(),
+ filesystem_context_.get(), begin, end);
}
void StoragePartitionImpl::
@@ -761,6 +777,7 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
storage::QuotaManager* quota_manager,
storage::SpecialStoragePolicy* special_storage_policy,
WebRTCIdentityStore* webrtc_identity_store,
+ storage::FileSystemContext* filesystem_context,
const base::Time begin,
const base::Time end) {
DCHECK_NE(remove_mask, 0u);
@@ -841,6 +858,16 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
decrement_callback));
}
+#if defined(ENABLE_PLUGINS)
+ if (remove_mask & REMOVE_DATA_MASK_PLUGIN_PRIVATE_DATA) {
+ IncrementTaskCountOnUI();
+ filesystem_context->default_file_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&ClearPluginPrivateDataOnFileTaskRunner,
+ make_scoped_refptr(filesystem_context),
+ storage_origin, begin, end, decrement_callback));
+ }
+#endif // defined(ENABLE_PLUGINS)
+
DecrementTaskCountOnUI();
}
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index 99f9a34a386..7e53766e420 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -12,6 +12,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "components/webmessaging/broadcast_channel_provider.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/background_sync/background_sync_context.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
@@ -69,6 +70,7 @@ class CONTENT_EXPORT StoragePartitionImpl
PlatformNotificationContextImpl* GetPlatformNotificationContext() override;
BackgroundSyncContext* GetBackgroundSyncContext();
+ webmessaging::BroadcastChannelProvider* GetBroadcastChannelProvider();
// mojom::StoragePartitionService interface.
void OpenLocalStorage(
@@ -173,7 +175,9 @@ class CONTENT_EXPORT StoragePartitionImpl
storage::SpecialStoragePolicy* special_storage_policy,
HostZoomLevelContext* host_zoom_level_context,
PlatformNotificationContextImpl* platform_notification_context,
- BackgroundSyncContext* background_sync_context);
+ BackgroundSyncContext* background_sync_context,
+ scoped_refptr<webmessaging::BroadcastChannelProvider>
+ broadcast_channel_provider);
// We will never have both remove_origin be populated and a cookie_matcher.
void ClearDataImpl(uint32_t remove_mask,
@@ -219,6 +223,8 @@ 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<webmessaging::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 6aa0c1b0877..a50428018c1 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_unittest.cc
@@ -30,6 +30,15 @@
#include "storage/browser/quota/quota_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(ENABLE_PLUGINS)
+#include "ppapi/shared_impl/ppapi_constants.h"
+#include "storage/browser/fileapi/async_file_util.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/common/fileapi/file_system_util.h"
+#endif // defined(ENABLE_PLUGINS)
+
using net::CanonicalCookie;
namespace content {
@@ -44,6 +53,11 @@ const char kTestOrigin2[] = "http://host2:1/";
const char kTestOrigin3[] = "http://host3:1/";
const char kTestOriginDevTools[] = "chrome-devtools://abcdefghijklmnopqrstuvw/";
+#if defined(ENABLE_PLUGINS)
+const char kWidevineCdmPluginId[] = "application_x-ppapi-widevine-cdm";
+const char kClearKeyCdmPluginId[] = "application_x-ppapi-clearkey-cdm";
+#endif // defined(ENABLE_PLUGINS)
+
const GURL kOrigin1(kTestOrigin1);
const GURL kOrigin2(kTestOrigin2);
const GURL kOrigin3(kTestOrigin3);
@@ -231,6 +245,199 @@ class RemoveLocalStorageTester {
DISALLOW_COPY_AND_ASSIGN(RemoveLocalStorageTester);
};
+#if defined(ENABLE_PLUGINS)
+class RemovePluginPrivateDataTester {
+ public:
+ explicit RemovePluginPrivateDataTester(
+ storage::FileSystemContext* filesystem_context)
+ : filesystem_context_(filesystem_context) {}
+
+ // Add some files to the PluginPrivateFileSystem. They are created as follows:
+ // kOrigin1 - ClearKey - 1 file - timestamp 10 days ago
+ // kOrigin2 - Widevine - 2 files - timestamps now and 60 days ago
+ void AddPluginPrivateTestData() {
+ base::Time now = base::Time::Now();
+ base::Time ten_days_ago = now - base::TimeDelta::FromDays(10);
+ base::Time sixty_days_ago = now - base::TimeDelta::FromDays(60);
+
+ // Create a PluginPrivateFileSystem for ClearKey and add a single file
+ // with a timestamp of 1 day ago.
+ std::string clearkey_fsid =
+ CreateFileSystem(kClearKeyCdmPluginId, kOrigin1);
+ clearkey_file_ = CreateFile(kOrigin1, clearkey_fsid, "foo");
+ SetFileTimestamp(clearkey_file_, ten_days_ago);
+
+ // Create a second PluginPrivateFileSystem for Widevine and add two files
+ // with different times.
+ std::string widevine_fsid =
+ CreateFileSystem(kWidevineCdmPluginId, kOrigin2);
+ storage::FileSystemURL widevine_file1 =
+ CreateFile(kOrigin2, widevine_fsid, "bar1");
+ storage::FileSystemURL widevine_file2 =
+ CreateFile(kOrigin2, widevine_fsid, "bar2");
+ SetFileTimestamp(widevine_file1, now);
+ SetFileTimestamp(widevine_file2, sixty_days_ago);
+ }
+
+ // Returns true, if the given origin exists in a PluginPrivateFileSystem.
+ bool DataExistsForOrigin(const GURL& origin) {
+ AwaitCompletionHelper await_completion;
+ bool data_exists_for_origin = false;
+ filesystem_context_->default_file_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&RemovePluginPrivateDataTester::
+ CheckIfDataExistsForOriginOnFileTaskRunner,
+ base::Unretained(this), origin,
+ &data_exists_for_origin, &await_completion));
+ await_completion.BlockUntilNotified();
+ return data_exists_for_origin;
+ }
+
+ // Opens the file created for ClearKey (in kOrigin1) for writing. Caller
+ // needs to verify if the file was opened or not.
+ base::File OpenClearKeyFileForWrite() {
+ AwaitCompletionHelper await_completion;
+ base::File file;
+ storage::AsyncFileUtil* async_file_util =
+ filesystem_context_->GetAsyncFileUtil(
+ storage::kFileSystemTypePluginPrivate);
+ std::unique_ptr<storage::FileSystemOperationContext> operation_context =
+ base::WrapUnique(
+ new storage::FileSystemOperationContext(filesystem_context_));
+ async_file_util->CreateOrOpen(
+ std::move(operation_context), clearkey_file_,
+ base::File::FLAG_OPEN | base::File::FLAG_WRITE,
+ base::Bind(&RemovePluginPrivateDataTester::OnFileOpened,
+ base::Unretained(this), &file, &await_completion));
+ await_completion.BlockUntilNotified();
+ return file;
+ }
+
+ private:
+ // Creates a PluginPrivateFileSystem for the |plugin_name| and |origin|
+ // provided. Returns the file system ID for the created
+ // PluginPrivateFileSystem.
+ std::string CreateFileSystem(const std::string& plugin_name,
+ const GURL& origin) {
+ AwaitCompletionHelper await_completion;
+ std::string fsid = storage::IsolatedContext::GetInstance()
+ ->RegisterFileSystemForVirtualPath(
+ storage::kFileSystemTypePluginPrivate,
+ ppapi::kPluginPrivateRootName, base::FilePath());
+ EXPECT_TRUE(storage::ValidateIsolatedFileSystemId(fsid));
+ filesystem_context_->OpenPluginPrivateFileSystem(
+ origin, storage::kFileSystemTypePluginPrivate, fsid, plugin_name,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&RemovePluginPrivateDataTester::OnFileSystemOpened,
+ base::Unretained(this), &await_completion));
+ await_completion.BlockUntilNotified();
+ return fsid;
+ }
+
+ // Creates a file named |file_name| in the PluginPrivateFileSystem identified
+ // by |origin| and |fsid|. Returns the URL for the created file. The file
+ // must not already exist or the test will fail.
+ storage::FileSystemURL CreateFile(const GURL& origin,
+ const std::string& fsid,
+ const std::string& file_name) {
+ AwaitCompletionHelper await_completion;
+ std::string root = storage::GetIsolatedFileSystemRootURIString(
+ origin, fsid, ppapi::kPluginPrivateRootName);
+ storage::FileSystemURL file_url =
+ filesystem_context_->CrackURL(GURL(root + file_name));
+ storage::AsyncFileUtil* file_util = filesystem_context_->GetAsyncFileUtil(
+ storage::kFileSystemTypePluginPrivate);
+ std::unique_ptr<storage::FileSystemOperationContext> operation_context =
+ base::WrapUnique(
+ new storage::FileSystemOperationContext(filesystem_context_));
+ operation_context->set_allowed_bytes_growth(
+ storage::QuotaManager::kNoLimit);
+ file_util->EnsureFileExists(
+ std::move(operation_context), file_url,
+ base::Bind(&RemovePluginPrivateDataTester::OnFileCreated,
+ base::Unretained(this), &await_completion));
+ await_completion.BlockUntilNotified();
+ return file_url;
+ }
+
+ // Sets the last_access_time and last_modified_time to |time_stamp| on the
+ // file specified by |file_url|. The file must already exist.
+ void SetFileTimestamp(const storage::FileSystemURL& file_url,
+ const base::Time& time_stamp) {
+ AwaitCompletionHelper await_completion;
+ storage::AsyncFileUtil* file_util = filesystem_context_->GetAsyncFileUtil(
+ storage::kFileSystemTypePluginPrivate);
+ std::unique_ptr<storage::FileSystemOperationContext> operation_context =
+ base::WrapUnique(
+ new storage::FileSystemOperationContext(filesystem_context_));
+ file_util->Touch(std::move(operation_context), file_url, time_stamp,
+ time_stamp,
+ base::Bind(&RemovePluginPrivateDataTester::OnFileTouched,
+ base::Unretained(this), &await_completion));
+ await_completion.BlockUntilNotified();
+ }
+
+ void OnFileSystemOpened(AwaitCompletionHelper* await_completion,
+ base::File::Error result) {
+ EXPECT_EQ(base::File::FILE_OK, result) << base::File::ErrorToString(result);
+ await_completion->Notify();
+ }
+
+ void OnFileCreated(AwaitCompletionHelper* await_completion,
+ base::File::Error result,
+ bool created) {
+ EXPECT_EQ(base::File::FILE_OK, result) << base::File::ErrorToString(result);
+ EXPECT_TRUE(created);
+ await_completion->Notify();
+ }
+
+ void OnFileTouched(AwaitCompletionHelper* await_completion,
+ base::File::Error result) {
+ EXPECT_EQ(base::File::FILE_OK, result) << base::File::ErrorToString(result);
+ await_completion->Notify();
+ }
+
+ void OnFileOpened(base::File* file_result,
+ AwaitCompletionHelper* await_completion,
+ base::File file,
+ const base::Closure& on_close_callback) {
+ *file_result = std::move(file);
+ await_completion->Notify();
+ }
+
+ // If |origin| exists in the PluginPrivateFileSystem, set
+ // |data_exists_for_origin| to true, false otherwise.
+ void CheckIfDataExistsForOriginOnFileTaskRunner(
+ const GURL& origin,
+ bool* data_exists_for_origin,
+ AwaitCompletionHelper* await_completion) {
+ storage::FileSystemBackend* backend =
+ filesystem_context_->GetFileSystemBackend(
+ storage::kFileSystemTypePluginPrivate);
+ storage::FileSystemQuotaUtil* quota_util = backend->GetQuotaUtil();
+
+ // Determine the set of origins used.
+ std::set<GURL> origins;
+ quota_util->GetOriginsForTypeOnFileTaskRunner(
+ storage::kFileSystemTypePluginPrivate, &origins);
+ *data_exists_for_origin = origins.find(origin) != origins.end();
+
+ // AwaitCompletionHelper and MessageLoop don't work on a
+ // SequencedTaskRunner, so post a task on the IO thread.
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&AwaitCompletionHelper::Notify,
+ base::Unretained(await_completion)));
+ }
+
+ // We don't own this pointer.
+ storage::FileSystemContext* filesystem_context_;
+
+ // Keep track of the URL for the ClearKey file so that it can be written to.
+ storage::FileSystemURL clearkey_file_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemovePluginPrivateDataTester);
+};
+#endif // defined(ENABLE_PLUGINS)
+
bool IsWebSafeSchemeForTest(const std::string& scheme) {
return scheme == "http";
}
@@ -344,14 +551,27 @@ void ClearData(content::StoragePartition* partition,
time, time, run_loop->QuitClosure());
}
+#if defined(ENABLE_PLUGINS)
+void ClearPluginPrivateData(content::StoragePartition* partition,
+ const GURL& storage_origin,
+ const base::Time delete_begin,
+ const base::Time delete_end,
+ base::RunLoop* run_loop) {
+ partition->ClearData(
+ StoragePartitionImpl::REMOVE_DATA_MASK_PLUGIN_PRIVATE_DATA,
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, storage_origin,
+ StoragePartition::OriginMatcherFunction(), delete_begin, delete_end,
+ run_loop->QuitClosure());
+}
+#endif // defined(ENABLE_PLUGINS)
+
} // namespace
class StoragePartitionImplTest : public testing::Test {
public:
StoragePartitionImplTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
- browser_context_(new TestBrowserContext()) {
- }
+ browser_context_(new TestBrowserContext()) {}
MockQuotaManager* GetMockManager() {
if (!quota_manager_.get()) {
@@ -975,6 +1195,102 @@ TEST_F(StoragePartitionImplTest, RemoveLocalStorageForLastWeek) {
EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin3));
}
+#if defined(ENABLE_PLUGINS)
+TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataForever) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+
+ RemovePluginPrivateDataTester tester(partition->GetFileSystemContext());
+ tester.AddPluginPrivateTestData();
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1));
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2));
+
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&ClearPluginPrivateData, partition, GURL(),
+ base::Time(), base::Time::Max(), &run_loop));
+ run_loop.Run();
+
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin1));
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin2));
+}
+
+TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataLastWeek) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+ base::Time a_week_ago = base::Time::Now() - base::TimeDelta::FromDays(7);
+
+ RemovePluginPrivateDataTester tester(partition->GetFileSystemContext());
+ tester.AddPluginPrivateTestData();
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1));
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2));
+
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&ClearPluginPrivateData, partition, GURL(),
+ a_week_ago, base::Time::Max(), &run_loop));
+ run_loop.Run();
+
+ // Origin1 has 1 file from 10 days ago, so it should remain around.
+ // Origin2 has a current file, so it should be removed (even though the
+ // second file is much older).
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1));
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin2));
+}
+
+TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataForOrigin) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+
+ RemovePluginPrivateDataTester tester(partition->GetFileSystemContext());
+ tester.AddPluginPrivateTestData();
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1));
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2));
+
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&ClearPluginPrivateData, partition, kOrigin1,
+ base::Time(), base::Time::Max(), &run_loop));
+ run_loop.Run();
+
+ // Only Origin1 should be deleted.
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin1));
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2));
+}
+
+TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataWhileWriting) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+
+ RemovePluginPrivateDataTester tester(partition->GetFileSystemContext());
+ tester.AddPluginPrivateTestData();
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1));
+ EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2));
+
+ const char test_data[] = {0, 1, 2, 3, 4, 5};
+ base::File file = tester.OpenClearKeyFileForWrite();
+ EXPECT_TRUE(file.IsValid());
+ EXPECT_EQ(static_cast<int>(arraysize(test_data)),
+ file.Write(0, test_data, arraysize(test_data)));
+
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&ClearPluginPrivateData, partition, GURL(),
+ base::Time(), base::Time::Max(), &run_loop));
+ run_loop.Run();
+
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin1));
+ EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin2));
+
+ const char more_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ EXPECT_EQ(static_cast<int>(arraysize(more_data)),
+ file.WriteAtCurrentPos(more_data, arraysize(more_data)));
+
+ base::File file2 = tester.OpenClearKeyFileForWrite();
+ EXPECT_FALSE(file2.IsValid());
+}
+#endif // defined(ENABLE_PLUGINS)
+
TEST(StoragePartitionImplStaticTest, CreatePredicateForHostCookies) {
GURL url("http://www.example.com/");
GURL url2("https://www.example.com/");
diff --git a/chromium/content/browser/streams/stream_unittest.cc b/chromium/content/browser/streams/stream_unittest.cc
index 2da9a36cd05..f57e678c1f5 100644
--- a/chromium/content/browser/streams/stream_unittest.cc
+++ b/chromium/content/browser/streams/stream_unittest.cc
@@ -5,6 +5,7 @@
#include <stddef.h>
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_read_observer.h"
@@ -195,7 +196,7 @@ TEST_F(StreamTest, Stream) {
scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize));
writer.Write(stream.get(), buffer, kBufferSize);
stream->Finalize();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(reader.completed());
ASSERT_EQ(reader.buffer()->capacity(), kBufferSize);
@@ -222,7 +223,7 @@ TEST_F(StreamTest, ClosedReaderDoesNotReturnStreamEmpty) {
scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize));
stream->AddData(buffer, kBufferSize);
stream->Finalize();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(reader.completed());
EXPECT_EQ(0, reader.buffer()->capacity());
}
@@ -308,7 +309,7 @@ TEST_F(StreamTest, MemoryExceedMemoryUsageLimit) {
scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize));
writer1.Write(stream1.get(), buffer, kBufferSize);
// Make transfer happen.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
writer2.Write(stream2.get(), buffer, kBufferSize);
@@ -337,7 +338,7 @@ TEST_F(StreamTest, UnderMemoryUsageLimit) {
writer.Write(stream.get(), buffer, kBufferSize);
// Run loop to make |reader| consume the data.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
writer.Write(stream.get(), buffer, kBufferSize);
@@ -360,13 +361,13 @@ TEST_F(StreamTest, Flush) {
writer.Write(stream.get(), buffer, kBufferSize);
// Run loop to make |reader| consume the data.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, reader.buffer()->capacity());
stream->Flush();
// Run loop to make |reader| consume the data.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(kBufferSize, reader.buffer()->capacity());
EXPECT_EQ(stream.get(), registry_->GetStream(url).get());
diff --git a/chromium/content/browser/streams/stream_url_request_job_unittest.cc b/chromium/content/browser/streams/stream_url_request_job_unittest.cc
index 0b09689e8e3..6c445625264 100644
--- a/chromium/content/browser/streams/stream_url_request_job_unittest.cc
+++ b/chromium/content/browser/streams/stream_url_request_job_unittest.cc
@@ -6,6 +6,7 @@
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_registry.h"
@@ -83,7 +84,7 @@ class StreamURLRequestJobTest : public testing::Test {
request_->SetExtraRequestHeaders(extra_headers);
request_->Start();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Verify response.
EXPECT_TRUE(request_->status().is_success());
@@ -139,7 +140,7 @@ TEST_F(StreamURLRequestJobTest, TestGetNonExistentStreamRequest) {
request_->set_method("GET");
request_->Start();
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Verify response.
EXPECT_FALSE(request_->status().is_success());
diff --git a/chromium/content/browser/theme_helper_mac.mm b/chromium/content/browser/theme_helper_mac.mm
index 7cc95a70aaf..8499fd4271a 100644
--- a/chromium/content/browser/theme_helper_mac.mm
+++ b/chromium/content/browser/theme_helper_mac.mm
@@ -96,20 +96,11 @@ ViewMsg_SystemColorsChanged* CreateSystemColorsChangedMessage() {
object:nil
suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
- if (base::mac::IsOSMountainLionOrLater()) {
- [distributedCenter addObserver:self
- selector:@selector(behaviorPrefsChanged:)
- name:@"NSScrollAnimationEnabled"
- object:nil
- suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
- } else {
- // Register for < 10.8
- [distributedCenter addObserver:self
- selector:@selector(behaviorPrefsChanged:)
- name:@"AppleScrollAnimationEnabled"
- object:nil
- suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
- }
+ [distributedCenter addObserver:self
+ selector:@selector(behaviorPrefsChanged:)
+ name:@"NSScrollAnimationEnabled"
+ object:nil
+ suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
[distributedCenter addObserver:self
selector:@selector(appearancePrefsChanged:)
diff --git a/chromium/content/browser/top_document_isolation_browsertest.cc b/chromium/content/browser/top_document_isolation_browsertest.cc
index 72d87060f4c..bca52ee1366 100644
--- a/chromium/content/browser/top_document_isolation_browsertest.cc
+++ b/chromium/content/browser/top_document_isolation_browsertest.cc
@@ -55,13 +55,13 @@ class TopDocumentIsolationTest : public ContentBrowserTest {
Shell* OpenPopup(FrameTreeNode* opener, const std::string& url) {
GURL gurl =
opener->current_frame_host()->GetLastCommittedURL().Resolve(url);
- return content::OpenPopup(opener->current_frame_host(), gurl, "_blank");
+ return content::OpenPopup(opener, gurl, "_blank");
}
void RendererInitiatedNavigateToURL(FrameTreeNode* node, const GURL& url) {
TestFrameNavigationObserver nav_observer(node);
- ASSERT_TRUE(ExecuteScript(node->current_frame_host(),
- "window.location.href='" + url.spec() + "'"));
+ ASSERT_TRUE(
+ ExecuteScript(node, "window.location.href='" + url.spec() + "'"));
nav_observer.Wait();
}
diff --git a/chromium/content/browser/tracing/background_tracing_config_impl.cc b/chromium/content/browser/tracing/background_tracing_config_impl.cc
index a370618c2f7..e964cfad5e8 100644
--- a/chromium/content/browser/tracing/background_tracing_config_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_config_impl.cc
@@ -31,6 +31,8 @@ const char kConfigCategoryBenchmarkGPU[] = "BENCHMARK_GPU";
const char kConfigCategoryBenchmarkIPC[] = "BENCHMARK_IPC";
const char kConfigCategoryBenchmarkStartup[] = "BENCHMARK_STARTUP";
const char kConfigCategoryBenchmarkBlinkGC[] = "BENCHMARK_BLINK_GC";
+const char kConfigCategoryBenchmarkMemoryHeavy[] = "BENCHMARK_MEMORY_HEAVY";
+const char kConfigCategoryBenchmarkMemoryLight[] = "BENCHMARK_MEMORY_LIGHT";
const char kConfigCategoryBenchmarkExecutionMetric[] =
"BENCHMARK_EXECUTION_METRIC";
const char kConfigCategoryBlinkStyle[] = "BLINK_STYLE";
@@ -59,6 +61,10 @@ std::string BackgroundTracingConfigImpl::CategoryPresetToString(
return kConfigCategoryBenchmarkStartup;
case BackgroundTracingConfigImpl::BENCHMARK_BLINK_GC:
return kConfigCategoryBenchmarkBlinkGC;
+ case BackgroundTracingConfigImpl::BENCHMARK_MEMORY_HEAVY:
+ return kConfigCategoryBenchmarkMemoryHeavy;
+ case BackgroundTracingConfigImpl::BENCHMARK_MEMORY_LIGHT:
+ return kConfigCategoryBenchmarkMemoryLight;
case BackgroundTracingConfigImpl::BENCHMARK_EXECUTION_METRIC:
return kConfigCategoryBenchmarkExecutionMetric;
case BackgroundTracingConfigImpl::BLINK_STYLE:
@@ -103,6 +109,16 @@ bool BackgroundTracingConfigImpl::StringToCategoryPreset(
return true;
}
+ if (category_preset_string == kConfigCategoryBenchmarkMemoryHeavy) {
+ *category_preset = BackgroundTracingConfigImpl::BENCHMARK_MEMORY_HEAVY;
+ return true;
+ }
+
+ if (category_preset_string == kConfigCategoryBenchmarkMemoryLight) {
+ *category_preset = BackgroundTracingConfigImpl::BENCHMARK_MEMORY_LIGHT;
+ return true;
+ }
+
if (category_preset_string == kConfigCategoryBenchmarkExecutionMetric) {
*category_preset = BackgroundTracingConfigImpl::BENCHMARK_EXECUTION_METRIC;
return true;
diff --git a/chromium/content/browser/tracing/background_tracing_config_impl.h b/chromium/content/browser/tracing/background_tracing_config_impl.h
index 878d93ae868..c006958edcd 100644
--- a/chromium/content/browser/tracing/background_tracing_config_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_config_impl.h
@@ -32,6 +32,8 @@ class CONTENT_EXPORT BackgroundTracingConfigImpl
BENCHMARK_IPC,
BENCHMARK_STARTUP,
BENCHMARK_BLINK_GC,
+ BENCHMARK_MEMORY_HEAVY,
+ BENCHMARK_MEMORY_LIGHT,
BENCHMARK_EXECUTION_METRIC,
BLINK_STYLE
};
diff --git a/chromium/content/browser/tracing/background_tracing_config_unittest.cc b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
index 9e8370e169c..1820a0b35c6 100644
--- a/chromium/content/browser/tracing/background_tracing_config_unittest.cc
+++ b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
@@ -283,6 +283,8 @@ TEST_F(BackgroundTracingConfigTest, ValidPreemptiveCategoryToString) {
BackgroundTracingConfigImpl::BENCHMARK_IPC,
BackgroundTracingConfigImpl::BENCHMARK_STARTUP,
BackgroundTracingConfigImpl::BENCHMARK_BLINK_GC,
+ BackgroundTracingConfigImpl::BENCHMARK_MEMORY_HEAVY,
+ BackgroundTracingConfigImpl::BENCHMARK_MEMORY_LIGHT,
BackgroundTracingConfigImpl::BENCHMARK_EXECUTION_METRIC,
BackgroundTracingConfigImpl::BLINK_STYLE,
};
@@ -293,6 +295,8 @@ TEST_F(BackgroundTracingConfigTest, ValidPreemptiveCategoryToString) {
"BENCHMARK_IPC",
"BENCHMARK_STARTUP",
"BENCHMARK_BLINK_GC",
+ "BENCHMARK_MEMORY_HEAVY",
+ "BENCHMARK_MEMORY_LIGHT",
"BENCHMARK_EXECUTION_METRIC",
"BLINK_STYLE"};
for (size_t i = 0;
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.cc b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
index 6afd1c35577..c5812f95922 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
@@ -8,9 +8,12 @@
#include "base/command_line.h"
#include "base/json/json_writer.h"
+#include "base/location.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/tracing/background_tracing_rule.h"
#include "content/public/browser/browser_thread.h"
@@ -46,6 +49,14 @@ void RecordBackgroundTracingMetric(BackgroundTracingMetrics metric) {
NUMBER_OF_BACKGROUND_TRACING_METRICS);
}
+// Tracing enabled callback for BENCHMARK_MEMORY_LIGHT category preset.
+void BenchmarkMemoryLight_TracingEnabledCallback() {
+ auto dump_manager = base::trace_event::MemoryDumpManager::GetInstance();
+ dump_manager->RequestGlobalDump(
+ base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED,
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND);
+}
+
} // namespace
BackgroundTracingManagerImpl::TracingTimer::TracingTimer(
@@ -130,7 +141,7 @@ bool BackgroundTracingManagerImpl::SetActiveScenario(
return false;
}
} else {
- base::MessageLoop::current()->PostTask(
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&BackgroundTracingManagerImpl::ValidateStartupScenario,
base::Unretained(this)));
@@ -210,9 +221,8 @@ void BackgroundTracingManagerImpl::StartTracingIfConfigNeedsIt() {
return;
if (config_->tracing_mode() == BackgroundTracingConfigImpl::PREEMPTIVE) {
- StartTracing(
- GetCategoryFilterStringForCategoryPreset(config_->category_preset()),
- base::trace_event::RECORD_CONTINUOUSLY);
+ StartTracing(config_->category_preset(),
+ base::trace_event::RECORD_CONTINUOUSLY);
}
// There is nothing to do in case of reactive tracing.
}
@@ -304,6 +314,8 @@ void BackgroundTracingManagerImpl::OnRuleTriggered(
return;
}
+ last_triggered_rule_.reset(new base::DictionaryValue);
+ triggered_rule->IntoDict(last_triggered_rule_.get());
int trace_delay = triggered_rule->GetTraceDelay();
if (config_->tracing_mode() == BackgroundTracingConfigImpl::REACTIVE) {
@@ -313,8 +325,7 @@ void BackgroundTracingManagerImpl::OnRuleTriggered(
if (!is_tracing_) {
// It was not already tracing, start a new trace.
- StartTracing(GetCategoryFilterStringForCategoryPreset(
- triggered_rule->category_preset()),
+ StartTracing(triggered_rule->category_preset(),
base::trace_event::RECORD_UNTIL_FULL);
} else {
// Reactive configs that trigger again while tracing should just
@@ -388,14 +399,33 @@ void BackgroundTracingManagerImpl::FireTimerForTesting() {
}
void BackgroundTracingManagerImpl::StartTracing(
- std::string category_filter_str,
+ BackgroundTracingConfigImpl::CategoryPreset preset,
base::trace_event::TraceRecordMode record_mode) {
- base::trace_event::TraceConfig trace_config(category_filter_str, record_mode);
+ base::trace_event::TraceConfig trace_config(
+ GetCategoryFilterStringForCategoryPreset(preset), record_mode);
if (requires_anonymized_data_)
trace_config.EnableArgumentFilter();
+ base::Closure tracing_enabled_callback;
+ if (!tracing_enabled_callback_for_testing_.is_null()) {
+ tracing_enabled_callback = tracing_enabled_callback_for_testing_;
+ } else if (preset == BackgroundTracingConfigImpl::CategoryPreset::
+ BENCHMARK_MEMORY_LIGHT) {
+ // On memory light mode, the periodic memory dumps are disabled and a single
+ // memory dump is requested after tracing is enabled in all the processes.
+ // TODO(ssid): Remove this when background tracing supports trace config
+ // strings and memory-infra supports peak detection crbug.com/609935.
+ base::trace_event::TraceConfig::MemoryDumpConfig memory_config;
+ memory_config.allowed_dump_modes =
+ std::set<base::trace_event::MemoryDumpLevelOfDetail>(
+ {base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND});
+ trace_config.ResetMemoryDumpConfig(memory_config);
+ tracing_enabled_callback =
+ base::Bind(&BenchmarkMemoryLight_TracingEnabledCallback);
+ }
+
is_tracing_ = TracingController::GetInstance()->StartTracing(
- trace_config, tracing_enabled_callback_for_testing_);
+ trace_config, tracing_enabled_callback);
RecordBackgroundTracingMetric(RECORDING_ENABLED);
}
@@ -449,13 +479,15 @@ void BackgroundTracingManagerImpl::OnFinalizeComplete() {
}
void BackgroundTracingManagerImpl::AddCustomMetadata(
- TracingControllerImpl::TraceDataSink* trace_data_sink) const {
+ TracingControllerImpl::TraceDataSink* trace_data_sink) {
base::DictionaryValue metadata_dict;
std::unique_ptr<base::DictionaryValue> config_dict(
new base::DictionaryValue());
config_->IntoDict(config_dict.get());
metadata_dict.Set("config", std::move(config_dict));
+ if (last_triggered_rule_)
+ metadata_dict.Set("last_triggered_rule", std::move(last_triggered_rule_));
trace_data_sink->AddMetadata(metadata_dict);
}
@@ -518,6 +550,9 @@ BackgroundTracingManagerImpl::GetCategoryFilterStringForCategoryPreset(
"disabled-by-default-ipc.flow";
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_BLINK_GC:
return "blink_gc,disabled-by-default-blink_gc";
+ case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_MEMORY_HEAVY:
+ case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_MEMORY_LIGHT:
+ return "-*,disabled-by-default-memory-infra";
case BackgroundTracingConfigImpl::CategoryPreset::
BENCHMARK_EXECUTION_METRIC:
return "blink.console,v8";
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.h b/chromium/content/browser/tracing/background_tracing_manager_impl.h
index bcb25a4214e..7b0ccba16cb 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.h
@@ -54,7 +54,8 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
BackgroundTracingManagerImpl();
~BackgroundTracingManagerImpl() override;
- void StartTracing(std::string, base::trace_event::TraceRecordMode);
+ void StartTracing(BackgroundTracingConfigImpl::CategoryPreset,
+ base::trace_event::TraceRecordMode);
void StartTracingIfConfigNeedsIt();
void OnFinalizeStarted(std::unique_ptr<const base::DictionaryValue> metadata,
base::RefCountedString*);
@@ -62,7 +63,7 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
void BeginFinalizing(StartedFinalizingCallback);
void ValidateStartupScenario();
- void AddCustomMetadata(TracingControllerImpl::TraceDataSink*) const;
+ void AddCustomMetadata(TracingControllerImpl::TraceDataSink*);
std::string GetTriggerNameFromHandle(TriggerHandle handle) const;
bool IsTriggerHandleValid(TriggerHandle handle) const;
@@ -95,7 +96,7 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
std::map<TriggerHandle, std::string> trigger_handles_;
std::unique_ptr<TracingTimer> tracing_timer_;
ReceiveCallback receive_callback_;
-
+ std::unique_ptr<base::DictionaryValue> last_triggered_rule_;
bool is_gathering_;
bool is_tracing_;
bool requires_anonymized_data_;
diff --git a/chromium/content/browser/tracing/background_tracing_rule.cc b/chromium/content/browser/tracing/background_tracing_rule.cc
index 9abe06ec2e6..c24896fc186 100644
--- a/chromium/content/browser/tracing/background_tracing_rule.cc
+++ b/chromium/content/browser/tracing/background_tracing_rule.cc
@@ -11,7 +11,7 @@
#include "base/rand_util.h"
#include "base/strings/safe_sprintf.h"
#include "base/values.h"
-#include "components/tracing/tracing_messages.h"
+#include "components/tracing/common/tracing_messages.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/content/browser/tracing/memory_tracing_browsertest.cc b/chromium/content/browser/tracing/memory_tracing_browsertest.cc
index c2cafd80d0d..80ccfae3df2 100644
--- a/chromium/content/browser/tracing/memory_tracing_browsertest.cc
+++ b/chromium/content/browser/tracing/memory_tracing_browsertest.cc
@@ -5,6 +5,7 @@
#include <stdint.h>
#include "base/bind.h"
+#include "base/callback_forward.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -21,6 +22,7 @@
#include "testing/gmock/include/gmock/gmock.h"
using base::trace_event::MemoryDumpArgs;
+using base::trace_event::MemoryDumpLevelOfDetail;
using base::trace_event::MemoryDumpManager;
using base::trace_event::MemoryDumpType;
using base::trace_event::ProcessMemoryDump;
@@ -39,16 +41,18 @@ class MockDumpProvider : public base::trace_event::MemoryDumpProvider {
class MemoryTracingTest : public ContentBrowserTest {
public:
- void DoRequestGlobalDump(const base::trace_event::MemoryDumpCallback& cb) {
- MemoryDumpManager::GetInstance()->RequestGlobalDump(
- MemoryDumpType::EXPLICITLY_TRIGGERED,
- base::trace_event::MemoryDumpLevelOfDetail::DETAILED, cb);
+ void DoRequestGlobalDump(const MemoryDumpType& dump_type,
+ const MemoryDumpLevelOfDetail& level_of_detail,
+ const base::trace_event::MemoryDumpCallback& cb) {
+ MemoryDumpManager::GetInstance()->RequestGlobalDump(dump_type,
+ level_of_detail, cb);
}
// Used as callback argument for MemoryDumpManager::RequestGlobalDump():
void OnGlobalMemoryDumpDone(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
base::Closure closure,
+ uint32_t request_index,
uint64_t dump_guid,
bool success) {
// Make sure we run the RunLoop closure on the same thread that originated
@@ -57,20 +61,37 @@ class MemoryTracingTest : public ContentBrowserTest {
task_runner->PostTask(
FROM_HERE, base::Bind(&MemoryTracingTest::OnGlobalMemoryDumpDone,
base::Unretained(this), task_runner, closure,
- dump_guid, success));
+ request_index, dump_guid, success));
return;
}
- ++callback_call_count_;
- last_callback_dump_guid_ = dump_guid;
- last_callback_success_ = success;
- closure.Run();
+ if (success)
+ EXPECT_NE(0u, dump_guid);
+ OnMemoryDumpDone(request_index, success);
+ if (!closure.is_null())
+ closure.Run();
+ }
+
+ void RequestGlobalDumpWithClosure(
+ bool from_renderer_thread,
+ const MemoryDumpType& dump_type,
+ const MemoryDumpLevelOfDetail& level_of_detail,
+ const base::Closure& closure) {
+ uint32_t request_index = next_request_index_++;
+ base::trace_event::MemoryDumpCallback callback = base::Bind(
+ &MemoryTracingTest::OnGlobalMemoryDumpDone, base::Unretained(this),
+ base::ThreadTaskRunnerHandle::Get(), closure, request_index);
+ if (from_renderer_thread) {
+ PostTaskToInProcessRendererAndWait(base::Bind(
+ &MemoryTracingTest::DoRequestGlobalDump, base::Unretained(this),
+ dump_type, level_of_detail, callback));
+ } else {
+ DoRequestGlobalDump(dump_type, level_of_detail, callback);
+ }
}
protected:
void SetUp() override {
- callback_call_count_ = 0;
- last_callback_dump_guid_ = 0;
- last_callback_success_ = false;
+ next_request_index_ = 0;
mock_dump_provider_.reset(new MockDumpProvider());
MemoryDumpManager::GetInstance()->RegisterDumpProvider(
@@ -106,29 +127,32 @@ class MemoryTracingTest : public ContentBrowserTest {
base::RunLoop().RunUntilIdle();
}
- void RequestGlobalDumpAndWait(bool from_renderer_thread) {
+ void RequestGlobalDumpAndWait(
+ bool from_renderer_thread,
+ const MemoryDumpType& dump_type,
+ const MemoryDumpLevelOfDetail& level_of_detail) {
base::RunLoop run_loop;
- base::trace_event::MemoryDumpCallback callback = base::Bind(
- &MemoryTracingTest::OnGlobalMemoryDumpDone, base::Unretained(this),
- base::ThreadTaskRunnerHandle::Get(), run_loop.QuitClosure());
- if (from_renderer_thread) {
- PostTaskToInProcessRendererAndWait(
- base::Bind(&MemoryTracingTest::DoRequestGlobalDump,
- base::Unretained(this), callback));
- } else {
- DoRequestGlobalDump(callback);
- }
+ RequestGlobalDumpWithClosure(from_renderer_thread, dump_type,
+ level_of_detail, run_loop.QuitClosure());
run_loop.Run();
}
+ void RequestGlobalDump(bool from_renderer_thread,
+ const MemoryDumpType& dump_type,
+ const MemoryDumpLevelOfDetail& level_of_detail) {
+ RequestGlobalDumpWithClosure(from_renderer_thread, dump_type,
+ level_of_detail, base::Closure());
+ }
+
void Navigate(Shell* shell) {
NavigateToURL(shell, GetTestUrl("", "title.html"));
}
+ MOCK_METHOD2(OnMemoryDumpDone, void(uint32_t request_index, bool successful));
+
base::Closure on_memory_dump_complete_closure_;
std::unique_ptr<MockDumpProvider> mock_dump_provider_;
- uint32_t callback_call_count_;
- uint64_t last_callback_dump_guid_;
+ uint32_t next_request_index_;
bool last_callback_success_;
};
@@ -152,12 +176,12 @@ IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest,
Navigate(shell());
EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_,_)).WillOnce(Return(true));
+ EXPECT_CALL(*this, OnMemoryDumpDone(_, true /* success */));
EnableMemoryTracing();
- RequestGlobalDumpAndWait(false /* from_renderer_thread */);
- EXPECT_EQ(1u, callback_call_count_);
- EXPECT_NE(0u, last_callback_dump_guid_);
- EXPECT_TRUE(last_callback_success_);
+ RequestGlobalDumpAndWait(false /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::DETAILED);
DisableTracing();
}
@@ -168,12 +192,12 @@ IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest,
Navigate(shell());
EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_,_)).WillOnce(Return(true));
+ EXPECT_CALL(*this, OnMemoryDumpDone(_, true /* success */));
EnableMemoryTracing();
- RequestGlobalDumpAndWait(true /* from_renderer_thread */);
- EXPECT_EQ(1u, callback_call_count_);
- EXPECT_NE(0u, last_callback_dump_guid_);
- EXPECT_TRUE(last_callback_success_);
+ RequestGlobalDumpAndWait(true /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::DETAILED);
DisableTracing();
}
@@ -183,25 +207,87 @@ IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest, ManyInterleavedDumps) {
EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_,_))
.Times(4)
.WillRepeatedly(Return(true));
+ EXPECT_CALL(*this, OnMemoryDumpDone(_, true /* success */)).Times(4);
EnableMemoryTracing();
+ RequestGlobalDumpAndWait(true /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::DETAILED);
+ RequestGlobalDumpAndWait(false /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::DETAILED);
+ RequestGlobalDumpAndWait(false /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::DETAILED);
+ RequestGlobalDumpAndWait(true /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::DETAILED);
+ DisableTracing();
+}
- RequestGlobalDumpAndWait(true /* from_renderer_thread */);
- EXPECT_NE(0u, last_callback_dump_guid_);
- EXPECT_TRUE(last_callback_success_);
+// Checks that, if there already is a memory dump in progress, subsequent memory
+// dump requests are queued and carried out after it's finished. Also checks
+// that periodic dump requests fail in case there is already a request in the
+// queue with the same level of detail.
+IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest, QueuedDumps) {
+ Navigate(shell());
- RequestGlobalDumpAndWait(false /* from_renderer_thread */);
- EXPECT_NE(0u, last_callback_dump_guid_);
- EXPECT_TRUE(last_callback_success_);
+ EnableMemoryTracing();
- RequestGlobalDumpAndWait(false /* from_renderer_thread */);
- EXPECT_NE(0u, last_callback_dump_guid_);
- EXPECT_TRUE(last_callback_success_);
+ // Issue the following 6 global memory dump requests:
+ //
+ // 0 (ED) req-------------------------------------->ok
+ // 1 (PD) req->fail(0)
+ // 2 (PL) req------------------------>ok
+ // 3 (PL) req->fail(2)
+ // 4 (EL) req---------->ok
+ // 5 (ED) req--------->ok
+ // 6 (PL) req->ok
+ //
+ // where P=PERIODIC_INTERVAL, E=EXPLICITLY_TRIGGERED, D=DETAILED and L=LIGHT.
+
+ EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_, _))
+ .Times(5)
+ .WillRepeatedly(Return(true));
- RequestGlobalDumpAndWait(true /* from_renderer_thread */);
- EXPECT_EQ(4u, callback_call_count_);
- EXPECT_NE(0u, last_callback_dump_guid_);
- EXPECT_TRUE(last_callback_success_);
+ EXPECT_CALL(*this, OnMemoryDumpDone(0, true /* success */));
+ RequestGlobalDump(true /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::DETAILED);
+
+ // This dump should fail immediately because there's already a detailed dump
+ // request in the queue.
+ EXPECT_CALL(*this, OnMemoryDumpDone(1, false /* success */));
+ RequestGlobalDump(true /* from_renderer_thread */,
+ MemoryDumpType::PERIODIC_INTERVAL,
+ MemoryDumpLevelOfDetail::DETAILED);
+
+ EXPECT_CALL(*this, OnMemoryDumpDone(2, true /* success */));
+ RequestGlobalDump(true /* from_renderer_thread */,
+ MemoryDumpType::PERIODIC_INTERVAL,
+ MemoryDumpLevelOfDetail::LIGHT);
+
+ // This dump should fail immediately because there's already a light dump
+ // request in the queue.
+ EXPECT_CALL(*this, OnMemoryDumpDone(3, false /* success */));
+ RequestGlobalDump(true /* from_renderer_thread */,
+ MemoryDumpType::PERIODIC_INTERVAL,
+ MemoryDumpLevelOfDetail::LIGHT);
+
+ EXPECT_CALL(*this, OnMemoryDumpDone(4, true /* success */));
+ RequestGlobalDump(true /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::LIGHT);
+
+ EXPECT_CALL(*this, OnMemoryDumpDone(5, true /* success */));
+ RequestGlobalDumpAndWait(true /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::DETAILED);
+
+ EXPECT_CALL(*this, OnMemoryDumpDone(6, true /* success */));
+ RequestGlobalDumpAndWait(true /* from_renderer_thread */,
+ MemoryDumpType::PERIODIC_INTERVAL,
+ MemoryDumpLevelOfDetail::LIGHT);
DisableTracing();
}
@@ -220,12 +306,12 @@ IN_PROC_BROWSER_TEST_F(MemoryTracingTest, MAYBE_BrowserInitiatedDump) {
Navigate(shell());
EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_,_)).WillOnce(Return(true));
+ EXPECT_CALL(*this, OnMemoryDumpDone(_, true /* success */));
EnableMemoryTracing();
- RequestGlobalDumpAndWait(false /* from_renderer_thread */);
- EXPECT_EQ(1u, callback_call_count_);
- EXPECT_NE(0u, last_callback_dump_guid_);
- EXPECT_TRUE(last_callback_success_);
+ RequestGlobalDumpAndWait(false /* from_renderer_thread */,
+ MemoryDumpType::EXPLICITLY_TRIGGERED,
+ MemoryDumpLevelOfDetail::DETAILED);
DisableTracing();
}
diff --git a/chromium/content/browser/tracing/trace_message_filter.cc b/chromium/content/browser/tracing/trace_message_filter.cc
index d9168e718bb..4062970c276 100644
--- a/chromium/content/browser/tracing/trace_message_filter.cc
+++ b/chromium/content/browser/tracing/trace_message_filter.cc
@@ -4,7 +4,7 @@
#include "content/browser/tracing/trace_message_filter.h"
-#include "components/tracing/tracing_messages.h"
+#include "components/tracing/common/tracing_messages.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/common/child_process_host_impl.h"
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index cf9ce5fb6dc..5756c737a5a 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -16,7 +16,7 @@
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "components/tracing/process_metrics_memory_dump_provider.h"
+#include "components/tracing/common/process_metrics_memory_dump_provider.h"
#include "content/browser/tracing/file_tracing_provider_impl.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/browser/tracing/tracing_ui.h"
@@ -561,6 +561,7 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
}
}
if (pending_memory_dump_ack_count_ > 0) {
+ DCHECK(!queued_memory_dump_requests_.empty());
TraceMessageFilterSet::const_iterator it =
pending_memory_dump_filters_.find(trace_message_filter);
if (it != pending_memory_dump_filters_.end()) {
@@ -569,7 +570,8 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse,
base::Unretained(this),
base::RetainedRef(trace_message_filter),
- pending_memory_dump_guid_, false /* success */));
+ queued_memory_dump_requests_.front().args.dump_guid,
+ false /* success */));
}
}
trace_message_filters_.erase(trace_message_filter);
@@ -920,21 +922,50 @@ void TracingControllerImpl::RequestGlobalMemoryDump(
base::Unretained(this), args, callback));
return;
}
- // Abort if another dump is already in progress.
- if (pending_memory_dump_guid_) {
- DVLOG(1) << "Requested memory dump " << args.dump_guid
- << " while waiting for " << pending_memory_dump_guid_;
- if (!callback.is_null())
- callback.Run(args.dump_guid, false /* success */);
- return;
+
+ bool another_dump_already_in_progress = !queued_memory_dump_requests_.empty();
+
+ // If this is a periodic memory dump request and there already is another
+ // request in the queue with the same level of detail, there's no point in
+ // enqueuing this request.
+ if (another_dump_already_in_progress &&
+ args.dump_type == base::trace_event::MemoryDumpType::PERIODIC_INTERVAL) {
+ for (const auto& request : queued_memory_dump_requests_) {
+ if (request.args.level_of_detail == args.level_of_detail) {
+ VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix << " ("
+ << base::trace_event::MemoryDumpTypeToString(args.dump_type)
+ << ") skipped because another dump request with the same "
+ "level of detail ("
+ << base::trace_event::MemoryDumpLevelOfDetailToString(
+ args.level_of_detail)
+ << ") is already in the queue";
+ if (!callback.is_null())
+ callback.Run(args.dump_guid, false /* success */);
+ return;
+ }
+ }
}
+ queued_memory_dump_requests_.emplace_back(args, callback);
+
+ // If another dump is already in progress, this dump will automatically be
+ // scheduled when the other dump finishes.
+ if (another_dump_already_in_progress)
+ return;
+
+ PerformNextQueuedGlobalMemoryDump();
+}
+
+void TracingControllerImpl::PerformNextQueuedGlobalMemoryDump() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!queued_memory_dump_requests_.empty());
+ const base::trace_event::MemoryDumpRequestArgs& args =
+ queued_memory_dump_requests_.front().args;
+
// Count myself (local trace) in pending_memory_dump_ack_count_, acked by
// OnBrowserProcessMemoryDumpDone().
pending_memory_dump_ack_count_ = trace_message_filters_.size() + 1;
pending_memory_dump_filters_.clear();
- pending_memory_dump_guid_ = args.dump_guid;
- pending_memory_dump_callback_ = callback;
failed_memory_dump_count_ = 0;
MemoryDumpManagerDelegate::CreateProcessDump(
@@ -951,6 +982,13 @@ void TracingControllerImpl::RequestGlobalMemoryDump(
tmf->SendProcessMemoryDumpRequest(args);
}
+TracingControllerImpl::QueuedMemoryDumpRequest::QueuedMemoryDumpRequest(
+ const base::trace_event::MemoryDumpRequestArgs& args,
+ const base::trace_event::MemoryDumpCallback& callback)
+ : args(args), callback(callback) {}
+
+TracingControllerImpl::QueuedMemoryDumpRequest::~QueuedMemoryDumpRequest() {}
+
uint64_t TracingControllerImpl::GetTracingProcessId() const {
return ChildProcessHost::kBrowserTracingProcessId;
}
@@ -990,7 +1028,8 @@ void TracingControllerImpl::OnProcessMemoryDumpResponse(
TraceMessageFilterSet::iterator it =
pending_memory_dump_filters_.find(trace_message_filter);
- if (pending_memory_dump_guid_ != dump_guid ||
+ DCHECK(!queued_memory_dump_requests_.empty());
+ if (queued_memory_dump_requests_.front().args.dump_guid != dump_guid ||
it == pending_memory_dump_filters_.end()) {
DLOG(WARNING) << "Received unexpected memory dump response: " << dump_guid;
return;
@@ -1001,8 +1040,9 @@ void TracingControllerImpl::OnProcessMemoryDumpResponse(
pending_memory_dump_filters_.erase(it);
if (!success) {
++failed_memory_dump_count_;
- DLOG(WARNING) << "Global memory dump failed because of NACK from child "
- << trace_message_filter->peer_pid();
+ VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix
+ << " failed because of NACK from child "
+ << trace_message_filter->peer_pid();
}
FinalizeGlobalMemoryDumpIfAllProcessesReplied();
}
@@ -1013,7 +1053,8 @@ void TracingControllerImpl::OnBrowserProcessMemoryDumpDone(uint64_t dump_guid,
--pending_memory_dump_ack_count_;
if (!success) {
++failed_memory_dump_count_;
- DLOG(WARNING) << "Global memory dump aborted on the current process";
+ VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix
+ << " aborted on the current process";
}
FinalizeGlobalMemoryDumpIfAllProcessesReplied();
}
@@ -1022,14 +1063,24 @@ void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() {
if (pending_memory_dump_ack_count_ > 0)
return;
- DCHECK_NE(0u, pending_memory_dump_guid_);
- const bool global_success = failed_memory_dump_count_ == 0;
- if (!pending_memory_dump_callback_.is_null()) {
- pending_memory_dump_callback_.Run(pending_memory_dump_guid_,
- global_success);
- pending_memory_dump_callback_.Reset();
+ DCHECK(!queued_memory_dump_requests_.empty());
+ {
+ const auto& callback = queued_memory_dump_requests_.front().callback;
+ if (!callback.is_null()) {
+ const bool global_success = failed_memory_dump_count_ == 0;
+ callback.Run(queued_memory_dump_requests_.front().args.dump_guid,
+ global_success);
+ }
+ }
+ queued_memory_dump_requests_.pop_front();
+
+ // Schedule the next queued dump (if applicable).
+ if (!queued_memory_dump_requests_.empty()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::PerformNextQueuedGlobalMemoryDump,
+ base::Unretained(this)));
}
- pending_memory_dump_guid_ = 0;
}
} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.h b/chromium/content/browser/tracing/tracing_controller_impl.h
index 2f344b4be35..a391cdbde34 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.h
+++ b/chromium/content/browser/tracing/tracing_controller_impl.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <list>
#include <set>
#include <string>
#include <vector>
@@ -81,6 +82,16 @@ class TracingControllerImpl
friend struct base::DefaultLazyInstanceTraits<TracingControllerImpl>;
friend class TraceMessageFilter;
+ // The arguments and callback for an queued global memory dump request.
+ struct QueuedMemoryDumpRequest {
+ QueuedMemoryDumpRequest(
+ const base::trace_event::MemoryDumpRequestArgs& args,
+ const base::trace_event::MemoryDumpCallback& callback);
+ ~QueuedMemoryDumpRequest();
+ const base::trace_event::MemoryDumpRequestArgs args;
+ const base::trace_event::MemoryDumpCallback callback;
+ };
+
TracingControllerImpl();
~TracingControllerImpl() override;
@@ -108,6 +119,8 @@ class TracingControllerImpl
return !watch_event_callback_.is_null();
}
+ void PerformNextQueuedGlobalMemoryDump();
+
// Methods for use by TraceMessageFilter.
void AddTraceMessageFilter(TraceMessageFilter* trace_message_filter);
void RemoveTraceMessageFilter(TraceMessageFilter* trace_message_filter);
@@ -187,8 +200,7 @@ class TracingControllerImpl
int pending_memory_dump_ack_count_;
int failed_memory_dump_count_;
TraceMessageFilterSet pending_memory_dump_filters_;
- uint64_t pending_memory_dump_guid_;
- base::trace_event::MemoryDumpCallback pending_memory_dump_callback_;
+ std::list<QueuedMemoryDumpRequest> queued_memory_dump_requests_;
std::vector<base::trace_event::TracingAgent*> additional_tracing_agents_;
int pending_clock_sync_ack_count_;
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index 234733b9f95..6619c3a1a8b 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -249,8 +249,8 @@ TracingUI::~TracingUI() {
void TracingUI::DoUploadBase64Encoded(const base::ListValue* args) {
std::string file_contents_base64;
if (!args || args->empty() || !args->GetString(0, &file_contents_base64)) {
- web_ui()->CallJavascriptFunction("onUploadError",
- base::StringValue("Missing data"));
+ web_ui()->CallJavascriptFunctionUnsafe("onUploadError",
+ base::StringValue("Missing data"));
return;
}
@@ -265,8 +265,8 @@ void TracingUI::DoUploadBase64Encoded(const base::ListValue* args) {
void TracingUI::DoUpload(const base::ListValue* args) {
std::string file_contents;
if (!args || args->empty() || !args->GetString(0, &file_contents)) {
- web_ui()->CallJavascriptFunction("onUploadError",
- base::StringValue("Missing data"));
+ web_ui()->CallJavascriptFunctionUnsafe("onUploadError",
+ base::StringValue("Missing data"));
return;
}
@@ -276,14 +276,14 @@ void TracingUI::DoUpload(const base::ListValue* args) {
void TracingUI::DoUploadInternal(const std::string& file_contents,
TraceUploader::UploadMode upload_mode) {
if (!delegate_) {
- web_ui()->CallJavascriptFunction("onUploadError",
- base::StringValue("Not implemented"));
+ web_ui()->CallJavascriptFunctionUnsafe(
+ "onUploadError", base::StringValue("Not implemented"));
return;
}
if (trace_uploader_) {
- web_ui()->CallJavascriptFunction("onUploadError",
- base::StringValue("Upload in progress"));
+ web_ui()->CallJavascriptFunctionUnsafe(
+ "onUploadError", base::StringValue("Upload in progress"));
return;
}
@@ -307,21 +307,20 @@ void TracingUI::DoUploadInternal(const std::string& file_contents,
void TracingUI::OnTraceUploadProgress(int64_t current, int64_t total) {
DCHECK(current <= total);
int percent = (current / total) * 100;
- web_ui()->CallJavascriptFunction(
- "onUploadProgress",
- base::FundamentalValue(percent),
- base::StringValue(base::StringPrintf("%" PRId64, current)),
- base::StringValue(base::StringPrintf("%" PRId64, total)));
+ web_ui()->CallJavascriptFunctionUnsafe(
+ "onUploadProgress", base::FundamentalValue(percent),
+ base::StringValue(base::StringPrintf("%" PRId64, current)),
+ base::StringValue(base::StringPrintf("%" PRId64, total)));
}
void TracingUI::OnTraceUploadComplete(bool success,
const std::string& feedback) {
if (success) {
- web_ui()->CallJavascriptFunction("onUploadComplete",
- base::StringValue(feedback));
+ web_ui()->CallJavascriptFunctionUnsafe("onUploadComplete",
+ base::StringValue(feedback));
} else {
- web_ui()->CallJavascriptFunction("onUploadError",
- base::StringValue(feedback));
+ web_ui()->CallJavascriptFunctionUnsafe("onUploadError",
+ base::StringValue(feedback));
}
trace_uploader_.reset();
}
diff --git a/chromium/content/browser/utility_process_host_impl.cc b/chromium/content/browser/utility_process_host_impl.cc
index 4a05b3f21d7..3bd028ab58a 100644
--- a/chromium/content/browser/utility_process_host_impl.cc
+++ b/chromium/content/browser/utility_process_host_impl.cc
@@ -17,12 +17,15 @@
#include "base/process/process_handle.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "build/build_config.h"
#include "content/browser/browser_child_process_host_impl.h"
-#include "content/browser/mojo/mojo_application_host.h"
+#include "content/browser/mojo/constants.h"
+#include "content/browser/mojo/mojo_child_connection.h"
+#include "content/browser/mojo/mojo_shell_context.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/in_process_child_thread_params.h"
@@ -32,10 +35,15 @@
#include "content/public/browser/utility_process_host_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/mojo_channel_switches.h"
+#include "content/public/common/mojo_shell_connection.h"
#include "content/public/common/process_type.h"
#include "content/public/common/sandbox_type.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "ipc/ipc_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/public/cpp/interface_registry.h"
#include "ui/base/ui_base_switches.h"
#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
@@ -158,8 +166,15 @@ UtilityProcessHostImpl::UtilityProcessHostImpl(
#endif
started_(false),
name_(base::ASCIIToUTF16("utility process")),
- mojo_application_host_(new MojoApplicationHost),
+ child_token_(mojo::edk::GenerateRandomToken()),
weak_ptr_factory_(this) {
+ process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_UTILITY, this,
+ child_token_));
+ mojo_child_connection_.reset(new MojoChildConnection(
+ kUtilityMojoApplicationName,
+ base::StringPrintf("%d_0", process_->GetData().id),
+ child_token_,
+ MojoShellContext::GetConnectorForIOThread()));
}
UtilityProcessHostImpl::~UtilityProcessHostImpl() {
@@ -223,9 +238,18 @@ bool UtilityProcessHostImpl::Start() {
return StartProcess();
}
-ServiceRegistry* UtilityProcessHostImpl::GetServiceRegistry() {
- DCHECK(mojo_application_host_);
- return mojo_application_host_->service_registry();
+shell::InterfaceRegistry* UtilityProcessHostImpl::GetInterfaceRegistry() {
+ return mojo_child_connection_->connection()->GetInterfaceRegistry();
+}
+
+shell::InterfaceProvider* UtilityProcessHostImpl::GetRemoteInterfaces() {
+ if (!mojo_child_connection_->connection()) {
+ // During shutdown, connection may be null. We don't care about successfully
+ // connecting to remote interfaces at this point, so we just use a dummy
+ // provider.
+ return &unbound_remote_interfaces_;
+ }
+ return mojo_child_connection_->connection()->GetRemoteInterfaces();
}
void UtilityProcessHostImpl::SetName(const base::string16& name) {
@@ -248,13 +272,11 @@ bool UtilityProcessHostImpl::StartProcess() {
if (is_batch_mode_)
return true;
- // Name must be set or metrics_service will crash in any test which
- // launches a UtilityProcessHost.
- process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_UTILITY, this));
process_->SetName(name_);
- std::string channel_id = process_->GetHost()->CreateChannel();
- if (channel_id.empty()) {
+ std::string mojo_channel_token =
+ process_->GetHost()->CreateChannelMojo(child_token_);
+ if (mojo_channel_token.empty()) {
NotifyAndDelete(LAUNCH_RESULT_FAILURE);
return false;
}
@@ -265,9 +287,9 @@ bool UtilityProcessHostImpl::StartProcess() {
// support single process mode this way.
in_process_thread_.reset(
g_utility_main_thread_factory(InProcessChildThreadParams(
- channel_id, BrowserThread::UnsafeGetMessageLoopForThread(
+ std::string(), BrowserThread::UnsafeGetMessageLoopForThread(
BrowserThread::IO)->task_runner(),
- std::string(), mojo_application_host_->GetToken())));
+ mojo_channel_token, mojo_child_connection_->shell_client_token())));
in_process_thread_->Start();
} else {
const base::CommandLine& browser_command_line =
@@ -304,13 +326,13 @@ bool UtilityProcessHostImpl::StartProcess() {
cmd_line->AppendSwitchASCII(switches::kProcessType,
switches::kUtilityProcess);
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
+ cmd_line->AppendSwitchASCII(switches::kMojoChannelToken,
+ mojo_channel_token);
std::string locale = GetContentClient()->browser()->GetApplicationLocale();
cmd_line->AppendSwitchASCII(switches::kLang, locale);
#if defined(OS_WIN)
- if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument())
- cmd_line->AppendArg(switches::kPrefetchArgumentOther);
+ cmd_line->AppendArg(switches::kPrefetchArgumentOther);
#endif // defined(OS_WIN)
if (no_sandbox_)
@@ -346,7 +368,7 @@ bool UtilityProcessHostImpl::StartProcess() {
#endif
cmd_line->AppendSwitchASCII(switches::kMojoApplicationChannelToken,
- mojo_application_host_->GetToken());
+ mojo_child_connection_->shell_client_token());
process_->Launch(
new UtilitySandboxedProcessLauncherDelegate(exposed_dir_,
diff --git a/chromium/content/browser/utility_process_host_impl.h b/chromium/content/browser/utility_process_host_impl.h
index a24104dc29e..86714fca113 100644
--- a/chromium/content/browser/utility_process_host_impl.h
+++ b/chromium/content/browser/utility_process_host_impl.h
@@ -17,6 +17,7 @@
#include "build/build_config.h"
#include "content/public/browser/browser_child_process_host_delegate.h"
#include "content/public/browser/utility_process_host.h"
+#include "services/shell/public/cpp/interface_provider.h"
namespace base {
class SequencedTaskRunner;
@@ -26,7 +27,7 @@ class Thread;
namespace content {
class BrowserChildProcessHostImpl;
class InProcessChildThreadParams;
-class MojoApplicationHost;
+class MojoChildConnection;
typedef base::Thread* (*UtilityMainThreadFactoryFunction)(
const InProcessChildThreadParams&);
@@ -58,7 +59,8 @@ class CONTENT_EXPORT UtilityProcessHostImpl
void SetEnv(const base::EnvironmentMap& env) override;
#endif
bool Start() override;
- ServiceRegistry* GetServiceRegistry() override;
+ shell::InterfaceRegistry* GetInterfaceRegistry() override;
+ shell::InterfaceProvider* GetRemoteInterfaces() override;
void SetName(const base::string16& name) override;
void set_child_flags(int flags) { child_flags_ = flags; }
@@ -118,8 +120,13 @@ class CONTENT_EXPORT UtilityProcessHostImpl
std::unique_ptr<base::Thread> in_process_thread_;
// Browser-side Mojo endpoint which sets up a Mojo channel with the child
- // process and contains the browser's ServiceRegistry.
- std::unique_ptr<MojoApplicationHost> mojo_application_host_;
+ // process and contains the browser's shell::InterfaceRegistry.
+ const std::string child_token_;
+ std::unique_ptr<MojoChildConnection> mojo_child_connection_;
+
+ // An InterfaceProvider instance used to service requests after the browser's
+ // shell connection has been torn down.
+ shell::InterfaceProvider unbound_remote_interfaces_;
// Used to vend weak pointers, and should always be declared last.
base::WeakPtrFactory<UtilityProcessHostImpl> weak_ptr_factory_;
diff --git a/chromium/content/browser/utility_process_host_impl_browsertest.cc b/chromium/content/browser/utility_process_host_impl_browsertest.cc
index f152367257f..16a65424191 100644
--- a/chromium/content/browser/utility_process_host_impl_browsertest.cc
+++ b/chromium/content/browser/utility_process_host_impl_browsertest.cc
@@ -8,34 +8,38 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/utility_process_host.h"
#include "content/public/browser/utility_process_host_client.h"
-#include "content/public/common/service_registry.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_mojo_service.mojom.h"
+#include "services/shell/public/cpp/interface_provider.h"
+#include "services/shell/public/cpp/interface_registry.h"
namespace content {
class UtilityProcessHostImplBrowserTest : public ContentBrowserTest {
public:
- void RunUtilityProcess() {
+ void RunUtilityProcess(bool elevated) {
base::RunLoop run_loop;
done_closure_ = run_loop.QuitClosure();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(
&UtilityProcessHostImplBrowserTest::RunUtilityProcessOnIOThread,
- base::Unretained(this)));
+ base::Unretained(this), elevated));
run_loop.Run();
}
protected:
- void RunUtilityProcessOnIOThread() {
+ void RunUtilityProcessOnIOThread(bool elevated) {
UtilityProcessHost* host = UtilityProcessHost::Create(nullptr, nullptr);
host->SetName(base::ASCIIToUTF16("TestProcess"));
+#if defined(OS_WIN)
+ if (elevated)
+ host->ElevatePrivileges();
+#endif
EXPECT_TRUE(host->Start());
- ServiceRegistry* service_registry = host->GetServiceRegistry();
- service_registry->ConnectToRemoteService(mojo::GetProxy(&service_));
+ host->GetRemoteInterfaces()->GetInterface(&service_);
service_->DoSomething(base::Bind(
&UtilityProcessHostImplBrowserTest::OnSomething,
base::Unretained(this)));
@@ -51,7 +55,14 @@ class UtilityProcessHostImplBrowserTest : public ContentBrowserTest {
};
IN_PROC_BROWSER_TEST_F(UtilityProcessHostImplBrowserTest, LaunchProcess) {
- RunUtilityProcess();
+ RunUtilityProcess(false);
}
+#if defined(OS_WIN)
+IN_PROC_BROWSER_TEST_F(UtilityProcessHostImplBrowserTest,
+ LaunchElevatedProcess) {
+ RunUtilityProcess(true);
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/utility_process_mojo_client_browsertest.cc b/chromium/content/browser/utility_process_mojo_client_browsertest.cc
new file mode 100644
index 00000000000..7ffa80dfce7
--- /dev/null
+++ b/chromium/content/browser/utility_process_mojo_client_browsertest.cc
@@ -0,0 +1,143 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/utility_process_mojo_client.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/test_mojo_service.mojom.h"
+
+namespace content {
+
+// Test fixture used to make different Mojo calls to the utility process.
+class UtilityProcessMojoClientBrowserTest : public ContentBrowserTest {
+ public:
+ void StartMojoService(bool disable_sandbox) {
+ mojo_client_.reset(new UtilityProcessMojoClient<mojom::TestMojoService>(
+ base::ASCIIToUTF16("TestMojoProcess")));
+
+ mojo_client_->set_error_callback(
+ base::Bind(&UtilityProcessMojoClientBrowserTest::OnConnectionError,
+ base::Unretained(this)));
+
+ // This test case needs to have the sandbox disabled.
+ if (disable_sandbox)
+ mojo_client_->set_disable_sandbox();
+ mojo_client_->Start();
+ }
+
+ // Called when a response is received from a call to DoSomething() or
+ // DoTerminateProcess().
+ void OnResponseReceived() {
+ response_received_ = true;
+ done_closure_.Run();
+ }
+
+ // Called when a connection error happen between the test and the utility
+ // process.
+ void OnConnectionError() {
+ error_happened_ = true;
+ done_closure_.Run();
+ }
+
+ // Called when a responsed is received from a call to CreateFolder().
+ void OnCreateFolderFinished(bool succeeded) {
+ response_received_ = true;
+ sandbox_succeeded_ = succeeded;
+ done_closure_.Run();
+ }
+
+ protected:
+ std::unique_ptr<UtilityProcessMojoClient<mojom::TestMojoService>>
+ mojo_client_;
+ base::Closure done_closure_;
+
+ // The test result that is compared to the current test case.
+ bool response_received_ = false;
+ bool error_happened_ = false;
+ bool sandbox_succeeded_ = false;
+};
+
+// Successful call through the Mojo service with response back.
+IN_PROC_BROWSER_TEST_F(UtilityProcessMojoClientBrowserTest, CallService) {
+ base::RunLoop run_loop;
+ done_closure_ = run_loop.QuitClosure();
+
+ StartMojoService(false);
+
+ mojo_client_->service()->DoSomething(
+ base::Bind(&UtilityProcessMojoClientBrowserTest::OnResponseReceived,
+ base::Unretained(this)));
+
+ run_loop.Run();
+ EXPECT_TRUE(response_received_);
+ EXPECT_FALSE(error_happened_);
+}
+
+// Call the Mojo service but the utility process terminates before getting
+// the result back.
+// TODO(pmonette): Re-enable when crbug.com/618206 is fixed.
+IN_PROC_BROWSER_TEST_F(UtilityProcessMojoClientBrowserTest,
+ DISABLED_ConnectionError) {
+ base::RunLoop run_loop;
+ done_closure_ = run_loop.QuitClosure();
+
+ StartMojoService(false);
+
+ mojo_client_->service()->DoTerminateProcess(
+ base::Bind(&UtilityProcessMojoClientBrowserTest::OnResponseReceived,
+ base::Unretained(this)));
+
+ run_loop.Run();
+ EXPECT_FALSE(response_received_);
+ EXPECT_TRUE(error_happened_);
+}
+
+// Android doesn't support non-sandboxed utility processes.
+#if !defined(OS_ANDROID)
+// Call a function that fails because the sandbox is still enabled.
+IN_PROC_BROWSER_TEST_F(UtilityProcessMojoClientBrowserTest, SandboxFailure) {
+ base::RunLoop run_loop;
+ done_closure_ = run_loop.QuitClosure();
+
+ StartMojoService(false);
+
+ mojo_client_->service()->CreateFolder(
+ base::Bind(&UtilityProcessMojoClientBrowserTest::OnCreateFolderFinished,
+ base::Unretained(this)));
+
+ run_loop.Run();
+ EXPECT_TRUE(response_received_);
+ // If the sandbox is disabled by the command line, this will succeed.
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox))
+ EXPECT_FALSE(sandbox_succeeded_);
+ EXPECT_FALSE(error_happened_);
+}
+
+// Call a function that succeeds only when the sandbox is disabled.
+IN_PROC_BROWSER_TEST_F(UtilityProcessMojoClientBrowserTest, SandboxSuccess) {
+ base::RunLoop run_loop;
+ done_closure_ = run_loop.QuitClosure();
+
+ StartMojoService(true);
+
+ mojo_client_->service()->CreateFolder(
+ base::Bind(&UtilityProcessMojoClientBrowserTest::OnCreateFolderFinished,
+ base::Unretained(this)));
+
+ run_loop.Run();
+ EXPECT_TRUE(response_received_);
+ EXPECT_TRUE(sandbox_succeeded_);
+ EXPECT_FALSE(error_happened_);
+}
+#endif
+
+} // namespace content
diff --git a/chromium/content/browser/vibration_browsertest.cc b/chromium/content/browser/vibration_browsertest.cc
index e0df1efdef9..26779911514 100644
--- a/chromium/content/browser/vibration_browsertest.cc
+++ b/chromium/content/browser/vibration_browsertest.cc
@@ -11,7 +11,6 @@
#include "build/build_config.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/service_registry.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"
@@ -19,6 +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"
// These tests run against a dummy implementation of the VibrationManager
// service. That is, they verify that the service implementation is correctly
@@ -81,7 +81,7 @@ class VibrationTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
ResetGlobalValues();
- GetMainFrame()->GetServiceRegistry()->AddService(
+ GetMainFrame()->GetInterfaceRegistry()->AddInterface(
base::Bind(&FakeVibrationManager::Create));
}
@@ -157,7 +157,7 @@ IN_PROC_BROWSER_TEST_F(VibrationTest,
ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(".", "page_with_iframe.html")));
RenderFrameHost* iframe = ChildFrameAt(GetMainFrame(), 0);
- iframe->GetServiceRegistry()->AddService(
+ iframe->GetInterfaceRegistry()->AddInterface(
base::Bind(&FakeVibrationManager::Create));
ASSERT_TRUE(Vibrate(1234, iframe));
g_wait_vibrate_runner->Run();
@@ -174,7 +174,7 @@ IN_PROC_BROWSER_TEST_F(VibrationTest,
ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(".", "page_with_iframe.html")));
RenderFrameHost* iframe = ChildFrameAt(GetMainFrame(), 0);
- iframe->GetServiceRegistry()->AddService(
+ iframe->GetInterfaceRegistry()->AddInterface(
base::Bind(&FakeVibrationManager::Create));
ASSERT_TRUE(Vibrate(1234, iframe));
g_wait_vibrate_runner->Run();
@@ -190,7 +190,7 @@ IN_PROC_BROWSER_TEST_F(VibrationTest,
ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(".", "page_with_iframe.html")));
RenderFrameHost* iframe = ChildFrameAt(GetMainFrame(), 0);
- iframe->GetServiceRegistry()->AddService(
+ iframe->GetInterfaceRegistry()->AddInterface(
base::Bind(&FakeVibrationManager::Create));
ASSERT_TRUE(Vibrate(1234, iframe));
g_wait_vibrate_runner->Run();
diff --git a/chromium/content/browser/vr/OWNERS b/chromium/content/browser/vr/OWNERS
deleted file mode 100644
index 8bc3cc2bc1c..00000000000
--- a/chromium/content/browser/vr/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-bajones@chromium.org
-kbr@chromium.org
-hendrikw@chromium.org
diff --git a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.cc b/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.cc
deleted file mode 100644
index 022ed8d22d2..00000000000
--- a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.cc
+++ /dev/null
@@ -1,167 +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/vr/android/cardboard/cardboard_vr_device.h"
-
-#include <math.h>
-#include <algorithm>
-
-#include "base/android/context_utils.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-#include "jni/CardboardVRDevice_jni.h"
-#include "ui/gfx/transform.h"
-#include "ui/gfx/transform_util.h"
-
-using base::android::AttachCurrentThread;
-
-namespace content {
-
-bool CardboardVRDevice::RegisterCardboardVRDevice(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-CardboardVRDevice::CardboardVRDevice(VRDeviceProvider* provider)
- : VRDevice(provider), frame_index_(0) {
- JNIEnv* env = AttachCurrentThread();
- j_cardboard_device_.Reset(Java_CardboardVRDevice_create(
- env, base::android::GetApplicationContext()));
- j_head_matrix_.Reset(env, env->NewFloatArray(16));
-}
-
-CardboardVRDevice::~CardboardVRDevice() {
- Java_CardboardVRDevice_stopTracking(AttachCurrentThread(),
- j_cardboard_device_.obj());
-}
-
-blink::mojom::VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() {
- TRACE_EVENT0("input", "CardboardVRDevice::GetVRDevice");
- blink::mojom::VRDeviceInfoPtr device = blink::mojom::VRDeviceInfo::New();
-
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jstring> j_device_name =
- Java_CardboardVRDevice_getDeviceName(env, j_cardboard_device_.obj());
- device->deviceName =
- base::android::ConvertJavaStringToUTF8(env, j_device_name.obj());
-
- ScopedJavaLocalRef<jfloatArray> j_fov(env, env->NewFloatArray(4));
- Java_CardboardVRDevice_getFieldOfView(env, j_cardboard_device_.obj(),
- j_fov.obj());
-
- std::vector<float> fov;
- base::android::JavaFloatArrayToFloatVector(env, j_fov.obj(), &fov);
-
- device->hmdInfo = blink::mojom::VRHMDInfo::New();
- blink::mojom::VRHMDInfoPtr& hmdInfo = device->hmdInfo;
-
- hmdInfo->leftEye = blink::mojom::VREyeParameters::New();
- hmdInfo->rightEye = blink::mojom::VREyeParameters::New();
- blink::mojom::VREyeParametersPtr& left_eye = hmdInfo->leftEye;
- blink::mojom::VREyeParametersPtr& right_eye = hmdInfo->rightEye;
-
- left_eye->recommendedFieldOfView = blink::mojom::VRFieldOfView::New();
- left_eye->recommendedFieldOfView->upDegrees = fov[0];
- left_eye->recommendedFieldOfView->downDegrees = fov[1];
- left_eye->recommendedFieldOfView->leftDegrees = fov[2];
- left_eye->recommendedFieldOfView->rightDegrees = fov[3];
-
- // Cardboard devices always assume a mirrored FOV, so this is just the left
- // eye FOV with the left and right degrees swapped.
- right_eye->recommendedFieldOfView = blink::mojom::VRFieldOfView::New();
- right_eye->recommendedFieldOfView->upDegrees = fov[0];
- right_eye->recommendedFieldOfView->downDegrees = fov[1];
- right_eye->recommendedFieldOfView->leftDegrees = fov[3];
- right_eye->recommendedFieldOfView->rightDegrees = fov[2];
-
- // Cardboard does not support configurable FOV.
- left_eye->maximumFieldOfView = left_eye->recommendedFieldOfView.Clone();
- right_eye->maximumFieldOfView = right_eye->recommendedFieldOfView.Clone();
- left_eye->minimumFieldOfView = left_eye->recommendedFieldOfView.Clone();
- right_eye->minimumFieldOfView = right_eye->recommendedFieldOfView.Clone();
-
- float ipd = Java_CardboardVRDevice_getIpd(env, j_cardboard_device_.obj());
-
- left_eye->eyeTranslation = blink::mojom::VRVector3::New();
- left_eye->eyeTranslation->x = ipd * -0.5f;
- left_eye->eyeTranslation->y = 0.0f;
- left_eye->eyeTranslation->z = 0.0f;
-
- right_eye->eyeTranslation = blink::mojom::VRVector3::New();
- right_eye->eyeTranslation->x = ipd * 0.5f;
- right_eye->eyeTranslation->y = 0.0f;
- right_eye->eyeTranslation->z = 0.0f;
-
- ScopedJavaLocalRef<jintArray> j_screen_size(env, env->NewIntArray(2));
- Java_CardboardVRDevice_getScreenSize(env, j_cardboard_device_.obj(),
- j_screen_size.obj());
-
- std::vector<int> screen_size;
- base::android::JavaIntArrayToIntVector(env, j_screen_size.obj(),
- &screen_size);
-
- left_eye->renderRect = blink::mojom::VRRect::New();
- left_eye->renderRect->x = 0;
- left_eye->renderRect->y = 0;
- left_eye->renderRect->width = screen_size[0] / 2.0;
- left_eye->renderRect->height = screen_size[1];
-
- right_eye->renderRect = blink::mojom::VRRect::New();
- right_eye->renderRect->x = screen_size[0] / 2.0;
- right_eye->renderRect->y = 0;
- right_eye->renderRect->width = screen_size[0] / 2.0;
- right_eye->renderRect->height = screen_size[1];
-
- return device;
-}
-
-blink::mojom::VRSensorStatePtr CardboardVRDevice::GetSensorState() {
- TRACE_EVENT0("input", "CardboardVRDevice::GetSensorState");
- blink::mojom::VRSensorStatePtr state = blink::mojom::VRSensorState::New();
-
- state->timestamp = base::Time::Now().ToJsTime();
- state->frameIndex = frame_index_++;
-
- JNIEnv* env = AttachCurrentThread();
- Java_CardboardVRDevice_getSensorState(env, j_cardboard_device_.obj(),
- j_head_matrix_.obj());
-
- std::vector<float> head_matrix;
- base::android::JavaFloatArrayToFloatVector(env, j_head_matrix_.obj(),
- &head_matrix);
-
- gfx::Transform transform(
- head_matrix[0], head_matrix[1], head_matrix[2], head_matrix[3],
- head_matrix[4], head_matrix[5], head_matrix[6], head_matrix[7],
- head_matrix[8], head_matrix[9], head_matrix[10], head_matrix[11],
- head_matrix[12], head_matrix[13], head_matrix[14], head_matrix[15]);
-
- gfx::DecomposedTransform decomposed_transform;
- gfx::DecomposeTransform(&decomposed_transform, transform);
-
- state->orientation = blink::mojom::VRVector4::New();
- state->orientation->x = decomposed_transform.quaternion[0];
- state->orientation->y = decomposed_transform.quaternion[1];
- state->orientation->z = decomposed_transform.quaternion[2];
- state->orientation->w = decomposed_transform.quaternion[3];
-
- state->position = blink::mojom::VRVector3::New();
- state->position->x = decomposed_transform.translate[0];
- state->position->y = decomposed_transform.translate[1];
- state->position->z = decomposed_transform.translate[2];
-
- return state;
-}
-
-void CardboardVRDevice::ResetSensor() {
- Java_CardboardVRDevice_resetSensor(AttachCurrentThread(),
- j_cardboard_device_.obj());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.h b/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.h
deleted file mode 100644
index 62175420471..00000000000
--- a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.h
+++ /dev/null
@@ -1,38 +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_VR_CARDBOARD_VR_DEVICE_H
-#define CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_H
-
-#include <jni.h>
-
-#include "base/android/jni_android.h"
-#include "base/macros.h"
-#include "content/browser/vr/vr_device.h"
-
-namespace content {
-
-class CardboardVRDevice : public VRDevice {
- public:
- static bool RegisterCardboardVRDevice(JNIEnv* env);
-
- explicit CardboardVRDevice(VRDeviceProvider* provider);
- ~CardboardVRDevice() override;
-
- blink::mojom::VRDeviceInfoPtr GetVRDevice() override;
- blink::mojom::VRSensorStatePtr GetSensorState() override;
- void ResetSensor() override;
-
- private:
- base::android::ScopedJavaGlobalRef<jobject> j_cardboard_device_;
- base::android::ScopedJavaGlobalRef<jfloatArray> j_head_matrix_;
-
- unsigned int frame_index_;
-
- DISALLOW_COPY_AND_ASSIGN(CardboardVRDevice);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_H
diff --git a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc b/chromium/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc
deleted file mode 100644
index e3c0f65f23e..00000000000
--- a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device_provider.cc
+++ /dev/null
@@ -1,29 +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/vr/android/cardboard/cardboard_vr_device_provider.h"
-
-#include "content/browser/vr/android/cardboard/cardboard_vr_device.h"
-
-namespace content {
-
-CardboardVRDeviceProvider::CardboardVRDeviceProvider() : VRDeviceProvider() {
-}
-
-CardboardVRDeviceProvider::~CardboardVRDeviceProvider() {
-}
-
-void CardboardVRDeviceProvider::GetDevices(std::vector<VRDevice*>* devices) {
- if (!cardboard_device_) {
- cardboard_device_.reset(new CardboardVRDevice(this));
- }
-
- devices->push_back(cardboard_device_.get());
-}
-
-void CardboardVRDeviceProvider::Initialize() {
- // No initialization needed for Cardboard devices.
-}
-
-} // namespace content
diff --git a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h b/chromium/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h
deleted file mode 100644
index d8133f4ce9a..00000000000
--- a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device_provider.h
+++ /dev/null
@@ -1,33 +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_VR_CARDBOARD_VR_DEVICE_PROVIDER_H
-#define CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_PROVIDER_H
-
-#include <map>
-#include <memory>
-
-#include "base/macros.h"
-#include "content/browser/vr/vr_device.h"
-#include "content/browser/vr/vr_device_provider.h"
-
-namespace content {
-
-class CardboardVRDeviceProvider : public VRDeviceProvider {
- public:
- CardboardVRDeviceProvider();
- ~CardboardVRDeviceProvider() override;
-
- void GetDevices(std::vector<VRDevice*>* devices) override;
- void Initialize() override;
-
- private:
- std::unique_ptr<VRDevice> cardboard_device_;
-
- DISALLOW_COPY_AND_ASSIGN(CardboardVRDeviceProvider);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_VR_CARDBOARD_VR_DEVICE_PROVIDER_H
diff --git a/chromium/content/browser/vr/vr_device.cc b/chromium/content/browser/vr/vr_device.cc
deleted file mode 100644
index ab7a7bc6ac1..00000000000
--- a/chromium/content/browser/vr/vr_device.cc
+++ /dev/null
@@ -1,22 +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/vr/vr_device.h"
-#include "content/browser/vr/vr_device_provider.h"
-
-namespace content {
-
-unsigned int VRDevice::next_id_ = 1;
-
-VRDevice::VRDevice(VRDeviceProvider* provider)
- : provider_(provider), id_(next_id_) {
- // Prevent wraparound. Devices with this ID will be treated as invalid.
- if (next_id_ != VR_DEVICE_LAST_ID)
- next_id_++;
-}
-
-VRDevice::~VRDevice() {
-}
-
-} // namespace content
diff --git a/chromium/content/browser/vr/vr_device.h b/chromium/content/browser/vr/vr_device.h
deleted file mode 100644
index 4b7cb302b78..00000000000
--- a/chromium/content/browser/vr/vr_device.h
+++ /dev/null
@@ -1,48 +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_VR_VR_DEVICE_H
-#define CONTENT_BROWSER_VR_VR_DEVICE_H
-
-#include "base/macros.h"
-#include "third_party/WebKit/public/platform/modules/vr/vr_service.mojom.h"
-
-namespace blink {
-struct WebHMDSensorState;
-}
-
-namespace ui {
-class BaseWindow;
-}
-
-namespace content {
-
-class VRDeviceProvider;
-
-const unsigned int VR_DEVICE_LAST_ID = 0xFFFFFFFF;
-
-class VRDevice {
- public:
- explicit VRDevice(VRDeviceProvider* provider);
- virtual ~VRDevice();
-
- VRDeviceProvider* provider() const { return provider_; }
- unsigned int id() const { return id_; }
-
- virtual blink::mojom::VRDeviceInfoPtr GetVRDevice() = 0;
- virtual blink::mojom::VRSensorStatePtr GetSensorState() = 0;
- virtual void ResetSensor() = 0;
-
- private:
- VRDeviceProvider* provider_;
- unsigned int id_;
-
- static unsigned int next_id_;
-
- DISALLOW_COPY_AND_ASSIGN(VRDevice);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_VR_VR_DEVICE_H
diff --git a/chromium/content/browser/vr/vr_device_manager.cc b/chromium/content/browser/vr/vr_device_manager.cc
deleted file mode 100644
index f7663f35237..00000000000
--- a/chromium/content/browser/vr/vr_device_manager.cc
+++ /dev/null
@@ -1,154 +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/vr/vr_device_manager.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/memory/singleton.h"
-#include "build/build_config.h"
-
-#if defined(OS_ANDROID)
-#include "content/browser/vr/android/cardboard/cardboard_vr_device_provider.h"
-#endif
-
-namespace content {
-
-namespace {
-VRDeviceManager* g_vr_device_manager = nullptr;
-}
-
-VRDeviceManager::VRDeviceManager()
- : vr_initialized_(false), keep_alive_(false) {
- bindings_.set_connection_error_handler(
- base::Bind(&VRDeviceManager::OnConnectionError, base::Unretained(this)));
-// Register VRDeviceProviders for the current platform
-#if defined(OS_ANDROID)
- std::unique_ptr<VRDeviceProvider> cardboard_provider(
- new CardboardVRDeviceProvider());
- RegisterProvider(std::move(cardboard_provider));
-#endif
-}
-
-VRDeviceManager::VRDeviceManager(std::unique_ptr<VRDeviceProvider> provider)
- : vr_initialized_(false), keep_alive_(true) {
- thread_checker_.DetachFromThread();
- RegisterProvider(std::move(provider));
- SetInstance(this);
-}
-
-VRDeviceManager::~VRDeviceManager() {
- DCHECK(thread_checker_.CalledOnValidThread());
- g_vr_device_manager = nullptr;
-}
-
-void VRDeviceManager::BindRequest(
- mojo::InterfaceRequest<blink::mojom::VRService> request) {
- VRDeviceManager* device_manager = GetInstance();
- device_manager->bindings_.AddBinding(device_manager, std::move(request));
-}
-
-void VRDeviceManager::OnConnectionError() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (bindings_.empty() && !keep_alive_) {
- // Delete the device manager when it has no active connections.
- delete g_vr_device_manager;
- }
-}
-
-VRDeviceManager* VRDeviceManager::GetInstance() {
- if (!g_vr_device_manager)
- g_vr_device_manager = new VRDeviceManager();
- return g_vr_device_manager;
-}
-
-void VRDeviceManager::SetInstance(VRDeviceManager* instance) {
- // Unit tests can create multiple instances but only one should exist at any
- // given time so g_vr_device_manager should only go from nullptr to
- // non-nullptr and vica versa.
- CHECK_NE(!!instance, !!g_vr_device_manager);
- g_vr_device_manager = instance;
-}
-
-bool VRDeviceManager::HasInstance() {
- // For testing. Checks to see if a VRDeviceManager instance is active.
- return !!g_vr_device_manager;
-}
-
-mojo::Array<blink::mojom::VRDeviceInfoPtr> VRDeviceManager::GetVRDevices() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- InitializeProviders();
-
- std::vector<VRDevice*> devices;
- for (const auto& provider : providers_)
- provider->GetDevices(&devices);
-
- mojo::Array<blink::mojom::VRDeviceInfoPtr> out_devices;
- for (const auto& device : devices) {
- if (device->id() == VR_DEVICE_LAST_ID)
- continue;
-
- if (devices_.find(device->id()) == devices_.end())
- devices_[device->id()] = device;
-
- blink::mojom::VRDeviceInfoPtr vr_device_info = device->GetVRDevice();
- if (vr_device_info.is_null())
- continue;
-
- vr_device_info->index = device->id();
- out_devices.push_back(std::move(vr_device_info));
- }
-
- return out_devices;
-}
-
-VRDevice* VRDeviceManager::GetDevice(unsigned int index) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- DeviceMap::iterator iter = devices_.find(index);
- if (iter == devices_.end()) {
- return nullptr;
- }
- return iter->second;
-}
-
-void VRDeviceManager::InitializeProviders() {
- if (vr_initialized_) {
- return;
- }
-
- for (const auto& provider : providers_)
- provider->Initialize();
-
- vr_initialized_ = true;
-}
-
-void VRDeviceManager::RegisterProvider(
- std::unique_ptr<VRDeviceProvider> provider) {
- providers_.push_back(make_linked_ptr(provider.release()));
-}
-
-void VRDeviceManager::GetDevices(const GetDevicesCallback& callback) {
- callback.Run(GetVRDevices());
-}
-
-void VRDeviceManager::GetSensorState(uint32_t index,
- const GetSensorStateCallback& callback) {
- VRDevice* device = GetDevice(index);
- if (device) {
- callback.Run(device->GetSensorState());
- } else {
- callback.Run(nullptr);
- }
-}
-
-void VRDeviceManager::ResetSensor(uint32_t index) {
- VRDevice* device = GetDevice(index);
- if (device)
- device->ResetSensor();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/vr/vr_device_manager.h b/chromium/content/browser/vr/vr_device_manager.h
deleted file mode 100644
index 666b51a52da..00000000000
--- a/chromium/content/browser/vr/vr_device_manager.h
+++ /dev/null
@@ -1,81 +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_VR_VR_DEVICE_MANAGER_H
-#define CONTENT_BROWSER_VR_VR_DEVICE_MANAGER_H
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "content/browser/vr/vr_device.h"
-#include "content/browser/vr/vr_device_provider.h"
-#include "content/common/content_export.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "third_party/WebKit/public/platform/modules/vr/vr_service.mojom.h"
-
-namespace content {
-
-class VRDeviceManager : public blink::mojom::VRService {
- public:
- ~VRDeviceManager() override;
-
- static void BindRequest(
- mojo::InterfaceRequest<blink::mojom::VRService> request);
-
- // Returns the VRDeviceManager singleton.
- static VRDeviceManager* GetInstance();
-
- mojo::Array<blink::mojom::VRDeviceInfoPtr> GetVRDevices();
- VRDevice* GetDevice(unsigned int index);
-
- private:
- friend class VRDeviceManagerTest;
-
- VRDeviceManager();
- // Constructor for testing.
- explicit VRDeviceManager(std::unique_ptr<VRDeviceProvider> provider);
-
- static void SetInstance(VRDeviceManager* service);
- static bool HasInstance();
-
- void InitializeProviders();
- void RegisterProvider(std::unique_ptr<VRDeviceProvider> provider);
-
- // mojom::VRService implementation
- void GetDevices(const GetDevicesCallback& callback) override;
- void GetSensorState(uint32_t index,
- const GetSensorStateCallback& callback) override;
- void ResetSensor(uint32_t index) override;
-
- // Mojo connection error handler.
- void OnConnectionError();
-
- using ProviderList = std::vector<linked_ptr<VRDeviceProvider>>;
- ProviderList providers_;
-
- // Devices are owned by their providers.
- using DeviceMap = std::map<unsigned int, VRDevice*>;
- DeviceMap devices_;
-
- bool vr_initialized_;
-
- mojo::BindingSet<blink::mojom::VRService> bindings_;
-
- // For testing. If true will not delete self when consumer count reaches 0.
- bool keep_alive_;
-
- base::ThreadChecker thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(VRDeviceManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_VR_VR_DEVICE_MANAGER_H
diff --git a/chromium/content/browser/vr/vr_device_manager_unittest.cc b/chromium/content/browser/vr/vr_device_manager_unittest.cc
deleted file mode 100644
index 93c2ada4d07..00000000000
--- a/chromium/content/browser/vr/vr_device_manager_unittest.cc
+++ /dev/null
@@ -1,100 +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/vr/vr_device_manager.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
-#include "content/browser/vr/test/fake_vr_device.h"
-#include "content/browser/vr/test/fake_vr_device_provider.h"
-#include "content/browser/vr/vr_device_provider.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class VRDeviceManagerTest : public testing::Test {
- protected:
- VRDeviceManagerTest();
- ~VRDeviceManagerTest() override;
-
- void SetUp() override;
-
- bool HasServiceInstance() { return VRDeviceManager::HasInstance(); }
-
- protected:
- FakeVRDeviceProvider* provider_;
- std::unique_ptr<VRDeviceManager> device_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(VRDeviceManagerTest);
-};
-
-VRDeviceManagerTest::VRDeviceManagerTest() {
-}
-
-VRDeviceManagerTest::~VRDeviceManagerTest() {
-}
-
-void VRDeviceManagerTest::SetUp() {
- std::unique_ptr<FakeVRDeviceProvider> provider(new FakeVRDeviceProvider());
- provider_ = provider.get();
- device_manager_.reset(new VRDeviceManager(std::move(provider)));
-}
-
-TEST_F(VRDeviceManagerTest, InitializationTest) {
- EXPECT_FALSE(provider_->IsInitialized());
-
- // Calling GetDevices should initialize the service if it hasn't been
- // initialized yet or the providesr have been released.
- // The mojom::VRService should initialize each of it's providers upon it's own
- // initialization.
- mojo::Array<mojom::VRDeviceInfoPtr> webvr_devices;
- webvr_devices = device_manager_->GetVRDevices();
- EXPECT_TRUE(provider_->IsInitialized());
-}
-
-TEST_F(VRDeviceManagerTest, GetDevicesBasicTest) {
- mojo::Array<mojom::VRDeviceInfoPtr> webvr_devices;
- webvr_devices = device_manager_->GetVRDevices();
- // Calling GetVRDevices should initialize the providers.
- EXPECT_TRUE(provider_->IsInitialized());
- // Should successfully return zero devices when none are available.
- EXPECT_EQ(0u, webvr_devices.size());
-
- // GetDeviceByIndex should return nullptr if an invalid index in queried.
- VRDevice* queried_device = device_manager_->GetDevice(1);
- EXPECT_EQ(nullptr, queried_device);
-
- std::unique_ptr<FakeVRDevice> device1(new FakeVRDevice(provider_));
- provider_->AddDevice(device1.get());
- webvr_devices = device_manager_->GetVRDevices();
- // Should have successfully returned one device.
- EXPECT_EQ(1u, webvr_devices.size());
- // The WebVRDevice index should match the device id.
- EXPECT_EQ(webvr_devices[0]->index, device1->id());
-
- std::unique_ptr<FakeVRDevice> device2(new FakeVRDevice(provider_));
- provider_->AddDevice(device2.get());
- webvr_devices = device_manager_->GetVRDevices();
- // Should have successfully returned two devices.
- EXPECT_EQ(2u, webvr_devices.size());
- // NOTE: Returned WebVRDevices are not required to be in any particular order.
-
- // Querying the WebVRDevice index should return the correct device.
- queried_device = device_manager_->GetDevice(device1->id());
- EXPECT_EQ(device1.get(), queried_device);
- queried_device = device_manager_->GetDevice(device2->id());
- EXPECT_EQ(device2.get(), queried_device);
-
- provider_->RemoveDevice(device1.get());
- webvr_devices = device_manager_->GetVRDevices();
- // Should have successfully returned one device.
- EXPECT_EQ(1u, webvr_devices.size());
- // The WebVRDevice index should match the only remaining device id.
- EXPECT_EQ(webvr_devices[0]->index, device2->id());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/vr/vr_device_provider.h b/chromium/content/browser/vr/vr_device_provider.h
deleted file mode 100644
index 9a4910a4733..00000000000
--- a/chromium/content/browser/vr/vr_device_provider.h
+++ /dev/null
@@ -1,27 +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_VR_VR_DEVICE_PROVIDER_H
-#define CONTENT_BROWSER_VR_VR_DEVICE_PROVIDER_H
-
-#include <vector>
-
-namespace content {
-
-class VRDevice;
-
-class VRDeviceProvider {
- public:
- VRDeviceProvider() {}
- virtual ~VRDeviceProvider() {}
-
- virtual void GetDevices(std::vector<VRDevice*>* devices) = 0;
-
- // If the VR API requires initialization that should happen here.
- virtual void Initialize() = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_VR_VR_DEVICE_PROVIDER_H
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_context.cc b/chromium/content/browser/wake_lock/wake_lock_service_context.cc
index 24c0296dbe7..b17b51851d2 100644
--- a/chromium/content/browser/wake_lock/wake_lock_service_context.cc
+++ b/chromium/content/browser/wake_lock/wake_lock_service_context.cc
@@ -8,12 +8,11 @@
#include "base/bind.h"
#include "build/build_config.h"
-#include "content/browser/power_save_blocker_impl.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/power_save_blocker.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/common/service_registry.h"
+#include "content/public/browser/web_contents.h"
+#include "device/power_save_blocker/power_save_blocker.h"
namespace content {
@@ -36,6 +35,12 @@ void WakeLockServiceContext::RenderFrameDeleted(
render_frame_host->GetRoutingID());
}
+void WakeLockServiceContext::WebContentsDestroyed() {
+#if defined(OS_ANDROID)
+ view_weak_factory_.reset();
+#endif
+}
+
void WakeLockServiceContext::RequestWakeLock(int render_process_id,
int render_frame_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -61,16 +66,21 @@ bool WakeLockServiceContext::HasWakeLockForTests() const {
void WakeLockServiceContext::CreateWakeLock() {
DCHECK(!wake_lock_);
- wake_lock_ = PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
- PowerSaveBlocker::kReasonOther, "Wake Lock API");
+ wake_lock_.reset(new device::PowerSaveBlocker(
+ device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ device::PowerSaveBlocker::kReasonOther, "Wake Lock API",
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
#if defined(OS_ANDROID)
// On Android, additionaly associate the blocker with this WebContents.
DCHECK(web_contents());
- static_cast<PowerSaveBlockerImpl*>(wake_lock_.get())
- ->InitDisplaySleepBlocker(web_contents());
+ if (web_contents()->GetNativeView()) {
+ view_weak_factory_.reset(new base::WeakPtrFactory<ui::ViewAndroid>(
+ web_contents()->GetNativeView()));
+ wake_lock_.get()->InitDisplaySleepBlocker(view_weak_factory_->GetWeakPtr());
+ }
#endif
}
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_context.h b/chromium/content/browser/wake_lock/wake_lock_service_context.h
index d734c4c47ae..31bd1cbbf60 100644
--- a/chromium/content/browser/wake_lock/wake_lock_service_context.h
+++ b/chromium/content/browser/wake_lock/wake_lock_service_context.h
@@ -16,9 +16,16 @@
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/interface_request.h"
-namespace content {
+#if defined(OS_ANDROID)
+#include "ui/android/view_android.h"
+#endif // OS_ANDROID
+namespace device {
class PowerSaveBlocker;
+} // namespace device
+
+namespace content {
+
class RenderFrameHost;
class WebContents;
@@ -35,6 +42,7 @@ class CONTENT_EXPORT WakeLockServiceContext : public WebContentsObserver {
// WebContentsObserver implementation.
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+ void WebContentsDestroyed() override;
// Requests wake lock for RenderFrame identified by |render_process_id| and
// |render_frame_id|.
@@ -57,7 +65,10 @@ class CONTENT_EXPORT WakeLockServiceContext : public WebContentsObserver {
std::set<std::pair<int, int>> frames_requesting_lock_;
// The actual power save blocker for screen.
- std::unique_ptr<PowerSaveBlocker> wake_lock_;
+ std::unique_ptr<device::PowerSaveBlocker> wake_lock_;
+#if defined(OS_ANDROID)
+ std::unique_ptr<base::WeakPtrFactory<ui::ViewAndroid>> view_weak_factory_;
+#endif
base::WeakPtrFactory<WakeLockServiceContext> weak_factory_;
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
index 56e4a42d90f..e5e2019d223 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
@@ -223,6 +223,14 @@ void OverscrollNavigationOverlay::OnOverscrollCompleted(
return;
}
+ main_window->SetTransform(gfx::Transform());
+ window_ = std::move(window);
+ // Make sure the window is in its default position.
+ window_->SetBounds(gfx::Rect(web_contents_window_->bounds().size()));
+ window_->SetTransform(gfx::Transform());
+ // Make sure the overlay window is on top.
+ web_contents_window_->StackChildAtTop(window_.get());
+
// Make sure we can navigate first, as other factors can trigger a navigation
// during an overscroll gesture and navigating without history produces a
// crash.
@@ -247,13 +255,6 @@ void OverscrollNavigationOverlay::OnOverscrollCompleted(
StartObserving();
}
- main_window->SetTransform(gfx::Transform());
- window_ = std::move(window);
- // Make sure the window is in its default position.
- window_->SetBounds(gfx::Rect(web_contents_window_->bounds().size()));
- window_->SetTransform(gfx::Transform());
- // Make sure the overlay window is on top.
- web_contents_window_->StackChildAtTop(window_.get());
direction_ = NONE;
StopObservingIfDone();
}
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
index 2488d888a31..7ee72bd4a23 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
@@ -58,6 +58,8 @@ class CONTENT_EXPORT OverscrollNavigationOverlay
FRIEND_TEST_ALL_PREFIXES(OverscrollNavigationOverlayTest, OverlayWindowSwap);
FRIEND_TEST_ALL_PREFIXES(OverscrollNavigationOverlayTest,
CloseDuringAnimation);
+ FRIEND_TEST_ALL_PREFIXES(OverscrollNavigationOverlayTest,
+ ImmediateLoadOnNavigate);
// Resets state and starts observing |web_contents_| for page load/paint
// updates. This function makes sure that the screenshot window is stacked
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 69777ebde7e..f5cb27a6fb1 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
@@ -31,6 +31,29 @@
namespace content {
+// Forces web contents to complete web page load as soon as navigation starts.
+class ImmediateLoadObserver : WebContentsObserver {
+ public:
+ explicit ImmediateLoadObserver(TestWebContents* contents)
+ : contents_(contents) {
+ Observe(contents);
+ }
+ ~ImmediateLoadObserver() override {}
+
+ void DidStartNavigationToPendingEntry(
+ const GURL& url,
+ NavigationController::ReloadType reload_type) override {
+ // Simulate immediate web page load.
+ contents_->TestSetIsLoading(false);
+ Observe(nullptr);
+ }
+
+ private:
+ TestWebContents* contents_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImmediateLoadObserver);
+};
+
// A subclass of TestWebContents that offers a fake content window.
class OverscrollTestWebContents : public TestWebContents {
public:
@@ -331,6 +354,18 @@ TEST_F(OverscrollNavigationOverlayTest, CloseDuringAnimation) {
// Ensure a clean close.
}
+// Tests that we can handle the case when the load completes as soon as the
+// navigation is started.
+TEST_F(OverscrollNavigationOverlayTest, ImmediateLoadOnNavigate) {
+ PerformBackNavigationViaSliderCallbacks();
+ // This observer will force the page load to complete as soon as the
+ // navigation starts.
+ ImmediateLoadObserver immediate_nav(contents());
+ GetOverlay()->owa_->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST);
+ // This will start and immediately complete the navigation.
+ GetOverlay()->owa_->OnOverscrollComplete(OVERSCROLL_EAST);
+ EXPECT_FALSE(GetOverlay()->window_.get());
+}
// Tests that swapping the overlay window at the end of a gesture caused by the
// start of a new overscroll does not crash and the events still reach the new
diff --git a/chromium/content/browser/web_contents/opened_by_dom_browsertest.cc b/chromium/content/browser/web_contents/opened_by_dom_browsertest.cc
index 44a184c2039..699121da96f 100644
--- a/chromium/content/browser/web_contents/opened_by_dom_browsertest.cc
+++ b/chromium/content/browser/web_contents/opened_by_dom_browsertest.cc
@@ -73,8 +73,7 @@ class OpenedByDOMTest : public ContentBrowserTest {
TestNavigationObserver nav_observer(NULL);
nav_observer.StartWatchingNewWebContents();
CHECK(ExecuteScript(
- shell->web_contents(),
- base::StringPrintf("window.open('%s')", url.spec().c_str())));
+ shell, base::StringPrintf("window.open('%s')", url.spec().c_str())));
nav_observer.Wait();
return new_shell_observer.GetShell();
}
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index 87c8b2d1cf1..fb45acf0584 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -673,6 +673,25 @@ void WebContentsAndroid::ReloadLoFiImages(JNIEnv* env,
static_cast<WebContentsImpl*>(web_contents_)->ReloadLoFiImages();
}
+int WebContentsAndroid::DownloadImage(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jstring>& jurl,
+ jboolean is_fav_icon,
+ jint max_bitmap_size,
+ jboolean bypass_cache,
+ const base::android::JavaParamRef<jobject>& jcallback) {
+ GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
+ return web_contents_->DownloadImage(
+ url, is_fav_icon, max_bitmap_size, bypass_cache,
+ base::Bind(&WebContentsAndroid::OnFinishDownloadImage,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(new ScopedJavaGlobalRef<jobject>(
+ env, obj)),
+ base::Owned(new ScopedJavaGlobalRef<jobject>(
+ env, jcallback))));
+}
+
void WebContentsAndroid::OnFinishGetContentBitmap(
ScopedJavaGlobalRef<jobject>* obj,
ScopedJavaGlobalRef<jobject>* callback,
@@ -689,4 +708,35 @@ void WebContentsAndroid::OnFinishGetContentBitmap(
response);
}
+void WebContentsAndroid::OnFinishDownloadImage(
+ base::android::ScopedJavaGlobalRef<jobject>* obj,
+ base::android::ScopedJavaGlobalRef<jobject>* callback,
+ int id,
+ int http_status_code,
+ const GURL& url,
+ const std::vector<SkBitmap>& bitmaps,
+ const std::vector<gfx::Size>& sizes) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> jbitmaps =
+ Java_WebContentsImpl_createBitmapList(env);
+ ScopedJavaLocalRef<jobject> jsizes =
+ Java_WebContentsImpl_createSizeList(env);
+ ScopedJavaLocalRef<jstring> jurl =
+ base::android::ConvertUTF8ToJavaString(env, url.spec());
+
+ for (const SkBitmap& bitmap : bitmaps) {
+ // WARNING: convering to java bitmaps results in duplicate memory
+ // allocations, which increases the chance of OOMs if DownloadImage() is
+ // misused.
+ ScopedJavaLocalRef<jobject> jbitmap = gfx::ConvertToJavaBitmap(&bitmap);
+ Java_WebContentsImpl_addToBitmapList(env, jbitmaps.obj(), jbitmap.obj());
+ }
+ for (const gfx::Size& size : sizes) {
+ Java_WebContentsImpl_createSizeAndAddToList(
+ env, jsizes.obj(), size.width(), size.height());
+ }
+ Java_WebContentsImpl_onDownloadImageFinished(
+ env, obj->obj(), callback->obj(), id,
+ http_status_code, jurl.obj(), jbitmaps.obj(), jsizes.obj());
+}
} // 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 7c890c351b6..6f4ed3d3d15 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -190,6 +190,14 @@ class CONTENT_EXPORT WebContentsAndroid
return synchronous_compositor_client_;
}
+ int DownloadImage(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jstring>& url,
+ jboolean is_fav_icon,
+ jint max_bitmap_size,
+ jboolean bypass_cache,
+ const base::android::JavaParamRef<jobject>& jcallback);
+
private:
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
@@ -199,6 +207,15 @@ class CONTENT_EXPORT WebContentsAndroid
const SkBitmap& bitmap,
ReadbackResponse response);
+ void OnFinishDownloadImage(
+ base::android::ScopedJavaGlobalRef<jobject>* obj,
+ base::android::ScopedJavaGlobalRef<jobject>* callback,
+ int id,
+ int http_status_code,
+ const GURL& url,
+ const std::vector<SkBitmap>& bitmaps,
+ const std::vector<gfx::Size>& sizes);
+
WebContentsImpl* web_contents_;
NavigationControllerAndroid navigation_controller_;
base::android::ScopedJavaGlobalRef<jobject> obj_;
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index 5621f827b46..ed4281631ae 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -65,6 +65,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/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"
@@ -95,6 +96,7 @@
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/resource_request_details.h"
#include "content/public/browser/screen_orientation_dispatcher_host.h"
@@ -114,14 +116,11 @@
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/common/web_preferences.h"
-#include "mojo/common/url_type_converters.h"
-#include "mojo/converters/geometry/geometry_type_converters.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 "skia/public/type_converters.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/accessibility/ax_tree_combiner.h"
@@ -418,6 +417,7 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
bluetooth_connected_device_count_(0),
virtual_keyboard_requested_(false),
page_scale_factor_is_one_(true),
+ mouse_lock_widget_(nullptr),
loading_weak_factory_(this),
weak_factory_(this) {
frame_tree_.SetFrameRemoveListener(
@@ -706,6 +706,8 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(FrameHostMsg_FindMatchRects_Reply,
OnFindMatchRectsReply)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_GetNearestFindResult_Reply,
+ OnGetNearestFindResultReply)
IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog,
OnOpenDateTimeDialog)
#endif
@@ -728,13 +730,6 @@ bool WebContentsImpl::HasValidFrameSource() {
return true;
}
-void WebContentsImpl::RunFileChooser(
- RenderViewHost* render_view_host,
- const FileChooserParams& params) {
- if (delegate_)
- delegate_->RunFileChooser(this, params);
-}
-
NavigationControllerImpl& WebContentsImpl::GetController() {
return controller_;
}
@@ -1219,23 +1214,6 @@ void WebContentsImpl::SetAudioMuted(bool mute) {
NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
}
-void WebContentsImpl::IncrementBluetoothConnectedDeviceCount() {
- // Notify for UI updates if the state changes.
- bluetooth_connected_device_count_++;
- if (bluetooth_connected_device_count_ == 1) {
- NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
- }
-}
-
-void WebContentsImpl::DecrementBluetoothConnectedDeviceCount() {
- // Notify for UI updates if the state changes.
- DCHECK(bluetooth_connected_device_count_ != 0);
- bluetooth_connected_device_count_--;
- if (bluetooth_connected_device_count_ == 0) {
- NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
- }
-}
-
bool WebContentsImpl::IsConnectedToBluetoothDevice() const {
return bluetooth_connected_device_count_ > 0;
}
@@ -1313,6 +1291,8 @@ void WebContentsImpl::WasShown() {
}
}
+ SendPageMessage(new PageMsg_WasShown(MSG_ROUTING_NONE));
+
last_active_time_ = base::TimeTicks::Now();
// The resize rect might have changed while this was inactive -- send the new
@@ -1342,6 +1322,8 @@ void WebContentsImpl::WasHidden() {
if (view)
view->Hide();
}
+
+ SendPageMessage(new PageMsg_WasHidden(MSG_ROUTING_NONE));
}
FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden());
@@ -1374,7 +1356,7 @@ bool WebContentsImpl::NeedToFireBeforeUnload() {
void WebContentsImpl::DispatchBeforeUnload() {
bool for_cross_site_transition = false;
- GetMainFrame()->DispatchBeforeUnload(for_cross_site_transition);
+ GetMainFrame()->DispatchBeforeUnload(for_cross_site_transition, false);
}
void WebContentsImpl::AttachToOuterWebContentsFrame(
@@ -1415,6 +1397,15 @@ void WebContentsImpl::AttachToOuterWebContentsFrame(
static_cast<RenderWidgetHostViewChildFrame*>(
render_manager->GetRenderWidgetHostView())
->RegisterSurfaceNamespaceId();
+
+ // At this point, we should destroy the TextInputManager which will notify all
+ // the RWHV in this WebContents. The RWHV in this WebContents should use the
+ // TextInputManager owned by the outer WebContents.
+ // TODO(ekaramad): Is it possible to have TextInputState before attaching to
+ // outer WebContents? In such a case, is this still the right way to hand off
+ // state tracking from inner WebContents's TextInputManager to that of the
+ // outer WebContent (crbug.com/609846)?
+ text_input_manager_.reset(nullptr);
}
void WebContentsImpl::Stop() {
@@ -1453,7 +1444,7 @@ void WebContentsImpl::Observe(int type,
// destroyed.
fullscreen_widget_had_focus_at_shutdown_ = (view && view->HasFocus());
} else {
- for (PendingWidgetViews::iterator i = pending_widget_views_.begin();
+ for (auto i = pending_widget_views_.begin();
i != pending_widget_views_.end(); ++i) {
if (host->GetView() == i->second) {
pending_widget_views_.erase(i);
@@ -1515,7 +1506,7 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
GetContentClient()->browser()->GetWebContentsViewDelegate(this);
#if defined(MOJO_SHELL_CLIENT)
- if (MojoShellConnection::Get() &&
+ if (MojoShellConnection::GetForProcess() &&
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMusInRenderer)) {
mus::Window* mus_window = aura::GetMusWindow(params.context);
@@ -1584,6 +1575,13 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
GetRenderManager()->current_frame_host()->SetRenderFrameCreated(true);
}
+ // Create the renderer process in advance if requested.
+ if (params.initialize_renderer) {
+ if (!GetRenderManager()->current_frame_host()->IsRenderFrameLive()) {
+ GetRenderManager()->InitRenderView(GetRenderViewHost(), nullptr);
+ }
+ }
+
// Ensure that observers are notified of the creation of this WebContents's
// main RenderFrameHost. It must be done here for main frames, since the
// NotifySwappedFromRenderManager expects view_ to already be created and that
@@ -1596,8 +1594,7 @@ void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) {
RemoveDestructionObserver(web_contents);
// Clear a pending contents that has been closed before being shown.
- for (PendingContents::iterator iter = pending_contents_.begin();
- iter != pending_contents_.end();
+ for (auto iter = pending_contents_.begin(); iter != pending_contents_.end();
++iter) {
if (iter->second != web_contents)
continue;
@@ -1690,6 +1687,8 @@ void WebContentsImpl::RenderWidgetDeleted(
if (fullscreen_widget_had_focus_at_shutdown_)
view_->RestoreFocus();
}
+
+ CHECK(mouse_lock_widget_ != render_widget_host);
}
void WebContentsImpl::RenderWidgetGotFocus(
@@ -1743,8 +1742,7 @@ bool WebContentsImpl::HandleWheelEvent(
// (i.e. control+tab) then the OS's buffered scroll events will come in
// with control key set which isn't what the user wants
if (delegate_ && event.wheelTicksY &&
- (event.modifiers & blink::WebInputEvent::ControlKey) &&
- !event.canScroll) {
+ !WebInputEventTraits::CanCauseScroll(event)) {
// Count only integer cumulative scrolls as zoom events; this handles
// smooth scroll and regular scroll device behavior.
zoom_scroll_remainder_ += event.wheelTicksY;
@@ -1820,11 +1818,9 @@ void WebContentsImpl::EnterFullscreenMode(const GURL& origin) {
if (delegate_)
delegate_->EnterFullscreenModeForTab(this, origin);
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidToggleFullscreenModeForTab(
- IsFullscreenForCurrentTab(
- GetRenderViewHost()->GetWidget()),
- false));
+ FOR_EACH_OBSERVER(
+ WebContentsObserver, observers_,
+ DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(), false));
}
void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
@@ -1861,17 +1857,11 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
}
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidToggleFullscreenModeForTab(
- IsFullscreenForCurrentTab(
- GetRenderViewHost()->GetWidget()),
- will_cause_resize));
+ DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(),
+ will_cause_resize));
}
-bool WebContentsImpl::IsFullscreenForCurrentTab(
- RenderWidgetHostImpl* render_widget_host) const {
- if (!RenderViewHostImpl::From(render_widget_host))
- return false;
-
+bool WebContentsImpl::IsFullscreenForCurrentTab() const {
return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false;
}
@@ -1887,26 +1877,53 @@ blink::WebDisplayMode WebContentsImpl::GetDisplayMode(
void WebContentsImpl::RequestToLockMouse(
RenderWidgetHostImpl* render_widget_host,
bool user_gesture,
- bool last_unlocked_by_target) {
- if (render_widget_host != GetRenderViewHost()->GetWidget()) {
+ bool last_unlocked_by_target,
+ bool privileged) {
+ if (mouse_lock_widget_) {
render_widget_host->GotResponseToLockMouseRequest(false);
return;
}
- if (delegate_)
+ if (privileged) {
+ mouse_lock_widget_ = render_widget_host;
+ render_widget_host->GotResponseToLockMouseRequest(true);
+ return;
+ }
+
+ bool widget_in_frame_tree = false;
+ for (FrameTreeNode* node : frame_tree_.Nodes()) {
+ if (node->current_frame_host()->GetRenderWidgetHost() ==
+ render_widget_host) {
+ widget_in_frame_tree = true;
+ break;
+ }
+ }
+
+ if (widget_in_frame_tree && delegate_) {
+ mouse_lock_widget_ = render_widget_host;
delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target);
- else
- GotResponseToLockMouseRequest(false);
+ } else {
+ render_widget_host->GotResponseToLockMouseRequest(false);
+ }
}
void WebContentsImpl::LostMouseLock(RenderWidgetHostImpl* render_widget_host) {
- if (!RenderViewHostImpl::From(render_widget_host))
- return;
+ CHECK(mouse_lock_widget_);
+ mouse_lock_widget_->SendMouseLockLost();
+ mouse_lock_widget_ = nullptr;
if (delegate_)
delegate_->LostMouseLock();
}
+bool WebContentsImpl::HasMouseLock(RenderWidgetHostImpl* render_widget_host) {
+ // To verify if the mouse is locked, the mouse_lock_widget_ needs to be
+ // assigned to the widget that requested the mouse lock, and the top-level
+ // platform RenderWidgetHostView needs to hold the mouse lock from the OS.
+ return mouse_lock_widget_ == render_widget_host &&
+ GetTopLevelRenderWidgetHostView()->IsMouseLocked();
+}
+
void WebContentsImpl::ForwardCompositorProto(
RenderWidgetHostImpl* render_widget_host,
const std::vector<uint8_t>& proto) {
@@ -2041,7 +2058,8 @@ void WebContentsImpl::CreateNewWindow(
// Save the created window associated with the route so we can show it
// later.
DCHECK_NE(MSG_ROUTING_NONE, route_id);
- pending_contents_[route_id] = new_contents;
+ pending_contents_[std::make_pair(render_process_id, route_id)] =
+ new_contents;
AddDestructionObserver(new_contents);
}
@@ -2062,9 +2080,7 @@ void WebContentsImpl::CreateNewWindow(
params.user_gesture, &was_blocked);
}
if (!was_blocked) {
- OpenURLParams open_params(params.target_url,
- Referrer(),
- CURRENT_TAB,
+ OpenURLParams open_params(params.target_url, params.referrer, CURRENT_TAB,
ui::PAGE_TRANSITION_LINK,
true /* is_renderer_initiated */);
open_params.user_gesture = params.user_gesture;
@@ -2123,7 +2139,8 @@ void WebContentsImpl::CreateNewWidget(int32_t render_process_id,
widget_view->SetPopupType(popup_type);
}
// Save the created widget associated with the route so we can show it later.
- pending_widget_views_[route_id] = widget_view;
+ pending_widget_views_[std::make_pair(render_process_id, route_id)] =
+ widget_view;
#if defined(OS_MACOSX)
// A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it
@@ -2132,11 +2149,12 @@ void WebContentsImpl::CreateNewWidget(int32_t render_process_id,
#endif
}
-void WebContentsImpl::ShowCreatedWindow(int route_id,
+void WebContentsImpl::ShowCreatedWindow(int process_id,
+ int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) {
- WebContentsImpl* contents = GetCreatedWindow(route_id);
+ WebContentsImpl* contents = GetCreatedWindow(process_id, route_id);
if (contents) {
WebContentsDelegate* delegate = GetDelegate();
contents->is_resume_pending_ = true;
@@ -2150,20 +2168,24 @@ void WebContentsImpl::ShowCreatedWindow(int route_id,
}
}
-void WebContentsImpl::ShowCreatedWidget(int route_id,
+void WebContentsImpl::ShowCreatedWidget(int process_id,
+ int route_id,
const gfx::Rect& initial_rect) {
- ShowCreatedWidget(route_id, false, initial_rect);
+ ShowCreatedWidget(process_id, route_id, false, initial_rect);
}
-void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) {
- ShowCreatedWidget(route_id, true, gfx::Rect());
+void WebContentsImpl::ShowCreatedFullscreenWidget(int process_id,
+ int route_id) {
+ ShowCreatedWidget(process_id, route_id, true, gfx::Rect());
}
-void WebContentsImpl::ShowCreatedWidget(int route_id,
+void WebContentsImpl::ShowCreatedWidget(int process_id,
+ int route_id,
bool is_fullscreen,
const gfx::Rect& initial_rect) {
RenderWidgetHostViewBase* widget_host_view =
- static_cast<RenderWidgetHostViewBase*>(GetCreatedWidget(route_id));
+ static_cast<RenderWidgetHostViewBase*>(
+ GetCreatedWidget(process_id, route_id));
if (!widget_host_view)
return;
@@ -2210,17 +2232,17 @@ void WebContentsImpl::ShowCreatedWidget(int route_id,
#endif
}
-WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) {
- PendingContents::iterator iter = pending_contents_.find(route_id);
+WebContentsImpl* WebContentsImpl::GetCreatedWindow(int process_id,
+ int route_id) {
+ auto iter = pending_contents_.find(std::make_pair(process_id, route_id));
// Certain systems can block the creation of new windows. If we didn't succeed
// in creating one, just return NULL.
- if (iter == pending_contents_.end()) {
- return NULL;
- }
+ if (iter == pending_contents_.end())
+ return nullptr;
WebContentsImpl* new_contents = iter->second;
- pending_contents_.erase(route_id);
+ pending_contents_.erase(std::make_pair(process_id, route_id));
RemoveDestructionObserver(new_contents);
// Don't initialize the guest WebContents immediately.
@@ -2229,25 +2251,26 @@ WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) {
if (!new_contents->GetRenderProcessHost()->HasConnection() ||
!new_contents->GetRenderViewHost()->GetWidget()->GetView())
- return NULL;
+ return nullptr;
return new_contents;
}
-RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int route_id) {
- PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id);
+RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int process_id,
+ int route_id) {
+ auto iter = pending_widget_views_.find(std::make_pair(process_id, route_id));
if (iter == pending_widget_views_.end()) {
DCHECK(false);
- return NULL;
+ return nullptr;
}
RenderWidgetHostView* widget_host_view = iter->second;
- pending_widget_views_.erase(route_id);
+ pending_widget_views_.erase(std::make_pair(process_id, route_id));
RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost();
if (!widget_host->GetProcess()->HasConnection()) {
// The view has gone away or the renderer crashed. Nothing to do.
- return NULL;
+ return nullptr;
}
return widget_host_view;
@@ -2354,7 +2377,7 @@ void WebContentsImpl::OnMoveValidationMessage(
void WebContentsImpl::SendScreenRects() {
for (FrameTreeNode* node : frame_tree_.Nodes()) {
- if (node->current_frame_host()->GetRenderWidgetHost())
+ if (node->current_frame_host()->is_local_root())
node->current_frame_host()->GetRenderWidgetHost()->SendScreenRects();
}
@@ -2369,6 +2392,22 @@ void WebContentsImpl::SendScreenRects() {
browser_plugin_embedder_->DidSendScreenRects();
}
+void WebContentsImpl::OnFirstPaintAfterLoad(
+ RenderWidgetHostImpl* render_widget_host) {
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ DidFirstPaintAfterLoad(render_widget_host));
+}
+
+TextInputManager* WebContentsImpl::GetTextInputManager() {
+ if (GetOuterWebContents())
+ return GetOuterWebContents()->GetTextInputManager();
+
+ if (!text_input_manager_)
+ text_input_manager_.reset(new TextInputManager());
+
+ return text_input_manager_.get();
+}
+
BrowserAccessibilityManager*
WebContentsImpl::GetRootBrowserAccessibilityManager() {
RenderFrameHostImpl* rfh = GetMainFrame();
@@ -2769,9 +2808,14 @@ void WebContentsImpl::SaveFrameWithHeaders(const GURL& url,
return;
// TODO(nasko): This check for main frame is incorrect and should be fixed
- // by explicitly passing in which frame this method should target.
+ // by explicitly passing in which frame this method should target. This would
+ // indicate whether it's the main frame, and also tell us the frame pointer
+ // to use for routing.
bool is_main_frame = (url == GetLastCommittedURL());
+ RenderFrameHost* frame_host = GetMainFrame();
+ StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
+ GetBrowserContext(), frame_host->GetSiteInstance());
DownloadManager* dlm =
BrowserContext::GetDownloadManager(GetBrowserContext());
if (!dlm)
@@ -2782,8 +2826,10 @@ void WebContentsImpl::SaveFrameWithHeaders(const GURL& url,
if (entry)
post_id = entry->GetPostID();
}
- std::unique_ptr<DownloadUrlParameters> params(
- DownloadUrlParameters::FromWebContents(this, url));
+ std::unique_ptr<DownloadUrlParameters> params(new DownloadUrlParameters(
+ url, frame_host->GetProcess()->GetID(),
+ frame_host->GetRenderViewHost()->GetRoutingID(),
+ frame_host->GetRoutingID(), storage_partition->GetURLRequestContext()));
params->set_referrer(referrer);
params->set_post_id(post_id);
if (post_id >= 0)
@@ -2935,10 +2981,12 @@ bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) {
if (GetBrowserPluginGuest())
return GetBrowserPluginGuest()->LockMouse(allowed);
- return GetRenderViewHost()
- ? GetRenderViewHost()->GetWidget()->GotResponseToLockMouseRequest(
- allowed)
- : false;
+ if (mouse_lock_widget_ &&
+ mouse_lock_widget_->GotResponseToLockMouseRequest(allowed))
+ return true;
+
+ mouse_lock_widget_ = nullptr;
+ return false;
}
bool WebContentsImpl::HasOpener() const {
@@ -3002,7 +3050,7 @@ int WebContentsImpl::DownloadImage(
}
mojo_image_downloader->DownloadImage(
- mojo::String::From(url), is_favicon, max_bitmap_size, bypass_cache,
+ url, is_favicon, max_bitmap_size, bypass_cache,
base::Bind(&WebContentsImpl::OnDidDownloadImage,
weak_factory_.GetWeakPtr(), callback, download_id, url));
return download_id;
@@ -3265,9 +3313,9 @@ void WebContentsImpl::DidNavigateMainFramePreCommit(
// No page change? Then, the renderer and browser can remain in fullscreen.
return;
}
- if (IsFullscreenForCurrentTab(GetRenderViewHost()->GetWidget()))
+ if (IsFullscreenForCurrentTab())
ExitFullscreen(false);
- DCHECK(!IsFullscreenForCurrentTab(GetRenderViewHost()->GetWidget()));
+ DCHECK(!IsFullscreenForCurrentTab());
}
void WebContentsImpl::DidNavigateMainFramePostCommit(
@@ -3595,6 +3643,12 @@ void WebContentsImpl::OnFindMatchRectsReply(
render_frame_message_source_, version, rects, active_rect);
}
+void WebContentsImpl::OnGetNearestFindResultReply(int request_id,
+ float distance) {
+ GetOrCreateFindRequestManager()->OnGetNearestFindResultReply(
+ render_frame_message_source_, request_id, distance);
+}
+
void WebContentsImpl::OnOpenDateTimeDialog(
const ViewHostMsg_DateTimeDialogValue_Params& value) {
date_time_chooser_->ShowDialog(GetTopLevelNativeWindow(),
@@ -4066,6 +4120,12 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
false));
}
+void WebContentsImpl::RunFileChooser(RenderFrameHost* render_frame_host,
+ const FileChooserParams& params) {
+ if (delegate_)
+ delegate_->RunFileChooser(render_frame_host, params);
+}
+
WebContents* WebContentsImpl::GetAsWebContents() {
return this;
}
@@ -4168,7 +4228,7 @@ void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
// Ensure fullscreen mode is exited in the |delegate_| since a crashed
// renderer may not have made a clean exit.
- if (IsFullscreenForCurrentTab(GetRenderViewHost()->GetWidget()))
+ if (IsFullscreenForCurrentTab())
ExitFullscreenMode(false);
// Cancel any visible dialogs so they are not left dangling over the sad tab.
@@ -4427,10 +4487,18 @@ void WebContentsImpl::UpdateTitle(RenderFrameHost* render_frame_host,
NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
render_frame_host->GetSiteInstance(), page_id);
- // TODO(creis): Switch to use this as the default.
NavigationEntryImpl* new_entry = controller_.GetEntryWithUniqueID(
static_cast<RenderFrameHostImpl*>(render_frame_host)->nav_entry_id());
- DCHECK_EQ(entry, new_entry);
+ 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;
+ } else {
+ // In modes that have no out-of-process iframes, nav_entry_id and page_id
+ // should agree on which entry to update.
+ DCHECK_EQ(entry, new_entry);
+ }
// We can handle title updates when we don't have an entry in
// UpdateTitleForEntry, but only if the update is from the current RVH.
@@ -4533,7 +4601,7 @@ void WebContentsImpl::OnUserInteraction(
// Exclude scroll events as user gestures for resource load dispatches.
// rdh is NULL in unittests.
if (rdh && type != blink::WebInputEvent::MouseWheel)
- rdh->OnUserGesture(this);
+ rdh->OnUserGesture();
}
void WebContentsImpl::OnIgnoredUIEvent() {
@@ -4542,7 +4610,8 @@ void WebContentsImpl::OnIgnoredUIEvent() {
}
void WebContentsImpl::RendererUnresponsive(
- RenderWidgetHostImpl* render_widget_host) {
+ RenderWidgetHostImpl* render_widget_host,
+ RenderWidgetHostDelegate::RendererUnresponsiveType type) {
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
OnRendererUnresponsive(render_widget_host));
@@ -4559,27 +4628,33 @@ void WebContentsImpl::RendererUnresponsive(
if (DevToolsAgentHost::IsDebuggerAttached(this))
return;
- if (rfhi->is_waiting_for_beforeunload_ack() ||
- rfhi->IsWaitingForUnloadACK()) {
- // Hang occurred while firing the beforeunload/unload handler.
+ // Record histograms about the type of renderer hang.
+ UMA_HISTOGRAM_ENUMERATION(
+ "ChildProcess.HangRendererType", type,
+ RenderWidgetHostDelegate::RENDERER_UNRESPONSIVE_MAX);
+
+ // We might have been waiting for both beforeunload and unload ACK.
+ // Check if tab is to be unloaded first.
+ if (rfhi->IsWaitingForUnloadACK()) {
+ // Hang occurred while firing the unload handler.
// Pretend the handler fired so tab closing continues as if it had.
GetRenderViewHost()->set_sudden_termination_allowed(true);
if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer())
return;
- // If the tab hangs in the beforeunload/unload handler there's really
- // nothing we can do to recover. If the hang is in the beforeunload handler,
- // pretend the beforeunload listeners have all fired and allow the delegate
- // to continue closing; the user will not have the option of cancelling the
- // close. Otherwise, pretend the unload listeners have all fired and close
+ // If the tab hangs in the unload handler there's really nothing we can do
+ // to recover. Pretend the unload listeners have all fired and close
// the tab.
- bool close = true;
- if (rfhi->is_waiting_for_beforeunload_ack() && delegate_) {
- delegate_->BeforeUnloadFired(this, true, &close);
- }
- if (close)
- Close();
+ Close();
+ return;
+ }
+
+ if (rfhi->is_waiting_for_beforeunload_ack()) {
+ // If the hang is in the beforeunload handler, pretend the beforeunload
+ // listeners have all fired and allow the delegate to continue closing;
+ // the user will not have the option of cancelling the close.
+ rfhi->SimulateBeforeUnloadAck();
return;
}
@@ -4821,13 +4896,12 @@ void WebContentsImpl::OnDidDownloadImage(
int id,
const GURL& image_url,
int32_t http_status_code,
- mojo::Array<skia::mojom::BitmapPtr> images,
- mojo::Array<mojo::SizePtr> original_image_sizes) {
+ mojo::Array<SkBitmap> images,
+ mojo::Array<gfx::Size> original_image_sizes) {
const std::vector<SkBitmap> bitmaps = images.To<std::vector<SkBitmap>>();
- const std::vector<gfx::Size> sizes =
- original_image_sizes.To<std::vector<gfx::Size>>();
- callback.Run(id, http_status_code, image_url, bitmaps, sizes);
+ callback.Run(id, http_status_code, image_url, bitmaps,
+ original_image_sizes.PassStorage());
}
void WebContentsImpl::OnDialogClosed(int render_process_id,
@@ -4954,6 +5028,19 @@ WebUI* WebContentsImpl::CreateWebUI(const GURL& url,
return NULL;
}
+// TODO(paulmeyer): This method will not be used until find-in-page across
+// GuestViews is implemented.
+WebContentsImpl* WebContentsImpl::GetOutermostWebContents() {
+ // Find the outer-most WebContents.
+ WebContentsImpl* outermost_web_contents = this;
+ while (outermost_web_contents->node_ &&
+ outermost_web_contents->node_->outer_web_contents()) {
+ outermost_web_contents =
+ outermost_web_contents->node_->outer_web_contents();
+ }
+ return outermost_web_contents;
+}
+
FindRequestManager* WebContentsImpl::GetOrCreateFindRequestManager() {
// TODO(paulmeyer): This method will need to access (or potentially create)
// the FindRequestManager in the outermost WebContents once find-in-page
@@ -4975,6 +5062,33 @@ void WebContentsImpl::NotifyFindReply(int request_id,
}
}
+void WebContentsImpl::IncrementBluetoothConnectedDeviceCount() {
+ // Trying to invalidate the tab state while being destroyed could result in a
+ // use after free.
+ if (IsBeingDestroyed()) {
+ return;
+ }
+ // Notify for UI updates if the state changes.
+ bluetooth_connected_device_count_++;
+ if (bluetooth_connected_device_count_ == 1) {
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ }
+}
+
+void WebContentsImpl::DecrementBluetoothConnectedDeviceCount() {
+ // Trying to invalidate the tab state while being destroyed could result in a
+ // use after free.
+ if (IsBeingDestroyed()) {
+ return;
+ }
+ // Notify for UI updates if the state changes.
+ DCHECK(bluetooth_connected_device_count_ != 0);
+ bluetooth_connected_device_count_--;
+ if (bluetooth_connected_device_count_ == 0) {
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ }
+}
+
#if defined(OS_ANDROID)
void WebContentsImpl::NotifyFindMatchRectsReply(
int version,
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index ef56b7d756f..50132917b04 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -73,6 +73,7 @@ class SavePackage;
class ScreenOrientationDispatcherHost;
class SiteInstance;
class TestWebContents;
+class TextInputManager;
class WakeLockServiceContext;
class WebContentsAudioMuter;
class WebContentsDelegate;
@@ -291,8 +292,6 @@ class CONTENT_EXPORT WebContentsImpl
int GetCapturerCount() const override;
bool IsAudioMuted() const override;
void SetAudioMuted(bool mute) override;
- void IncrementBluetoothConnectedDeviceCount();
- void DecrementBluetoothConnectedDeviceCount();
bool IsConnectedToBluetoothDevice() const override;
bool IsCrashed() const override;
void SetIsCrashed(base::TerminationStatus status, int error_code) override;
@@ -429,6 +428,8 @@ class CONTENT_EXPORT WebContentsImpl
void RunBeforeUnloadConfirm(RenderFrameHost* render_frame_host,
bool is_reload,
IPC::Message* reply_msg) override;
+ void RunFileChooser(RenderFrameHost* render_frame_host,
+ const FileChooserParams& params) override;
void DidAccessInitialDocument() override;
void DidChangeName(RenderFrameHost* render_frame_host,
const std::string& name) override;
@@ -497,8 +498,6 @@ class CONTENT_EXPORT WebContentsImpl
uint64_t upload_position,
uint64_t upload_size) override;
void Activate() override;
- void RunFileChooser(RenderViewHost* render_view_host,
- const FileChooserParams& params) override;
void UpdatePreferredSize(const gfx::Size& pref_size) override;
void CreateNewWindow(
SiteInstance* source_site_instance,
@@ -512,12 +511,15 @@ class CONTENT_EXPORT WebContentsImpl
blink::WebPopupType popup_type) override;
void CreateNewFullscreenWidget(int32_t render_process_id,
int32_t route_id) override;
- void ShowCreatedWindow(int route_id,
+ void ShowCreatedWindow(int process_id,
+ int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) override;
- void ShowCreatedWidget(int route_id, const gfx::Rect& initial_rect) override;
- void ShowCreatedFullscreenWidget(int route_id) override;
+ void ShowCreatedWidget(int process_id,
+ int route_id,
+ const gfx::Rect& initial_rect) override;
+ void ShowCreatedFullscreenWidget(int process_id, int route_id) override;
void RequestMediaAccessPermission(
const MediaStreamRequest& request,
const MediaResponseCallback& callback) override;
@@ -609,23 +611,28 @@ class CONTENT_EXPORT WebContentsImpl
void ReplicatePageFocus(bool is_focused) override;
RenderWidgetHostImpl* GetFocusedRenderWidgetHost(
RenderWidgetHostImpl* receiving_widget) override;
- void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host) override;
+ void RendererUnresponsive(
+ RenderWidgetHostImpl* render_widget_host,
+ RenderWidgetHostDelegate::RendererUnresponsiveType type) override;
void RendererResponsive(RenderWidgetHostImpl* render_widget_host) override;
void RequestToLockMouse(RenderWidgetHostImpl* render_widget_host,
bool user_gesture,
- bool last_unlocked_by_target) override;
+ bool last_unlocked_by_target,
+ bool privileged) override;
gfx::Rect GetRootWindowResizerRect(
RenderWidgetHostImpl* render_widget_host) const override;
- bool IsFullscreenForCurrentTab(
- RenderWidgetHostImpl* render_widget_host) const override;
+ bool IsFullscreenForCurrentTab() const override;
blink::WebDisplayMode GetDisplayMode(
RenderWidgetHostImpl* render_widget_host) const override;
void LostCapture(RenderWidgetHostImpl* render_widget_host) override;
void LostMouseLock(RenderWidgetHostImpl* render_widget_host) override;
+ bool HasMouseLock(RenderWidgetHostImpl* render_widget_host) override;
void ForwardCompositorProto(RenderWidgetHostImpl* render_widget_host,
const std::vector<uint8_t>& proto) override;
void OnRenderFrameProxyVisibilityChanged(bool visible) override;
void SendScreenRects() override;
+ void OnFirstPaintAfterLoad(RenderWidgetHostImpl* render_widget_host) override;
+ TextInputManager* GetTextInputManager() override;
// RenderFrameHostManager::Delegate ------------------------------------------
@@ -750,6 +757,10 @@ class CONTENT_EXPORT WebContentsImpl
int active_match_ordinal,
bool final_update);
+ // Modify the counter of connected devices for this WebContents.
+ void IncrementBluetoothConnectedDeviceCount();
+ void DecrementBluetoothConnectedDeviceCount();
+
#if defined(OS_ANDROID)
// Called by FindRequestManager when all of the find match rects are in.
void NotifyFindMatchRectsReply(int version,
@@ -757,7 +768,7 @@ class CONTENT_EXPORT WebContentsImpl
const gfx::RectF& active_rect);
#endif
-private:
+ private:
friend class WebContentsObserver;
friend class WebContents; // To implement factory methods.
@@ -779,6 +790,10 @@ private:
FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, HistoryNavigate);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, PageDoesBackAndReload);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrossSiteIframe);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ TwoSubframesCreatePopupsSimultaneously);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ TwoSubframesCreatePopupMenuWidgetsSimultaneously);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessAccessibilityBrowserTest,
CrossSiteIframeAccessibility);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
@@ -857,8 +872,8 @@ private:
int id,
const GURL& image_url,
int32_t http_status_code,
- mojo::Array<skia::mojom::BitmapPtr> images,
- mojo::Array<mojo::SizePtr> original_image_sizes);
+ mojo::Array<SkBitmap> images,
+ mojo::Array<gfx::Size> original_image_sizes);
// Callback function when showing JavaScript dialogs. Takes in a routing ID
// pair to identify the RenderFrameHost that opened the dialog, because it's
@@ -997,18 +1012,19 @@ private:
blink::WebPopupType popup_type);
// Helper for ShowCreatedWidget/ShowCreatedFullscreenWidget.
- void ShowCreatedWidget(int route_id,
+ void ShowCreatedWidget(int process_id,
+ int route_id,
bool is_fullscreen,
const gfx::Rect& initial_rect);
// Finds the new RenderWidgetHost and returns it. Note that this can only be
// called once as this call also removes it from the internal map.
- RenderWidgetHostView* GetCreatedWidget(int route_id);
+ RenderWidgetHostView* GetCreatedWidget(int process_id, int route_id);
// Finds the new WebContentsImpl by route_id, initializes it for
// renderer-initiated creation, and returns it. Note that this can only be
// called once as this call also removes it from the internal map.
- WebContentsImpl* GetCreatedWindow(int route_id);
+ WebContentsImpl* GetCreatedWindow(int process_id, int route_id);
// Sends a Page message IPC.
void SendPageMessage(IPC::Message* msg);
@@ -1071,6 +1087,9 @@ private:
void SetJavaScriptDialogManagerForTesting(
JavaScriptDialogManager* dialog_manager);
+ // Returns the outermost WebContents in this WebContents's tree.
+ WebContentsImpl* GetOutermostWebContents();
+
// Returns the FindRequestManager, or creates one if it doesn't already exist.
FindRequestManager* GetOrCreateFindRequestManager();
@@ -1091,14 +1110,13 @@ private:
RenderViewHostDelegateView* render_view_host_delegate_view_;
// Tracks created WebContentsImpl objects that have not been shown yet. They
- // are identified by the route ID passed to CreateNewWindow.
- typedef std::map<int, WebContentsImpl*> PendingContents;
- PendingContents pending_contents_;
+ // are identified by the process ID and routing ID passed to CreateNewWindow.
+ typedef std::pair<int, int> ProcessRoutingIdPair;
+ std::map<ProcessRoutingIdPair, WebContentsImpl*> pending_contents_;
- // These maps hold on to the widgets that we created on behalf of the renderer
- // that haven't shown yet.
- typedef std::map<int, RenderWidgetHostView*> PendingWidgetViews;
- PendingWidgetViews pending_widget_views_;
+ // This map holds widgets that were created on behalf of the renderer but
+ // haven't been shown yet.
+ std::map<ProcessRoutingIdPair, RenderWidgetHostView*> pending_widget_views_;
typedef std::map<WebContentsImpl*, DestructionObserver*> DestructionObservers;
DestructionObservers destruction_observers_;
@@ -1125,7 +1143,7 @@ private:
// SavePackage, lazily created.
scoped_refptr<SavePackage> save_package_;
- // Manages/coordinates find-in-page requests. Created lazily.
+ // Manages/coordinates multi-process find-in-page requests. Created lazily.
std::unique_ptr<FindRequestManager> find_request_manager_;
// Data for loading state ----------------------------------------------------
@@ -1375,6 +1393,18 @@ private:
bool page_scale_factor_is_one_;
+ // TextInputManager tracks the IME-related state for all the
+ // RenderWidgetHostViews on this WebContents. Only exists on the outermost
+ // WebContents and is automatically destroyed when a WebContents becomes an
+ // inner WebContents by attaching to an outer WebContents. Then the
+ // IME-related state for RenderWidgetHosts on the inner WebContents is tracked
+ // by the TextInputManager in the outer WebContents.
+ std::unique_ptr<TextInputManager> text_input_manager_;
+
+ // Stores the RenderWidgetHost that currently holds a mouse lock or nullptr if
+ // there's no RenderWidgetHost holding a lock.
+ RenderWidgetHostImpl* mouse_lock_widget_;
+
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 55e00c56a3f..0833357f8ae 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -252,15 +252,14 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// Navigate to an invalid URL and make sure it doesn't leave a pending entry.
LoadStopNotificationObserver load_observer1(
&shell()->web_contents()->GetController());
- ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.location.href=\"nonexistent:12121\";"));
+ ASSERT_TRUE(
+ ExecuteScript(shell(), "window.location.href=\"nonexistent:12121\";"));
load_observer1.Wait();
EXPECT_FALSE(shell()->web_contents()->GetController().GetPendingEntry());
LoadStopNotificationObserver load_observer2(
&shell()->web_contents()->GetController());
- ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.location.href=\"#foo\";"));
+ ASSERT_TRUE(ExecuteScript(shell(), "window.location.href=\"#foo\";"));
load_observer2.Wait();
EXPECT_EQ(embedded_test_server()->GetURL("/title1.html#foo"),
shell()->web_contents()->GetVisibleURL());
@@ -402,8 +401,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
NavigateToURL(shell(), kWebUIUrl);
- bool js_executed = content::ExecuteScript(shell()->web_contents(),
- kJSCodeForAppendingFrame);
+ bool js_executed = content::ExecuteScript(shell(), kJSCodeForAppendingFrame);
EXPECT_TRUE(js_executed);
}
@@ -499,7 +497,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
embedded_test_server()->GetURL("/title1.html"));
WebContentsAddedObserver new_web_contents_observer;
- ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
+ ASSERT_TRUE(ExecuteScript(shell(),
"var a = document.createElement('a');"
"a.href='./title2.html';"
"a.target = '_blank';"
@@ -699,7 +697,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ChangeDisplayMode) {
NavigateToURL(shell(), GURL("about://blank"));
- ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
+ ASSERT_TRUE(ExecuteScript(shell(),
"document.title = "
" window.matchMedia('(display-mode:"
" minimal-ui)').matches"));
@@ -709,7 +707,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ChangeDisplayMode) {
// Simulate widget is entering fullscreen (changing size is enough).
shell()->web_contents()->GetRenderViewHost()->GetWidget()->WasResized();
- ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
+ ASSERT_TRUE(ExecuteScript(shell(),
"document.title = "
" window.matchMedia('(display-mode:"
" fullscreen)').matches"));
@@ -770,6 +768,85 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ChangePageScale) {
observer.WaitForPageScaleUpdate();
}
+// Test that a direct navigation to a view-source URL works.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ViewSourceDirectNavigation) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ const GURL kUrl(embedded_test_server()->GetURL("/simple_page.html"));
+ const GURL kViewSourceURL(kViewSourceScheme + std::string(":") + kUrl.spec());
+ NavigateToURL(shell(), kViewSourceURL);
+ // Displayed view-source URLs don't include the scheme of the effective URL if
+ // the effective URL is HTTP. (e.g. view-source:example.com is displayed
+ // instead of view-source:http://example.com).
+ EXPECT_EQ(base::ASCIIToUTF16(std::string("view-source:") + kUrl.host() + ":" +
+ kUrl.port() + kUrl.path()),
+ shell()->web_contents()->GetTitle());
+ EXPECT_TRUE(shell()
+ ->web_contents()
+ ->GetController()
+ .GetLastCommittedEntry()
+ ->IsViewSourceMode());
+}
+
+// Test that window.open to a view-source URL is blocked.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ ViewSourceWindowOpen_ShouldBeBlocked) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ const GURL kUrl(embedded_test_server()->GetURL("/simple_page.html"));
+ const GURL kViewSourceURL(kViewSourceScheme + std::string(":") + kUrl.spec());
+ NavigateToURL(shell(), kUrl);
+
+ ShellAddedObserver new_shell_observer;
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "window.open('" + kViewSourceURL.spec() + "');"));
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+ EXPECT_EQ("", new_shell->web_contents()->GetURL().spec());
+ // No navigation should commit.
+ EXPECT_FALSE(
+ new_shell->web_contents()->GetController().GetLastCommittedEntry());
+}
+
+// Test that a content initiated navigation to a view-source URL is blocked.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ ViewSourceRedirect_ShouldBeBlocked) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ const GURL kUrl(embedded_test_server()->GetURL("/simple_page.html"));
+ const GURL kViewSourceURL(kViewSourceScheme + std::string(":") + kUrl.spec());
+ NavigateToURL(shell(), kUrl);
+
+ std::unique_ptr<ConsoleObserverDelegate> console_delegate(
+ new ConsoleObserverDelegate(
+ shell()->web_contents(),
+ "Not allowed to load local resource: view-source:*"));
+ shell()->web_contents()->SetDelegate(console_delegate.get());
+
+ EXPECT_TRUE(
+ ExecuteScript(shell()->web_contents(),
+ "window.location = '" + kViewSourceURL.spec() + "';"));
+ console_delegate->Wait();
+ // Original page shouldn't navigate away.
+ EXPECT_EQ(kUrl, shell()->web_contents()->GetURL());
+ EXPECT_FALSE(shell()
+ ->web_contents()
+ ->GetController()
+ .GetLastCommittedEntry()
+ ->IsViewSourceMode());
+}
+
+// Test that view source mode for a webui page can be opened.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ViewSourceWebUI) {
+ const std::string kUrl =
+ "view-source:chrome://" + std::string(kChromeUIGpuHost);
+ const GURL kGURL(kUrl);
+ NavigateToURL(shell(), kGURL);
+ EXPECT_EQ(base::ASCIIToUTF16(kUrl), shell()->web_contents()->GetTitle());
+ EXPECT_TRUE(shell()
+ ->web_contents()
+ ->GetController()
+ .GetLastCommittedEntry()
+ ->IsViewSourceMode());
+}
+
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -780,8 +857,8 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) {
ShellAddedObserver new_shell_observer;
// Open a new, named window.
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
- "window.open('about:blank','new_window');"));
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "window.open('about:blank','new_window');"));
Shell* new_shell = new_shell_observer.GetShell();
WaitForLoadStop(new_shell->web_contents());
@@ -792,7 +869,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) {
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- new_shell->web_contents(),
+ new_shell,
"window.domAutomationController.send(window.name == 'new_window');",
&success));
EXPECT_TRUE(success);
@@ -804,7 +881,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) {
// Test clicking a target=foo link.
bool success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
+ shell(),
"window.domAutomationController.send(clickSameSiteTargetedLink());",
&success));
EXPECT_TRUE(success);
@@ -854,7 +931,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// clicking on the link right away would cause the ExecuteScript to never
// return.
SetShouldProceedOnBeforeUnload(shell(), false);
- EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "clickLinkSoon()"));
+ EXPECT_TRUE(ExecuteScript(shell(), "clickLinkSoon()"));
WaitForAppModalDialog(shell());
// Have the cross-site navigation commit. The main RenderFrameHost should
@@ -1011,4 +1088,83 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
wc->SetJavaScriptDialogManagerForTesting(nullptr);
}
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ CreateWebContentsWithRendererProcess) {
+ GURL url("http://c.com/title3.html");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WebContents* base_web_contents = shell()->web_contents();
+ ASSERT_TRUE(base_web_contents);
+
+ WebContents::CreateParams create_params(
+ base_web_contents->GetBrowserContext());
+ create_params.initialize_renderer = true;
+ create_params.initial_size =
+ base_web_contents->GetContainerBounds().size();
+ std::unique_ptr<WebContents> web_contents(WebContents::Create(create_params));
+ ASSERT_TRUE(web_contents);
+
+ // There is no navigation (to about:blank or something like that).
+ EXPECT_FALSE(web_contents->IsLoading());
+
+ ASSERT_TRUE(web_contents->GetMainFrame());
+ EXPECT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
+ EXPECT_TRUE(web_contents->GetController().IsInitialBlankNavigation());
+ int renderer_id = web_contents->GetRenderProcessHost()->GetID();
+
+ TestNavigationObserver same_tab_observer(web_contents.get(), 1);
+ NavigationController::LoadURLParams params(url);
+ params.transition_type = ui::PageTransitionFromInt(
+ ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
+ web_contents->GetController().LoadURLWithParams(params);
+ same_tab_observer.Wait();
+
+ // Check that pre-warmed process is used.
+ EXPECT_EQ(renderer_id, web_contents->GetRenderProcessHost()->GetID());
+ EXPECT_EQ(1, web_contents->GetController().GetEntryCount());
+ NavigationEntry* entry =
+ web_contents->GetController().GetLastCommittedEntry();
+ ASSERT_TRUE(entry);
+ EXPECT_EQ(url, entry->GetURL());
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ NavigatingToWebUIDoesNotUsePreWarmedProcess) {
+ GURL web_ui_url(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost));
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WebContents* base_web_contents = shell()->web_contents();
+ ASSERT_TRUE(base_web_contents);
+
+ WebContents::CreateParams create_params(
+ base_web_contents->GetBrowserContext());
+ create_params.initialize_renderer = true;
+ create_params.initial_size =
+ base_web_contents->GetContainerBounds().size();
+ std::unique_ptr<WebContents> web_contents(WebContents::Create(create_params));
+ ASSERT_TRUE(web_contents);
+
+ // There is no navigation (to about:blank or something like that).
+ EXPECT_FALSE(web_contents->IsLoading());
+
+ ASSERT_TRUE(web_contents->GetMainFrame());
+ EXPECT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
+ EXPECT_TRUE(web_contents->GetController().IsInitialBlankNavigation());
+ int renderer_id = web_contents->GetRenderProcessHost()->GetID();
+
+ TestNavigationObserver same_tab_observer(web_contents.get(), 1);
+ NavigationController::LoadURLParams params(web_ui_url);
+ params.transition_type = ui::PageTransitionFromInt(
+ ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
+ web_contents->GetController().LoadURLWithParams(params);
+ same_tab_observer.Wait();
+
+ // Check that pre-warmed process isn't used.
+ EXPECT_NE(renderer_id, web_contents->GetRenderProcessHost()->GetID());
+ EXPECT_EQ(1, web_contents->GetController().GetEntryCount());
+ NavigationEntry* entry =
+ web_contents->GetController().GetLastCommittedEntry();
+ ASSERT_TRUE(entry);
+ EXPECT_EQ(web_ui_url, entry->GetURL());
+}
+
} // 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 e6f350002cd..0c13e0614c8 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -49,8 +49,8 @@
#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
-#include "net/base/test_data_directory.h"
#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
#include "url/url_constants.h"
@@ -405,29 +405,46 @@ TEST_F(WebContentsImplTest, UseTitleFromPendingEntryIfSet) {
EXPECT_EQ(title, contents()->GetTitle());
}
-// Test view source mode for a webui page.
-TEST_F(WebContentsImplTest, NTPViewSource) {
+// Browser initiated navigations to view-source URLs of WebUI pages should work.
+TEST_F(WebContentsImplTest, DirectNavigationToViewSourceWebUI) {
NavigationControllerImpl& cont =
static_cast<NavigationControllerImpl&>(controller());
- const char kUrl[] = "view-source:chrome://blah";
- const GURL kGURL(kUrl);
+ const GURL kGURL("view-source:chrome://blah");
+ // NavigationControllerImpl rewrites view-source URLs, simulating that here.
+ const GURL kRewrittenURL("chrome://blah");
process()->sink().ClearMessages();
- cont.LoadURL(
- kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ // Use LoadURLWithParams instead of LoadURL, because the former properly
+ // rewrites view-source:chrome://blah URLs to chrome://blah.
+ NavigationController::LoadURLParams load_params(kGURL);
+ load_params.transition_type = ui::PAGE_TRANSITION_TYPED;
+ load_params.extra_headers = "content-type: text/plain";
+ load_params.load_type = NavigationController::LOAD_TYPE_DEFAULT;
+ load_params.is_renderer_initiated = false;
+ controller().LoadURLWithParams(load_params);
+
int entry_id = cont.GetPendingEntry()->GetUniqueID();
// Did we get the expected message?
EXPECT_TRUE(process()->sink().GetFirstMessageMatching(
FrameMsg_EnableViewSourceMode::ID));
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- InitNavigateParams(&params, 0, entry_id, true, kGURL,
+ InitNavigateParams(&params, 0, entry_id, true, kRewrittenURL,
ui::PAGE_TRANSITION_TYPED);
contents()->GetMainFrame()->PrepareForCommit();
+ contents()->GetMainFrame()->OnMessageReceived(
+ FrameHostMsg_DidStartProvisionalLoad(1, kRewrittenURL,
+ base::TimeTicks::Now()));
contents()->GetMainFrame()->SendNavigateWithParams(&params);
- // Also check title and url.
- EXPECT_EQ(base::ASCIIToUTF16(kUrl), contents()->GetTitle());
+
+ // This is the virtual URL.
+ EXPECT_EQ(base::ASCIIToUTF16("view-source:chrome://blah"),
+ contents()->GetTitle());
+
+ // The actual URL navigated to.
+ EXPECT_EQ(kRewrittenURL,
+ contents()->GetController().GetLastCommittedEntry()->GetURL());
}
// Test to ensure UpdateMaxPageID is working properly.
@@ -1320,11 +1337,13 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) {
// Go back within the site.
controller().GoBack();
+ contents()->GetMainFrame()->PrepareForCommit();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(entry2, controller().GetPendingEntry());
// Before that commits, go back again.
controller().GoBack();
+ contents()->GetMainFrame()->PrepareForCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
EXPECT_TRUE(contents()->GetPendingMainFrame());
EXPECT_EQ(entry1, controller().GetPendingEntry());
@@ -1530,11 +1549,11 @@ TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
- EXPECT_FALSE(contents()->IsFullscreenForCurrentTab(test_rvh()->GetWidget()));
+ EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
orig_rfh->OnMessageReceived(
FrameHostMsg_ToggleFullscreen(orig_rfh->GetRoutingID(), true));
- EXPECT_TRUE(contents()->IsFullscreenForCurrentTab(test_rvh()->GetWidget()));
+ EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));
// Navigate to a new site.
@@ -1548,7 +1567,7 @@ TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
ui::PAGE_TRANSITION_TYPED);
// Confirm fullscreen has exited.
- EXPECT_FALSE(contents()->IsFullscreenForCurrentTab(test_rvh()->GetWidget()));
+ EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
contents()->SetDelegate(nullptr);
@@ -1583,14 +1602,14 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Sanity-check: Confirm we're not starting out in fullscreen mode.
- EXPECT_FALSE(contents()->IsFullscreenForCurrentTab(test_rvh()->GetWidget()));
+ EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
for (int i = 0; i < 2; ++i) {
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
orig_rfh->OnMessageReceived(
FrameHostMsg_ToggleFullscreen(orig_rfh->GetRoutingID(), true));
- EXPECT_TRUE(contents()->IsFullscreenForCurrentTab(test_rvh()->GetWidget()));
+ EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));
// Navigate backward (or forward).
@@ -1607,8 +1626,7 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
orig_rfh->SimulateNavigationStop();
// Confirm fullscreen has exited.
- EXPECT_FALSE(
- contents()->IsFullscreenForCurrentTab(test_rvh()->GetWidget()));
+ EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
}
@@ -1647,18 +1665,18 @@ TEST_F(WebContentsImplTest, CrashExitsFullscreen) {
url, ui::PAGE_TRANSITION_TYPED);
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
- EXPECT_FALSE(contents()->IsFullscreenForCurrentTab(test_rvh()->GetWidget()));
+ EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
contents()->GetMainFrame()->OnMessageReceived(FrameHostMsg_ToggleFullscreen(
contents()->GetMainFrame()->GetRoutingID(), true));
- EXPECT_TRUE(contents()->IsFullscreenForCurrentTab(test_rvh()->GetWidget()));
+ EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));
// Crash the renderer.
main_test_rfh()->GetProcess()->SimulateCrash();
// Confirm fullscreen has exited.
- EXPECT_FALSE(contents()->IsFullscreenForCurrentTab(test_rvh()->GetWidget()));
+ EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
contents()->SetDelegate(nullptr);
@@ -2637,9 +2655,10 @@ TEST_F(WebContentsImplTest, PendingContents) {
std::unique_ptr<TestWebContents> other_contents(
static_cast<TestWebContents*>(CreateTestWebContents()));
contents()->AddPendingContents(other_contents.get());
+ int process_id = other_contents->GetRenderViewHost()->GetProcess()->GetID();
int route_id = other_contents->GetRenderViewHost()->GetRoutingID();
other_contents.reset();
- EXPECT_EQ(nullptr, contents()->GetCreatedWindow(route_id));
+ EXPECT_EQ(nullptr, contents()->GetCreatedWindow(process_id, route_id));
}
TEST_F(WebContentsImplTest, CapturerOverridesPreferredSize) {
@@ -2805,43 +2824,34 @@ TEST_F(WebContentsImplTest, HandleWheelEvent) {
EXPECT_FALSE(contents()->HandleWheelEvent(event));
EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
- modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey |
- WebInputEvent::ControlKey;
- event =
- SyntheticWebMouseWheelEventBuilder::Build(0, 0, 0, 1, modifiers, false);
- EXPECT_FALSE(contents()->HandleWheelEvent(event));
- EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
-
- // But whenever the ctrl modifier is applied with canScroll=false, they can
- // increase/decrease zoom. Except on MacOS where we never want to adjust zoom
+ // But whenever the ctrl modifier is applied zoom can be increased or
+ // decreased. Except on MacOS where we never want to adjust zoom
// with mousewheel.
modifiers = WebInputEvent::ControlKey;
event =
SyntheticWebMouseWheelEventBuilder::Build(0, 0, 0, 1, modifiers, false);
- event.canScroll = false;
bool handled = contents()->HandleWheelEvent(event);
-#if defined(OS_MACOSX)
- EXPECT_FALSE(handled);
- EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
-#else
+#if defined(USE_AURA)
EXPECT_TRUE(handled);
EXPECT_EQ(1, delegate->GetAndResetContentsZoomChangedCallCount());
EXPECT_TRUE(delegate->last_zoom_in());
+#else
+ EXPECT_FALSE(handled);
+ EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
#endif
modifiers = WebInputEvent::ControlKey | WebInputEvent::ShiftKey |
WebInputEvent::AltKey;
event =
SyntheticWebMouseWheelEventBuilder::Build(0, 0, 2, -5, modifiers, false);
- event.canScroll = false;
handled = contents()->HandleWheelEvent(event);
-#if defined(OS_MACOSX)
- EXPECT_FALSE(handled);
- EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
-#else
+#if defined(USE_AURA)
EXPECT_TRUE(handled);
EXPECT_EQ(1, delegate->GetAndResetContentsZoomChangedCallCount());
EXPECT_FALSE(delegate->last_zoom_in());
+#else
+ EXPECT_FALSE(handled);
+ EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
#endif
// Unless there is no vertical movement.
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 63856d1e2de..cff51f58318 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -1033,8 +1033,14 @@ void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
return;
ui::EventType type = event->type();
- if (type == ui::ET_MOUSE_PRESSED)
- web_contents_->GetDelegate()->ActivateContents(web_contents_);
+ if (type == ui::ET_MOUSE_PRESSED) {
+ // Linux window managers like to handle raise-on-click themselves. If we
+ // raise-on-click manually, this may override user settings that prevent
+ // focus-stealing.
+#if !defined(USE_X11) || defined (OS_CHROMEOS)
+ web_contents_->GetDelegate()->ActivateContents(web_contents_);
+#endif
+ }
web_contents_->GetDelegate()->ContentsMouseEvent(
web_contents_, display::Screen::GetScreen()->GetCursorScreenPoint(),
@@ -1049,6 +1055,9 @@ void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
current_drop_data_.reset(new DropData());
PrepareDropData(current_drop_data_.get(), event.data());
+
+ web_contents_->GetRenderViewHost()->FilterDropData(current_drop_data_.get());
+
blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
// Give the delegate an opportunity to cancel the drag.
@@ -1064,7 +1073,7 @@ void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
gfx::Point screen_pt = display::Screen::GetScreen()->GetCursorScreenPoint();
web_contents_->GetRenderViewHost()->DragTargetDragEnter(
- *current_drop_data_.get(), event.location(), screen_pt, op,
+ *current_drop_data_, event.location(), screen_pt, op,
ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
if (drag_dest_delegate_) {
@@ -1117,7 +1126,8 @@ int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
return ui::DragDropTypes::DRAG_NONE;
web_contents_->GetRenderViewHost()->DragTargetDrop(
- event.location(), display::Screen::GetScreen()->GetCursorScreenPoint(),
+ *current_drop_data_, event.location(),
+ display::Screen::GetScreen()->GetCursorScreenPoint(),
ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
if (drag_dest_delegate_)
drag_dest_delegate_->OnDrop();
@@ -1134,4 +1144,21 @@ void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window* window,
web_contents_->UpdateWebContentsVisibility(visible);
}
+#if defined(USE_EXTERNAL_POPUP_MENU)
+void WebContentsViewAura::ShowPopupMenu(RenderFrameHost* render_frame_host,
+ const gfx::Rect& bounds,
+ int item_height,
+ double item_font_size,
+ int selected_item,
+ const std::vector<MenuItem>& items,
+ bool right_aligned,
+ bool allow_multiple_selection) {
+ NOTIMPLEMENTED() << " show " << items.size() << " menu items";
+}
+
+void WebContentsViewAura::HidePopupMenu() {
+ NOTIMPLEMENTED();
+}
+#endif
+
} // namespace content
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 856ccadd30c..18a3ec2781a 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -122,6 +122,18 @@ class CONTENT_EXPORT WebContentsViewAura
void UpdateDragCursor(blink::WebDragOperation operation) override;
void GotFocus() override;
void TakeFocus(bool reverse) override;
+#if defined(USE_EXTERNAL_POPUP_MENU)
+ void ShowPopupMenu(RenderFrameHost* render_frame_host,
+ const gfx::Rect& bounds,
+ int item_height,
+ double item_font_size,
+ int selected_item,
+ const std::vector<MenuItem>& items,
+ bool right_aligned,
+ bool allow_multiple_selection) override;
+
+ void HidePopupMenu() override;
+#endif
// Overridden from OverscrollControllerDelegate:
gfx::Rect GetVisibleBounds() const override;
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index a06161ba284..021bf6b9660 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -5,6 +5,7 @@
#include "content/browser/web_contents/web_contents_view_aura.h"
#include <stddef.h>
+#include <tuple>
#include "base/command_line.h"
#include "base/location.h"
@@ -224,8 +225,8 @@ class InputEventMessageFilterWaitsForAcks : public BrowserMessageFilter {
if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
InputHostMsg_HandleInputEvent_ACK::Param params;
InputHostMsg_HandleInputEvent_ACK::Read(&message, &params);
- blink::WebInputEvent::Type type = base::get<0>(params).type;
- InputEventAckState ack = base::get<0>(params).state;
+ blink::WebInputEvent::Type type = std::get<0>(params).type;
+ InputEventAckState ack = std::get<0>(params).state;
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&InputEventMessageFilterWaitsForAcks::ReceivedEventAck,
this, type, ack));
@@ -383,9 +384,7 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
int ExecuteScriptAndExtractInt(const std::string& script) {
int value = 0;
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
- shell()->web_contents(),
- "domAutomationController.send(" + script + ")",
- &value));
+ shell(), "domAutomationController.send(" + script + ")", &value));
return value;
}
@@ -499,7 +498,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
ui::EventProcessor* dispatcher = content->GetHost()->event_processor();
gfx::Rect bounds = content->GetBoundsInRootWindow();
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::TouchEvent press(
ui::ET_TOUCH_PRESSED,
gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5), 0,
@@ -1032,7 +1031,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_VerticalOverscroll) {
{
int kXStep = bounds.width() / 10;
gfx::Point location(bounds.right() - kXStep, bounds.y() + 5);
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, location, 0, timestamp);
ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
ASSERT_FALSE(details.dispatcher_destroyed);
@@ -1064,7 +1063,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_VerticalOverscroll) {
int kYStep = bounds.height() / 10;
gfx::Point location(bounds.x() + 10, bounds.y() + kYStep);
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, location, 0, timestamp);
ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
ASSERT_FALSE(details.dispatcher_destroyed);
@@ -1098,7 +1097,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_VerticalOverscroll) {
int kXStep = bounds.width() / 10;
int kYStep = bounds.height() / 10;
gfx::Point location = bounds.origin() + gfx::Vector2d(0, kYStep);
- base::TimeDelta timestamp = ui::EventTimeForNow();
+ base::TimeTicks timestamp = ui::EventTimeForNow();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, location, 0, timestamp);
ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
ASSERT_FALSE(details.dispatcher_destroyed);
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 b87c8b96365..78fbfe943a7 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -226,8 +226,7 @@ void WebContentsViewMac::UpdateDragCursor(WebDragOperation operation) {
}
void WebContentsViewMac::GotFocus() {
- // This is only used in the views FocusManager stuff but it bleeds through
- // all subclasses. http://crbug.com/21875
+ web_contents_->NotifyWebContentsFocused();
}
// This is called when the renderer asks us to take focus back (i.e., it has
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 fc94fecd8ec..565ed314c86 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mus.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_mus.cc
@@ -6,7 +6,7 @@
#include "build/build_config.h"
#include "components/mus/public/cpp/window.h"
-#include "components/mus/public/cpp/window_tree_connection.h"
+#include "components/mus/public/cpp/window_tree_client.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_mus.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -30,7 +30,7 @@ WebContentsViewMus::WebContentsViewMus(
: web_contents_(web_contents), delegate_(delegate) {
DCHECK(parent_window);
*delegate_view = this;
- mus::Window* window = parent_window->connection()->NewWindow();
+ mus::Window* window = parent_window->window_tree()->NewWindow();
window->SetVisible(true);
window->SetBounds(gfx::Rect(300, 300));
parent_window->AddChild(window);
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 ec3b00035dd..d549b548937 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
@@ -130,6 +130,7 @@ int GetModifierFlags() {
dropData.reset(new DropData());
[self populateDropData:dropData.get()
fromPasteboard:[info draggingPasteboard]];
+ currentRVH_->FilterDropData(dropData.get());
NSDragOperation mask = [info draggingSourceOperationMask];
@@ -142,7 +143,7 @@ int GetModifierFlags() {
return NSDragOperationNone;
if ([self onlyAllowsNavigation]) {
- if ([[info draggingPasteboard] containsURLData])
+ if ([[info draggingPasteboard] containsURLDataConvertingTextToURL:YES])
return NSDragOperationCopy;
return NSDragOperationNone;
}
@@ -200,7 +201,7 @@ int GetModifierFlags() {
return NSDragOperationNone;
if ([self onlyAllowsNavigation]) {
- if ([[info draggingPasteboard] containsURLData])
+ if ([[info draggingPasteboard] containsURLDataConvertingTextToURL:YES])
return NSDragOperationCopy;
return NSDragOperationNone;
}
@@ -231,7 +232,7 @@ int GetModifierFlags() {
// Check if we only allow navigation and navigate to a url on the pasteboard.
if ([self onlyAllowsNavigation]) {
NSPasteboard* pboard = [info draggingPasteboard];
- if ([pboard containsURLData]) {
+ if ([pboard containsURLDataConvertingTextToURL:YES]) {
GURL url;
ui::PopulateURLAndTitleFromPasteboard(&url, NULL, pboard, YES);
webContents_->OpenURL(OpenURLParams(
@@ -254,9 +255,8 @@ int GetModifierFlags() {
NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
webContents_->GetRenderViewHost()->DragTargetDrop(
- gfx::Point(viewPoint.x, viewPoint.y),
- gfx::Point(screenPoint.x, screenPoint.y),
- GetModifierFlags());
+ *dropData_, gfx::Point(viewPoint.x, viewPoint.y),
+ gfx::Point(screenPoint.x, screenPoint.y), GetModifierFlags());
dropData_.reset();
diff --git a/chromium/content/browser/webui/shared_resources_data_source.cc b/chromium/content/browser/webui/shared_resources_data_source.cc
index aa1289c279e..7e5baf3337e 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.cc
+++ b/chromium/content/browser/webui/shared_resources_data_source.cc
@@ -112,12 +112,15 @@ std::string SharedResourcesDataSource::GetMimeType(
#if defined(OS_WIN)
base::FilePath file(base::UTF8ToWide(path));
- std::string extension = base::WideToUTF8(file.FinalExtension()).substr(1);
+ std::string extension = base::WideToUTF8(file.FinalExtension());
#else
base::FilePath file(path);
- std::string extension = file.FinalExtension().substr(1);
+ std::string extension = file.FinalExtension();
#endif
+ if (!extension.empty())
+ extension.erase(0, 1);
+
if (extension == "html")
return "text/html";
@@ -139,7 +142,7 @@ std::string SharedResourcesDataSource::GetMimeType(
if (extension == "woff2")
return "application/font-woff2";
- CHECK(false) << path;
+ NOTREACHED() << path;
return "text/plain";
}
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index ff5d602d422..87f332bf6a3 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -53,11 +53,10 @@ namespace content {
namespace {
const char kChromeURLContentSecurityPolicyHeaderBase[] =
- "Content-Security-Policy: script-src chrome://resources 'self'";
+ "Content-Security-Policy: ";
const char kChromeURLXFrameOptionsHeader[] = "X-Frame-Options: DENY";
static const char kNetworkErrorKey[] = "netError";
-const int kNoRenderProcessId = -1;
bool SchemeIsInSchemes(const std::string& scheme,
const std::vector<std::string>& schemes) {
@@ -154,9 +153,24 @@ class URLRequestChromeJob : public net::URLRequestJob {
content_security_policy_object_source_ = data;
}
- void set_content_security_policy_frame_source(
+ void set_content_security_policy_script_source(
const std::string& data) {
- content_security_policy_frame_source_ = data;
+ content_security_policy_script_source_ = data;
+ }
+
+ void set_content_security_policy_child_source(
+ const std::string& data) {
+ content_security_policy_child_source_ = data;
+ }
+
+ void set_content_security_policy_style_source(
+ const std::string& data) {
+ content_security_policy_style_source_ = data;
+ }
+
+ void set_content_security_policy_image_source(
+ const std::string& data) {
+ content_security_policy_image_source_ = data;
}
void set_deny_xframe_options(bool deny_xframe_options) {
@@ -181,17 +195,15 @@ class URLRequestChromeJob : public net::URLRequestJob {
// Helper for Start(), to let us start asynchronously.
// (This pattern is shared by most net::URLRequestJob implementations.)
- void StartAsync(bool allowed);
+ void StartAsync();
- // Called on the UI thread to check if this request is allowed.
- static void CheckStoragePartitionMatches(
- int render_process_id,
- const GURL& url,
+ // Due to a race condition, DevTools relies on a legacy thread hop to the UI
+ // thread before calling StartAsync.
+ // TODO(caseq): Fix the race condition and remove this thread hop in
+ // https://crbug.com/616641.
+ static void DelayStartForDevTools(
const base::WeakPtr<URLRequestChromeJob>& job);
- // Specific resources require unsafe-eval in the Content Security Policy.
- bool RequiresUnsafeEval() const;
-
// Do the actual copy from data_ (the data we're serving) into |buf|.
// Separate from ReadRawData so we can handle async I/O. Returns the number of
// bytes read.
@@ -216,8 +228,11 @@ class URLRequestChromeJob : public net::URLRequestJob {
bool add_content_security_policy_;
// These are used with the CSP.
+ std::string content_security_policy_script_source_;
std::string content_security_policy_object_source_;
- std::string content_security_policy_frame_source_;
+ std::string content_security_policy_child_source_;
+ std::string content_security_policy_style_source_;
+ std::string content_security_policy_image_source_;
// If true, sets the "X-Frame-Options: DENY" header.
bool deny_xframe_options_;
@@ -249,8 +264,6 @@ URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request,
pending_buf_size_(0),
allow_caching_(true),
add_content_security_policy_(true),
- content_security_policy_object_source_("object-src 'none';"),
- content_security_policy_frame_source_("frame-src 'none';"),
deny_xframe_options_(true),
send_content_type_header_(false),
is_incognito_(is_incognito),
@@ -264,19 +277,29 @@ URLRequestChromeJob::~URLRequestChromeJob() {
}
void URLRequestChromeJob::Start() {
- int render_process_id, unused;
- bool is_renderer_request = ResourceRequestInfo::GetRenderFrameForRequest(
- request_, &render_process_id, &unused);
- if (!is_renderer_request)
- render_process_id = kNoRenderProcessId;
- BrowserThread::PostTask(
- BrowserThread::UI,
+ const GURL url = request_->url();
+
+ // Due to a race condition, DevTools relies on a legacy thread hop to the UI
+ // thread before calling StartAsync.
+ // TODO(caseq): Fix the race condition and remove this thread hop in
+ // https://crbug.com/616641.
+ if (url.SchemeIs(kChromeDevToolsScheme)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&URLRequestChromeJob::DelayStartForDevTools,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+
+ // Start reading asynchronously so that all error reporting and data
+ // callbacks happen as they would for network requests.
+ base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&URLRequestChromeJob::CheckStoragePartitionMatches,
- render_process_id, request_->url(),
- weak_factory_.GetWeakPtr()));
+ base::Bind(&URLRequestChromeJob::StartAsync, weak_factory_.GetWeakPtr()));
+
TRACE_EVENT_ASYNC_BEGIN1("browser", "DataManager:Request", this, "URL",
- request_->url().possibly_invalid_spec());
+ url.possibly_invalid_spec());
}
void URLRequestChromeJob::Kill() {
@@ -306,9 +329,11 @@ void URLRequestChromeJob::GetResponseInfo(net::HttpResponseInfo* info) {
// response headers.
if (add_content_security_policy_) {
std::string base = kChromeURLContentSecurityPolicyHeaderBase;
- base.append(RequiresUnsafeEval() ? " 'unsafe-eval'; " : "; ");
+ base.append(content_security_policy_script_source_);
base.append(content_security_policy_object_source_);
- base.append(content_security_policy_frame_source_);
+ base.append(content_security_policy_child_source_);
+ base.append(content_security_policy_style_source_);
+ base.append(content_security_policy_image_source_);
info->headers->AddHeader(base);
}
@@ -386,57 +411,24 @@ int URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size) {
return buf_size;
}
-void URLRequestChromeJob::CheckStoragePartitionMatches(
- int render_process_id,
- const GURL& url,
+void URLRequestChromeJob::DelayStartForDevTools(
const base::WeakPtr<URLRequestChromeJob>& job) {
- // The embedder could put some webui pages in separate storage partition.
- // RenderProcessHostImpl::IsSuitableHost would guard against top level pages
- // being in the same process. We do an extra check to guard against an
- // exploited renderer pretending to add them as a subframe. We skip this check
- // for resources.
- bool allowed = false;
- std::vector<std::string> hosts;
- GetContentClient()->
- browser()->GetAdditionalWebUIHostsToIgnoreParititionCheck(&hosts);
- if (url.SchemeIs(kChromeUIScheme) &&
- (url.SchemeIs(kChromeUIScheme) ||
- std::find(hosts.begin(), hosts.end(), url.host()) != hosts.end())) {
- allowed = true;
- } else if (render_process_id == kNoRenderProcessId) {
- // Request was not issued by renderer.
- allowed = true;
- } else {
- RenderProcessHost* process = RenderProcessHost::FromID(render_process_id);
- if (process) {
- StoragePartition* partition = BrowserContext::GetStoragePartitionForSite(
- process->GetBrowserContext(), url);
- allowed = partition == process->GetStoragePartition();
- }
- }
-
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&URLRequestChromeJob::StartAsync, job, allowed));
+ base::Bind(&URLRequestChromeJob::StartAsync, job));
}
-void URLRequestChromeJob::StartAsync(bool allowed) {
+void URLRequestChromeJob::StartAsync() {
if (!request_)
return;
- if (!allowed || !backend_->StartRequest(request_, this)) {
+ if (!backend_->StartRequest(request_, this)) {
NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
net::ERR_INVALID_URL));
}
}
-// TODO(tsepez,mfoltz): Refine this method when tests have been fixed to not use
-// eval()/new Function(). http://crbug.com/525224
-bool URLRequestChromeJob::RequiresUnsafeEval() const {
- return true;
-}
-
namespace {
// Gets mime type for data that is available from |source| by |path|.
@@ -629,10 +621,16 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
job->set_allow_caching(source->source()->AllowCaching());
job->set_add_content_security_policy(
source->source()->ShouldAddContentSecurityPolicy());
+ job->set_content_security_policy_script_source(
+ source->source()->GetContentSecurityPolicyScriptSrc());
job->set_content_security_policy_object_source(
source->source()->GetContentSecurityPolicyObjectSrc());
- job->set_content_security_policy_frame_source(
- source->source()->GetContentSecurityPolicyFrameSrc());
+ job->set_content_security_policy_child_source(
+ source->source()->GetContentSecurityPolicyChildSrc());
+ job->set_content_security_policy_style_source(
+ source->source()->GetContentSecurityPolicyStyleSrc());
+ job->set_content_security_policy_image_source(
+ source->source()->GetContentSecurityPolicyImgSrc());
job->set_deny_xframe_options(
source->source()->ShouldDenyXFrameOptions());
job->set_send_content_type_header(
diff --git a/chromium/content/browser/webui/url_data_manager_backend_unittest.cc b/chromium/content/browser/webui/url_data_manager_backend_unittest.cc
index f52c8084e61..fdf50037d74 100644
--- a/chromium/content/browser/webui/url_data_manager_backend_unittest.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend_unittest.cc
@@ -43,7 +43,8 @@ class CancelAfterFirstReadURLRequestDelegate : public net::TestDelegate {
class UrlDataManagerBackendTest : public testing::Test {
public:
- UrlDataManagerBackendTest() {
+ UrlDataManagerBackendTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
// URLRequestJobFactory takes ownership of the passed in ProtocolHandler.
url_request_job_factory_.SetProtocolHandler(
"chrome", URLDataManagerBackend::CreateProtocolHandler(
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 0a4c3416497..2c091282f99 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.cc
@@ -66,10 +66,10 @@ class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
return parent_->object_src_;
return URLDataSource::GetContentSecurityPolicyObjectSrc();
}
- std::string GetContentSecurityPolicyFrameSrc() const override {
+ std::string GetContentSecurityPolicyChildSrc() const override {
if (parent_->frame_src_set_)
return parent_->frame_src_;
- return URLDataSource::GetContentSecurityPolicyFrameSrc();
+ return URLDataSource::GetContentSecurityPolicyChildSrc();
}
bool ShouldDenyXFrameOptions() const override {
return parent_->deny_xframe_options_;
@@ -169,7 +169,7 @@ void WebUIDataSourceImpl::OverrideContentSecurityPolicyObjectSrc(
object_src_ = data;
}
-void WebUIDataSourceImpl::OverrideContentSecurityPolicyFrameSrc(
+void WebUIDataSourceImpl::OverrideContentSecurityPolicyChildSrc(
const std::string& data) {
frame_src_set_ = true;
frame_src_ = data;
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 811007a0291..2cc738cfd25 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.h
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.h
@@ -42,7 +42,7 @@ class CONTENT_EXPORT WebUIDataSourceImpl
void DisableReplaceExistingSource() override;
void DisableContentSecurityPolicy() override;
void OverrideContentSecurityPolicyObjectSrc(const std::string& data) override;
- void OverrideContentSecurityPolicyFrameSrc(const std::string& data) override;
+ void OverrideContentSecurityPolicyChildSrc(const std::string& data) override;
void DisableDenyXFrameOptions() override;
protected:
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 2fc48e67572..543c70d2de0 100644
--- a/chromium/content/browser/webui/web_ui_data_source_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
@@ -33,7 +33,7 @@ class TestClient : public TestContentClient {
return base::string16();
}
- base::RefCountedStaticMemory* GetDataResourceBytes(
+ base::RefCountedMemory* GetDataResourceBytes(
int resource_id) const override {
base::RefCountedStaticMemory* bytes = NULL;
if (resource_id == kDummyDefaultResourceId) {
diff --git a/chromium/content/browser/webui/web_ui_impl.cc b/chromium/content/browser/webui/web_ui_impl.cc
index 41fc037852c..880029a3ee1 100644
--- a/chromium/content/browser/webui/web_ui_impl.cc
+++ b/chromium/content/browser/webui/web_ui_impl.cc
@@ -18,8 +18,10 @@
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/view_messages.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "content/public/common/bindings_policy.h"
@@ -27,6 +29,26 @@
namespace content {
+class WebUIImpl::MainFrameNavigationObserver : public WebContentsObserver {
+ public:
+ MainFrameNavigationObserver(WebUIImpl* web_ui, WebContents* contents)
+ : WebContentsObserver(contents), web_ui_(web_ui) {}
+ ~MainFrameNavigationObserver() override {}
+
+ private:
+ void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+ // Only disallow JavaScript on cross-document navigations in the main frame.
+ if (!navigation_handle->IsInMainFrame() ||
+ !navigation_handle->HasCommitted() || navigation_handle->IsSamePage()) {
+ return;
+ }
+
+ web_ui_->DisallowJavascriptOnAllHandlers();
+ }
+
+ WebUIImpl* web_ui_;
+};
+
const WebUI::TypeID WebUI::kNoWebUI = NULL;
// static
@@ -50,6 +72,7 @@ WebUIImpl::WebUIImpl(WebContents* contents, const std::string& frame_name)
: link_transition_type_(ui::PAGE_TRANSITION_LINK),
bindings_(BINDINGS_POLICY_WEB_UI),
web_contents_(contents),
+ web_contents_observer_(new MainFrameNavigationObserver(this, contents)),
frame_name_(frame_name) {
DCHECK(contents);
}
@@ -95,9 +118,10 @@ void WebUIImpl::RenderViewReused(RenderViewHost* render_view_host,
GURL site_url = render_view_host->GetSiteInstance()->GetSiteURL();
GetContentClient()->browser()->LogWebUIUrl(site_url);
}
+}
- for (WebUIMessageHandler* handler : handlers_)
- handler->RenderViewReused();
+void WebUIImpl::RenderFrameHostSwappingOut() {
+ DisallowJavascriptOnAllHandlers();
}
WebContents* WebUIImpl::GetWebContents() const {
@@ -154,23 +178,23 @@ bool WebUIImpl::CanCallJavascript() {
target_frame->GetLastCommittedURL().spec() == url::kAboutBlankURL);
}
-void WebUIImpl::CallJavascriptFunction(const std::string& function_name) {
+void WebUIImpl::CallJavascriptFunctionUnsafe(const std::string& function_name) {
DCHECK(base::IsStringASCII(function_name));
base::string16 javascript = base::ASCIIToUTF16(function_name + "();");
ExecuteJavascript(javascript);
}
-void WebUIImpl::CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg) {
+void WebUIImpl::CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg) {
DCHECK(base::IsStringASCII(function_name));
std::vector<const base::Value*> args;
args.push_back(&arg);
ExecuteJavascript(GetJavascriptCall(function_name, args));
}
-void WebUIImpl::CallJavascriptFunction(
- const std::string& function_name,
- const base::Value& arg1, const base::Value& arg2) {
+void WebUIImpl::CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2) {
DCHECK(base::IsStringASCII(function_name));
std::vector<const base::Value*> args;
args.push_back(&arg1);
@@ -178,9 +202,10 @@ void WebUIImpl::CallJavascriptFunction(
ExecuteJavascript(GetJavascriptCall(function_name, args));
}
-void WebUIImpl::CallJavascriptFunction(
- const std::string& function_name,
- const base::Value& arg1, const base::Value& arg2, const base::Value& arg3) {
+void WebUIImpl::CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2,
+ const base::Value& arg3) {
DCHECK(base::IsStringASCII(function_name));
std::vector<const base::Value*> args;
args.push_back(&arg1);
@@ -189,12 +214,11 @@ void WebUIImpl::CallJavascriptFunction(
ExecuteJavascript(GetJavascriptCall(function_name, args));
}
-void WebUIImpl::CallJavascriptFunction(
- const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2,
- const base::Value& arg3,
- const base::Value& arg4) {
+void WebUIImpl::CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2,
+ const base::Value& arg3,
+ const base::Value& arg4) {
DCHECK(base::IsStringASCII(function_name));
std::vector<const base::Value*> args;
args.push_back(&arg1);
@@ -204,7 +228,7 @@ void WebUIImpl::CallJavascriptFunction(
ExecuteJavascript(GetJavascriptCall(function_name, args));
}
-void WebUIImpl::CallJavascriptFunction(
+void WebUIImpl::CallJavascriptFunctionUnsafe(
const std::string& function_name,
const std::vector<const base::Value*>& args) {
DCHECK(base::IsStringASCII(function_name));
@@ -233,6 +257,10 @@ void WebUIImpl::ProcessWebUIMessage(const GURL& source_url,
}
}
+ScopedVector<WebUIMessageHandler>* WebUIImpl::GetHandlersForTesting() {
+ return &handlers_;
+}
+
// WebUIImpl, protected: -------------------------------------------------------
void WebUIImpl::AddMessageHandler(WebUIMessageHandler* handler) {
@@ -275,4 +303,9 @@ void WebUIImpl::AddToSetIfFrameNameMatches(
frame_set->insert(host);
}
+void WebUIImpl::DisallowJavascriptOnAllHandlers() {
+ for (WebUIMessageHandler* handler : handlers_)
+ handler->DisallowJavascript();
+}
+
} // namespace content
diff --git a/chromium/content/browser/webui/web_ui_impl.h b/chromium/content/browser/webui/web_ui_impl.h
index 268c7576e80..752f8395469 100644
--- a/chromium/content/browser/webui/web_ui_impl.h
+++ b/chromium/content/browser/webui/web_ui_impl.h
@@ -36,6 +36,9 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
// 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 the owning RenderFrameHost has started swapping out.
+ void RenderFrameHostSwappingOut();
+
// WebUI implementation:
WebContents* GetWebContents() const override;
WebUIController* GetController() const override;
@@ -56,29 +59,32 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
const std::string& message,
const base::ListValue& args) override;
bool CanCallJavascript() override;
- void CallJavascriptFunction(const std::string& function_name) override;
- void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg) override;
- void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2) override;
- void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2,
- const base::Value& arg3) override;
- void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2,
- const base::Value& arg3,
- const base::Value& arg4) override;
- void CallJavascriptFunction(
+ void CallJavascriptFunctionUnsafe(const std::string& function_name) override;
+ void CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg) override;
+ void CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2) override;
+ void CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2,
+ const base::Value& arg3) override;
+ void CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2,
+ const base::Value& arg3,
+ const base::Value& arg4) override;
+ void CallJavascriptFunctionUnsafe(
const std::string& function_name,
const std::vector<const base::Value*>& args) override;
+ ScopedVector<WebUIMessageHandler>* GetHandlersForTesting() override;
// IPC::Listener implementation:
bool OnMessageReceived(const IPC::Message& message) override;
private:
+ class MainFrameNavigationObserver;
+
// IPC message handling.
void OnWebUISend(const GURL& source_url,
const std::string& message,
@@ -97,6 +103,9 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
void AddToSetIfFrameNameMatches(std::set<RenderFrameHost*>* frame_set,
RenderFrameHost* host);
+ // Called internally and by the owned MainFrameNavigationObserver.
+ void DisallowJavascriptOnAllHandlers();
+
// A map of message name -> message handling callback.
typedef std::map<std::string, MessageCallback> MessageCallbackMap;
MessageCallbackMap message_callbacks_;
@@ -114,6 +123,9 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
// Non-owning pointer to the WebContents this WebUI is associated with.
WebContents* web_contents_;
+ // Notifies this WebUI about notifications in the main frame.
+ std::unique_ptr<MainFrameNavigationObserver> web_contents_observer_;
+
// The name of the frame this WebUI is embedded in. If empty, the main frame
// is used.
const std::string frame_name_;
diff --git a/chromium/content/browser/webui/web_ui_message_handler.cc b/chromium/content/browser/webui/web_ui_message_handler.cc
index 56e0adcbbaa..2a768b066dc 100644
--- a/chromium/content/browser/webui/web_ui_message_handler.cc
+++ b/chromium/content/browser/webui/web_ui_message_handler.cc
@@ -11,6 +11,10 @@
namespace content {
+void WebUIMessageHandler::AllowJavascriptForTesting() {
+ AllowJavascript();
+}
+
void WebUIMessageHandler::AllowJavascript() {
if (javascript_allowed_)
return;
@@ -69,8 +73,20 @@ base::string16 WebUIMessageHandler::ExtractStringValue(
return base::string16();
}
-void WebUIMessageHandler::RenderViewReused() {
- DisallowJavascript();
+void WebUIMessageHandler::ResolveJavascriptCallback(
+ const base::Value& callback_id,
+ const base::Value& response) {
+ // cr.webUIResponse is a global JS function exposed from cr.js.
+ CallJavascriptFunction("cr.webUIResponse", callback_id,
+ base::FundamentalValue(true), response);
+}
+
+void WebUIMessageHandler::RejectJavascriptCallback(
+ const base::Value& callback_id,
+ const base::Value& response) {
+ // cr.webUIResponse is a global JS function exposed from cr.js.
+ CallJavascriptFunction("cr.webUIResponse", callback_id,
+ base::FundamentalValue(false), response);
}
} // namespace content
diff --git a/chromium/content/browser/webui/web_ui_message_handler_unittest.cc b/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
index cd12a3e8d61..46a0829ea35 100644
--- a/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
@@ -18,32 +18,32 @@ TEST(WebUIMessageHandlerTest, ExtractIntegerValue) {
base::string16 neg_string(base::UTF8ToUTF16("-1234"));
base::string16 pos_string(base::UTF8ToUTF16("1234"));
- list.Append(new base::FundamentalValue(zero_value));
+ list.AppendInteger(zero_value);
EXPECT_TRUE(WebUIMessageHandler::ExtractIntegerValue(&list, &value));
EXPECT_EQ(value, zero_value);
list.Clear();
- list.Append(new base::FundamentalValue(neg_value));
+ list.AppendInteger(neg_value);
EXPECT_TRUE(WebUIMessageHandler::ExtractIntegerValue(&list, &value));
EXPECT_EQ(value, neg_value);
list.Clear();
- list.Append(new base::FundamentalValue(pos_value));
+ list.AppendInteger(pos_value);
EXPECT_TRUE(WebUIMessageHandler::ExtractIntegerValue(&list, &value));
EXPECT_EQ(value, pos_value);
list.Clear();
- list.Append(new base::StringValue(zero_string));
+ list.AppendString(zero_string);
EXPECT_TRUE(WebUIMessageHandler::ExtractIntegerValue(&list, &value));
EXPECT_EQ(value, zero_value);
list.Clear();
- list.Append(new base::StringValue(neg_string));
+ list.AppendString(neg_string);
EXPECT_TRUE(WebUIMessageHandler::ExtractIntegerValue(&list, &value));
EXPECT_EQ(value, neg_value);
list.Clear();
- list.Append(new base::StringValue(pos_string));
+ list.AppendString(pos_string);
EXPECT_TRUE(WebUIMessageHandler::ExtractIntegerValue(&list, &value));
EXPECT_EQ(value, pos_value);
}
@@ -55,32 +55,32 @@ TEST(WebUIMessageHandlerTest, ExtractDoubleValue) {
base::string16 neg_string(base::UTF8ToUTF16("-1234.5"));
base::string16 pos_string(base::UTF8ToUTF16("1234.5"));
- list.Append(new base::FundamentalValue(zero_value));
+ list.AppendDouble(zero_value);
EXPECT_TRUE(WebUIMessageHandler::ExtractDoubleValue(&list, &value));
EXPECT_DOUBLE_EQ(value, zero_value);
list.Clear();
- list.Append(new base::FundamentalValue(neg_value));
+ list.AppendDouble(neg_value);
EXPECT_TRUE(WebUIMessageHandler::ExtractDoubleValue(&list, &value));
EXPECT_DOUBLE_EQ(value, neg_value);
list.Clear();
- list.Append(new base::FundamentalValue(pos_value));
+ list.AppendDouble(pos_value);
EXPECT_TRUE(WebUIMessageHandler::ExtractDoubleValue(&list, &value));
EXPECT_DOUBLE_EQ(value, pos_value);
list.Clear();
- list.Append(new base::StringValue(zero_string));
+ list.AppendString(zero_string);
EXPECT_TRUE(WebUIMessageHandler::ExtractDoubleValue(&list, &value));
EXPECT_DOUBLE_EQ(value, zero_value);
list.Clear();
- list.Append(new base::StringValue(neg_string));
+ list.AppendString(neg_string);
EXPECT_TRUE(WebUIMessageHandler::ExtractDoubleValue(&list, &value));
EXPECT_DOUBLE_EQ(value, neg_value);
list.Clear();
- list.Append(new base::StringValue(pos_string));
+ list.AppendString(pos_string);
EXPECT_TRUE(WebUIMessageHandler::ExtractDoubleValue(&list, &value));
EXPECT_DOUBLE_EQ(value, pos_value);
}
@@ -89,7 +89,7 @@ TEST(WebUIMessageHandlerTest, ExtractStringValue) {
base::ListValue list;
base::string16 in_string(base::UTF8ToUTF16(
"The facts, though interesting, are irrelevant."));
- list.Append(new base::StringValue(in_string));
+ list.AppendString(in_string);
base::string16 out_string = WebUIMessageHandler::ExtractStringValue(&list);
EXPECT_EQ(in_string, out_string);
}
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index 5edfb2c3ff4..c3220264681 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
@@ -22,7 +23,6 @@
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/service_registry.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -31,12 +31,22 @@
#include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/test/test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/shell/public/cpp/interface_registry.h"
namespace content {
namespace {
+base::FilePath GetFilePathForJSResource(const std::string& path) {
+ std::string binding_path = "gen/" + path + ".js";
+#if defined(OS_WIN)
+ base::ReplaceChars(binding_path, "//", "\\", &binding_path);
+#endif
+ base::FilePath exe_dir;
+ PathService::Get(base::DIR_EXE, &exe_dir);
+ return exe_dir.AppendASCII(binding_path);
+}
+
bool got_message = false;
// The bindings for the page are generated from a .mojom file. This code looks
@@ -45,8 +55,7 @@ bool GetResource(const std::string& id,
const WebUIDataSource::GotDataCallback& callback) {
if (id.find(".mojom") != std::string::npos) {
std::string contents;
- CHECK(base::ReadFileToString(mojo::test::GetFilePathForJSResource(id),
- &contents))
+ CHECK(base::ReadFileToString(GetFilePathForJSResource(id), &contents))
<< id;
base::RefCountedString* ref_contents = new base::RefCountedString;
ref_contents->data() = contents;
@@ -74,7 +83,7 @@ class BrowserTargetImpl : public mojom::BrowserTarget {
~BrowserTargetImpl() override {}
// mojom::BrowserTarget overrides:
- void Start(const mojo::Closure& closure) override {
+ void Start(const StartCallback& closure) override {
closure.Run();
}
void Stop() override {
@@ -121,7 +130,7 @@ class PingTestWebUIController : public TestWebUIController {
// WebUIController overrides:
void RenderViewCreated(RenderViewHost* render_view_host) override {
- render_view_host->GetMainFrame()->GetServiceRegistry()->AddService(
+ render_view_host->GetMainFrame()->GetInterfaceRegistry()->AddInterface(
base::Bind(&PingTestWebUIController::CreateHandler,
base::Unretained(this)));
}
@@ -189,8 +198,7 @@ bool IsGeneratedResourceAvailable(const std::string& resource_path) {
// files. If the bindings file doesn't exist assume we're on such a bot and
// pass.
// TODO(sky): remove this conditional when isolates support copying from gen.
- const base::FilePath test_file_path(
- mojo::test::GetFilePathForJSResource(resource_path));
+ const base::FilePath test_file_path(GetFilePathForJSResource(resource_path));
if (base::PathExists(test_file_path))
return true;
LOG(WARNING) << " mojom binding file doesn't exist, assuming on isolate";
diff --git a/chromium/content/browser/zygote_host/zygote_communication_linux.cc b/chromium/content/browser/zygote_host/zygote_communication_linux.cc
index fc7b5053d80..77488bdb16b 100644
--- a/chromium/content/browser/zygote_host/zygote_communication_linux.cc
+++ b/chromium/content/browser/zygote_host/zygote_communication_linux.cc
@@ -16,46 +16,18 @@
#include "base/pickle.h"
#include "base/posix/eintr_wrapper.h"
#include "base/posix/unix_domain_socket_linux.h"
-#include "content/browser/renderer_host/render_sandbox_host_linux.h"
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
-#include "content/common/child_process_sandbox_support_impl_linux.h"
#include "content/common/zygote_commands_linux.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
-#include "sandbox/linux/services/namespace_sandbox.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
#include "ui/display/display_switches.h"
-#include "ui/gfx/switches.h"
namespace content {
-namespace {
-
-// Receive a fixed message on fd and return the sender's PID.
-// Returns true if the message received matches the expected message.
-bool ReceiveFixedMessage(int fd,
- const char* expect_msg,
- size_t expect_len,
- base::ProcessId* sender_pid) {
- char buf[expect_len + 1];
- std::vector<base::ScopedFD> fds_vec;
-
- const ssize_t len = base::UnixDomainSocket::RecvMsgWithPid(
- fd, buf, sizeof(buf), &fds_vec, sender_pid);
- if (static_cast<size_t>(len) != expect_len)
- return false;
- if (memcmp(buf, expect_msg, expect_len) != 0)
- return false;
- if (!fds_vec.empty())
- return false;
- return true;
-}
-
-} // namespace
-
ZygoteCommunication::ZygoteCommunication()
- : control_fd_(-1),
+ : control_fd_(),
control_lock_(),
pid_(),
list_of_running_zygote_children_(),
@@ -68,7 +40,7 @@ ZygoteCommunication::~ZygoteCommunication() {}
bool ZygoteCommunication::SendMessage(const base::Pickle& data,
const std::vector<int>* fds) {
- DCHECK_NE(-1, control_fd_);
+ DCHECK(control_fd_.is_valid());
CHECK(data.size() <= kZygoteMaxMessageLength)
<< "Trying to send too-large message to zygote (sending " << data.size()
<< " bytes, max is " << kZygoteMaxMessageLength << ")";
@@ -77,17 +49,18 @@ bool ZygoteCommunication::SendMessage(const base::Pickle& data,
<< "(sending " << fds->size() << ", max is "
<< base::UnixDomainSocket::kMaxFileDescriptors << ")";
- return base::UnixDomainSocket::SendMsg(control_fd_, data.data(), data.size(),
+ return base::UnixDomainSocket::SendMsg(control_fd_.get(), data.data(),
+ data.size(),
fds ? *fds : std::vector<int>());
}
ssize_t ZygoteCommunication::ReadSandboxStatus() {
- DCHECK_NE(-1, control_fd_);
+ DCHECK(control_fd_.is_valid());
// At startup we send a kZygoteCommandGetSandboxStatus request to the zygote,
// but don't wait for the reply. Thus, the first time that we read from the
// zygote, we get the reply to that request.
ssize_t bytes_read = HANDLE_EINTR(
- read(control_fd_, &sandbox_status_, sizeof(sandbox_status_)));
+ read(control_fd_.get(), &sandbox_status_, sizeof(sandbox_status_)));
if (bytes_read != sizeof(sandbox_status_)) {
return -1;
}
@@ -95,7 +68,7 @@ ssize_t ZygoteCommunication::ReadSandboxStatus() {
}
ssize_t ZygoteCommunication::ReadReply(void* buf, size_t buf_len) {
- DCHECK_NE(-1, control_fd_);
+ DCHECK(control_fd_.is_valid());
if (!have_read_sandbox_status_word_) {
if (ReadSandboxStatus() == -1) {
return -1;
@@ -104,7 +77,7 @@ ssize_t ZygoteCommunication::ReadReply(void* buf, size_t buf_len) {
UMA_HISTOGRAM_SPARSE_SLOWLY("Linux.SandboxStatus", sandbox_status_);
}
- return HANDLE_EINTR(read(control_fd_, buf, buf_len));
+ return HANDLE_EINTR(read(control_fd_.get(), buf, buf_len));
}
pid_t ZygoteCommunication::ForkRequest(
@@ -265,13 +238,6 @@ void ZygoteCommunication::Init() {
cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kZygoteProcess);
- int fds[2];
- CHECK(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
- CHECK(base::UnixDomainSocket::EnableReceiveProcessId(fds[0]));
- base::FileHandleMappingVector fds_to_map;
- fds_to_map.push_back(std::make_pair(fds[1], kZygoteSocketPairFd));
-
- base::LaunchOptions options;
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
if (browser_command_line.HasSwitch(switches::kZygoteCmdPrefix)) {
@@ -297,75 +263,7 @@ void ZygoteCommunication::Init() {
GetContentClient()->browser()->AppendExtraCommandLineSwitches(&cmd_line, -1);
- const bool using_namespace_sandbox =
- ZygoteHostImpl::GetInstance()->ShouldUseNamespaceSandbox();
- // A non empty sandbox_cmd means we want a SUID sandbox.
- const bool using_suid_sandbox =
- !ZygoteHostImpl::GetInstance()->SandboxCommand().empty() &&
- !using_namespace_sandbox;
-
- // Start up the sandbox host process and get the file descriptor for the
- // renderers to talk to it.
- const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
- fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD()));
-
- base::ScopedFD dummy_fd;
- if (using_suid_sandbox) {
- std::unique_ptr<sandbox::SetuidSandboxHost> sandbox_host(
- sandbox::SetuidSandboxHost::Create());
- sandbox_host->PrependWrapper(&cmd_line);
- sandbox_host->SetupLaunchOptions(&options, &fds_to_map, &dummy_fd);
- sandbox_host->SetupLaunchEnvironment();
- }
-
- options.fds_to_remap = &fds_to_map;
- base::Process process =
- using_namespace_sandbox
- ? sandbox::NamespaceSandbox::LaunchProcess(cmd_line, options)
- : base::LaunchProcess(cmd_line, options);
- CHECK(process.IsValid()) << "Failed to launch zygote process";
-
- dummy_fd.reset();
-
- if (using_suid_sandbox || using_namespace_sandbox) {
- // The SUID sandbox will execute the zygote in a new PID namespace, and
- // the main zygote process will then fork from there. Watch now our
- // elaborate dance to find and validate the zygote's PID.
-
- // First we receive a message from the zygote boot process.
- base::ProcessId boot_pid;
- CHECK(ReceiveFixedMessage(fds[0], kZygoteBootMessage,
- sizeof(kZygoteBootMessage), &boot_pid));
-
- // Within the PID namespace, the zygote boot process thinks it's PID 1,
- // but its real PID can never be 1. This gives us a reliable test that
- // the kernel is translating the sender's PID to our namespace.
- CHECK_GT(boot_pid, 1)
- << "Received invalid process ID for zygote; kernel might be too old? "
- "See crbug.com/357670 or try using --"
- << switches::kDisableSetuidSandbox << " to workaround.";
-
- // Now receive the message that the zygote's ready to go, along with the
- // main zygote process's ID.
- CHECK(ReceiveFixedMessage(fds[0], kZygoteHelloMessage,
- sizeof(kZygoteHelloMessage), &pid_));
- CHECK_GT(pid_, 1);
-
- if (process.Pid() != pid_) {
- // Reap the sandbox.
- base::EnsureProcessGetsReaped(process.Pid());
- }
- } else {
- // Not using the SUID sandbox.
- // Note that ~base::Process() will reset the internal value, but there's no
- // real "handle" on POSIX so that is safe.
- pid_ = process.Pid();
- }
-
- close(fds[1]);
- control_fd_ = fds[0];
-
- ZygoteHostImpl::GetInstance()->AddZygotePid(pid_);
+ pid_ = ZygoteHostImpl::GetInstance()->LaunchZygote(&cmd_line, &control_fd_);
base::Pickle pickle;
pickle.WriteInt(kZygoteCommandGetSandboxStatus);
diff --git a/chromium/content/browser/zygote_host/zygote_communication_linux.h b/chromium/content/browser/zygote_host/zygote_communication_linux.h
index 2766618a936..32a2822b9f2 100644
--- a/chromium/content/browser/zygote_host/zygote_communication_linux.h
+++ b/chromium/content/browser/zygote_host/zygote_communication_linux.h
@@ -7,13 +7,22 @@
#include <memory>
#include <set>
+#include <string>
#include <vector>
+#include <sys/types.h>
+
+#include "base/files/scoped_file.h"
#include "base/process/kill.h"
+#include "base/process/process_handle.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/public/browser/file_descriptor_info.h"
+namespace base {
+class Pickle;
+} // namespace base
+
namespace content {
class CONTENT_EXPORT ZygoteCommunication {
@@ -53,9 +62,6 @@ class CONTENT_EXPORT ZygoteCommunication {
int GetSandboxStatus();
private:
- // Whether we should use the namespace sandbox instead of the setuid sandbox.
- bool ShouldUseNamespaceSandbox();
-
// Should be called every time a Zygote child is born.
void ZygoteChildBorn(pid_t process);
@@ -70,7 +76,7 @@ class CONTENT_EXPORT ZygoteCommunication {
// Get the sandbox status from the zygote.
ssize_t ReadSandboxStatus();
- int control_fd_; // the socket to the zygote.
+ base::ScopedFD control_fd_; // the socket to the zygote.
// A lock protecting all communication with the zygote. This lock must be
// acquired before sending a command and released after the result has been
// received.
diff --git a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
index e798f96fd7a..38b8cf6b3b5 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -4,26 +4,59 @@
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
+#include <sys/socket.h>
+
#include "base/allocator/allocator_extension.h"
-#include "base/command_line.h"
#include "base/files/file_enumerator.h"
+#include "base/posix/unix_domain_socket_linux.h"
#include "base/process/kill.h"
#include "base/process/memory.h"
#include "base/strings/string_number_conversions.h"
-#include "content/public/browser/content_browser_client.h"
+#include "content/browser/renderer_host/render_sandbox_host_linux.h"
+#include "content/common/child_process_sandbox_support_impl_linux.h"
+#include "content/common/zygote_commands_linux.h"
#include "content/public/common/content_switches.h"
#include "sandbox/linux/services/credentials.h"
+#include "sandbox/linux/services/namespace_sandbox.h"
+#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
#include "sandbox/linux/suid/common/sandbox.h"
namespace content {
+namespace {
+
+// Receive a fixed message on fd and return the sender's PID.
+// Returns true if the message received matches the expected message.
+bool ReceiveFixedMessage(int fd,
+ const char* expect_msg,
+ size_t expect_len,
+ base::ProcessId* sender_pid) {
+ // Allocate an extra byte of buffer space so we can check that we received
+ // exactly |expect_len| bytes, and the message wasn't just truncated to fit.
+ char buf[expect_len + 1];
+ std::vector<base::ScopedFD> fds_vec;
+
+ const ssize_t len = base::UnixDomainSocket::RecvMsgWithPid(
+ fd, buf, sizeof(buf), &fds_vec, sender_pid);
+ if (static_cast<size_t>(len) != expect_len)
+ return false;
+ if (memcmp(buf, expect_msg, expect_len) != 0)
+ return false;
+ if (!fds_vec.empty())
+ return false;
+ return true;
+}
+
+} // namespace
+
// static
ZygoteHost* ZygoteHost::GetInstance() {
return ZygoteHostImpl::GetInstance();
}
ZygoteHostImpl::ZygoteHostImpl()
- : should_use_namespace_sandbox_(true),
+ : use_namespace_sandbox_(false),
+ use_suid_sandbox_(false),
use_suid_sandbox_for_adj_oom_score_(false),
sandbox_binary_(),
zygote_pids_lock_(),
@@ -36,34 +69,50 @@ ZygoteHostImpl* ZygoteHostImpl::GetInstance() {
return base::Singleton<ZygoteHostImpl>::get();
}
-void ZygoteHostImpl::Init(const std::string& sandbox_cmd) {
- sandbox_binary_ = sandbox_cmd;
-
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kNoSandbox) ||
- command_line.HasSwitch(switches::kDisableNamespaceSandbox) ||
- !sandbox::Credentials::CanCreateProcessInNewUserNS()) {
- should_use_namespace_sandbox_ = false;
+void ZygoteHostImpl::Init(const base::CommandLine& command_line) {
+ if (command_line.HasSwitch(switches::kNoSandbox)) {
+ return;
}
- const bool using_namespace_sandbox = ShouldUseNamespaceSandbox();
- // A non empty sandbox_cmd means we want a SUID sandbox.
- const bool using_suid_sandbox =
- !sandbox_binary_.empty() && !using_namespace_sandbox;
+ {
+ std::unique_ptr<sandbox::SetuidSandboxHost> setuid_sandbox_host(
+ sandbox::SetuidSandboxHost::Create());
+ sandbox_binary_ = setuid_sandbox_host->GetSandboxBinaryPath().value();
+ }
- // Use the SUID sandbox for adjusting OOM scores when we are using the setuid
- // sandbox. This is needed beacuse the processes are non-dumpable, so
- // /proc/pid/oom_score_adj can only be written by root.
- use_suid_sandbox_for_adj_oom_score_ = using_suid_sandbox;
+ if (!command_line.HasSwitch(switches::kDisableNamespaceSandbox) &&
+ sandbox::Credentials::CanCreateProcessInNewUserNS()) {
+ use_namespace_sandbox_ = true;
#if defined(OS_CHROMEOS)
- // Chrome OS has a kernel patch that restricts oom_score_adj. See
- // crbug.com/576409 for details.
- if (!sandbox_binary_.empty()) {
- use_suid_sandbox_for_adj_oom_score_ = true;
- }
+ // Chrome OS has a kernel patch that restricts oom_score_adj. See
+ // crbug.com/576409 for details.
+ if (!sandbox_binary_.empty()) {
+ use_suid_sandbox_for_adj_oom_score_ = true;
+ } else {
+ LOG(ERROR) << "SUID sandbox binary is missing. Won't be able to adjust "
+ "OOM scores.";
+ }
#endif
+ } else if (!command_line.HasSwitch(switches::kDisableSetuidSandbox) &&
+ !sandbox_binary_.empty()) {
+ use_suid_sandbox_ = true;
+
+ // Use the SUID sandbox for adjusting OOM scores when we are using
+ // the setuid sandbox. This is needed beacuse the processes are
+ // non-dumpable, so /proc/pid/oom_score_adj can only be written by
+ // root.
+ use_suid_sandbox_for_adj_oom_score_ = use_suid_sandbox_;
+ } else {
+ LOG(FATAL)
+ << "No usable sandbox! Update your kernel or see "
+ "https://chromium.googlesource.com/chromium/src/+/master/"
+ "docs/linux_suid_sandbox_development.md for more information on "
+ "developing with the SUID sandbox. "
+ "If you want to live dangerously and need an immediate workaround, "
+ "you can try using --"
+ << switches::kNoSandbox << ".";
+ }
}
void ZygoteHostImpl::AddZygotePid(pid_t pid) {
@@ -76,10 +125,6 @@ bool ZygoteHostImpl::IsZygotePid(pid_t pid) {
return zygote_pids_.find(pid) != zygote_pids_.end();
}
-const std::string& ZygoteHostImpl::SandboxCommand() const {
- return sandbox_binary_;
-}
-
void ZygoteHostImpl::SetRendererSandboxStatus(int status) {
renderer_sandbox_status_ = status;
}
@@ -88,8 +133,78 @@ int ZygoteHostImpl::GetRendererSandboxStatus() const {
return renderer_sandbox_status_;
}
-bool ZygoteHostImpl::ShouldUseNamespaceSandbox() {
- return should_use_namespace_sandbox_;
+pid_t ZygoteHostImpl::LaunchZygote(base::CommandLine* cmd_line,
+ base::ScopedFD* control_fd) {
+ int fds[2];
+ CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
+ CHECK(base::UnixDomainSocket::EnableReceiveProcessId(fds[0]));
+
+ base::FileHandleMappingVector fds_to_map;
+ fds_to_map.push_back(std::make_pair(fds[1], kZygoteSocketPairFd));
+
+ // Start up the sandbox host process and get the file descriptor for the
+ // renderers to talk to it.
+ const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
+ fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD()));
+
+ base::LaunchOptions options;
+ base::ScopedFD dummy_fd;
+ if (use_suid_sandbox_) {
+ std::unique_ptr<sandbox::SetuidSandboxHost> sandbox_host(
+ sandbox::SetuidSandboxHost::Create());
+ sandbox_host->PrependWrapper(cmd_line);
+ sandbox_host->SetupLaunchOptions(&options, &fds_to_map, &dummy_fd);
+ sandbox_host->SetupLaunchEnvironment();
+ }
+
+ options.fds_to_remap = &fds_to_map;
+ base::Process process =
+ use_namespace_sandbox_
+ ? sandbox::NamespaceSandbox::LaunchProcess(*cmd_line, options)
+ : base::LaunchProcess(*cmd_line, options);
+ CHECK(process.IsValid()) << "Failed to launch zygote process";
+
+ dummy_fd.reset();
+ close(fds[1]);
+ control_fd->reset(fds[0]);
+
+ pid_t pid = process.Pid();
+
+ if (use_namespace_sandbox_ || use_suid_sandbox_) {
+ // The namespace and SUID sandbox will execute the zygote in a new
+ // PID namespace, and the main zygote process will then fork from
+ // there. Watch now our elaborate dance to find and validate the
+ // zygote's PID.
+
+ // First we receive a message from the zygote boot process.
+ base::ProcessId boot_pid;
+ CHECK(ReceiveFixedMessage(fds[0], kZygoteBootMessage,
+ sizeof(kZygoteBootMessage), &boot_pid));
+
+ // Within the PID namespace, the zygote boot process thinks it's PID 1,
+ // but its real PID can never be 1. This gives us a reliable test that
+ // the kernel is translating the sender's PID to our namespace.
+ CHECK_GT(boot_pid, 1)
+ << "Received invalid process ID for zygote; kernel might be too old? "
+ "See crbug.com/357670 or try using --"
+ << switches::kNoSandbox << " to workaround.";
+
+ // Now receive the message that the zygote's ready to go, along with the
+ // main zygote process's ID.
+ pid_t real_pid;
+ CHECK(ReceiveFixedMessage(fds[0], kZygoteHelloMessage,
+ sizeof(kZygoteHelloMessage), &real_pid));
+ CHECK_GT(real_pid, 1);
+
+ if (real_pid != pid) {
+ // Reap the sandbox.
+ base::EnsureProcessGetsReaped(pid);
+ }
+ pid = real_pid;
+ }
+
+ AddZygotePid(pid);
+ return pid;
}
#if !defined(OS_OPENBSD)
diff --git a/chromium/content/browser/zygote_host/zygote_host_impl_linux.h b/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
index e42a222913f..ee70bd6900b 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
@@ -10,6 +10,8 @@
#include <set>
#include <string>
+#include "base/command_line.h"
+#include "base/files/scoped_file.h"
#include "base/process/process_handle.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/zygote_host_linux.h"
@@ -26,21 +28,15 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
// Returns the singleton instance.
static ZygoteHostImpl* GetInstance();
- void Init(const std::string& sandbox_cmd);
-
- // Retrieves the sandbox command passed into Init();
- const std::string& SandboxCommand() const;
-
- // Tells the ZygoteHost the PIDs of all the zygotes.
- void AddZygotePid(pid_t pid);
+ void Init(const base::CommandLine& cmd_line);
// Returns whether or not this pid is the pid of a zygote.
bool IsZygotePid(pid_t pid) override;
- bool ShouldUseNamespaceSandbox();
-
void SetRendererSandboxStatus(int status);
int GetRendererSandboxStatus() const override;
+
+ pid_t LaunchZygote(base::CommandLine* cmd_line, base::ScopedFD* control_fd);
void AdjustRendererOOMScore(base::ProcessHandle process_handle,
int score) override;
@@ -50,10 +46,16 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
ZygoteHostImpl();
~ZygoteHostImpl() override;
+ // Tells the ZygoteHost the PIDs of all the zygotes.
+ void AddZygotePid(pid_t pid);
+
int renderer_sandbox_status_;
- bool should_use_namespace_sandbox_;
+
+ bool use_namespace_sandbox_;
+ bool use_suid_sandbox_;
bool use_suid_sandbox_for_adj_oom_score_;
std::string sandbox_binary_;
+
// This lock protects the |zygote_pids_| set.
base::Lock zygote_pids_lock_;
// This is a set of PIDs representing all the running zygotes.
diff --git a/chromium/content/child/BUILD.gn b/chromium/content/child/BUILD.gn
index e47d003692c..636c47e881a 100644
--- a/chromium/content/child/BUILD.gn
+++ b/chromium/content/child/BUILD.gn
@@ -32,7 +32,6 @@ source_set("child") {
public_deps = [
"//gpu/ipc/client:client",
- "//mojo/edk/system",
]
deps = [
@@ -48,10 +47,11 @@ source_set("child") {
"//content/public/common:common_sources",
"//crypto:platform",
"//gpu/command_buffer/client",
- "//ipc/mojo",
"//media",
"//mojo/common",
+ "//mojo/edk/system",
"//net",
+ "//services/shell/public/cpp",
"//services/shell/public/interfaces",
"//services/shell/runner/common",
"//skia",
diff --git a/chromium/content/child/DEPS b/chromium/content/child/DEPS
index ccc7ada628e..15d826df100 100644
--- a/chromium/content/child/DEPS
+++ b/chromium/content/child/DEPS
@@ -1,6 +1,6 @@
include_rules = [
- # Allow inclusion of specific components that we depend on. We may only
- # depend on components which we share with the mojo html_viewer.
+ # Allow inclusion of specific components that we depend on.
+ # See comment in content/DEPS for which components are allowed.
"+components/mime_util",
"+components/scheduler/child",
"+components/scheduler/common",
diff --git a/chromium/content/child/OWNERS b/chromium/content/child/OWNERS
index 62b2db68ad4..3d62269f838 100644
--- a/chromium/content/child/OWNERS
+++ b/chromium/content/child/OWNERS
@@ -1,9 +1,18 @@
# For Blink API usage
esprehn@chromium.org
+# AppCache
per-file appcache*=michaeln@chromium.org
# WebSocket
per-file *websocket*=ricea@chromium.org
per-file *websocket*=tyoshino@chromium.org
per-file *websocket*=yhirano@chromium.org
+
+# WebSQL
+per-file database_*=jsbell@chromium.org
+per-file database_*=michaeln@chromium.org
+per-file db_*=jsbell@chromium.org
+per-file db_*=michaeln@chromium.org
+per-file web_database_*=jsbell@chromium.org
+per-file web_database_*=michaeln@chromium.org
diff --git a/chromium/content/child/assert_matching_enums.cc b/chromium/content/child/assert_matching_enums.cc
index 21e57714a2a..d6bbd75f646 100644
--- a/chromium/content/child/assert_matching_enums.cc
+++ b/chromium/content/child/assert_matching_enums.cc
@@ -6,7 +6,6 @@
// from Blink are valid.
#include "base/macros.h"
-#include "content/public/common/mhtml_generation_params.h"
#include "content/public/common/screen_orientation_values.h"
#include "media/base/mime_util.h"
#include "third_party/WebKit/public/platform/WebMimeRegistry.h"
@@ -46,13 +45,4 @@ STATIC_ASSERT_ENUM(blink::WebMimeRegistry::IsSupported, media::IsSupported);
STATIC_ASSERT_ENUM(blink::WebMimeRegistry::MayBeSupported,
media::MayBeSupported);
-// MHTMLCacheControlPolicy
-STATIC_ASSERT_ENUM(blink::WebFrameSerializerCacheControlPolicy::None,
- MHTMLCacheControlPolicy::NONE);
-STATIC_ASSERT_ENUM(
- blink::WebFrameSerializerCacheControlPolicy::FailForNoStoreMainFrame,
- MHTMLCacheControlPolicy::FAIL_FOR_NO_STORE_MAIN_FRAME);
-STATIC_ASSERT_ENUM(blink::WebFrameSerializerCacheControlPolicy::Last,
- MHTMLCacheControlPolicy::LAST);
-
} // namespace content
diff --git a/chromium/content/child/background_sync/background_sync_provider.cc b/chromium/content/child/background_sync/background_sync_provider.cc
index 6bb7aa3aef3..517a6b61b81 100644
--- a/chromium/content/child/background_sync/background_sync_provider.cc
+++ b/chromium/content/child/background_sync/background_sync_provider.cc
@@ -34,9 +34,9 @@ int64_t GetServiceWorkerRegistrationId(
}
void ConnectToServiceOnMainThread(
- mojo::InterfaceRequest<blink::mojom::BackgroundSyncService> request) {
+ blink::mojom::BackgroundSyncServiceRequest request) {
DCHECK(ChildThreadImpl::current());
- ChildThreadImpl::current()->service_registry()->ConnectToRemoteService(
+ ChildThreadImpl::current()->GetRemoteInterfaces()->GetInterface(
std::move(request));
}
@@ -131,7 +131,7 @@ void BackgroundSyncProvider::WillStopCurrentWorkerThread() {
void BackgroundSyncProvider::RegisterCallback(
std::unique_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
blink::mojom::BackgroundSyncError error,
- const blink::mojom::SyncRegistrationPtr& options) {
+ blink::mojom::SyncRegistrationPtr options) {
// TODO(iclelland): Determine the correct error message to return in each case
std::unique_ptr<blink::WebSyncRegistration> result;
switch (error) {
@@ -171,7 +171,7 @@ void BackgroundSyncProvider::RegisterCallback(
void BackgroundSyncProvider::GetRegistrationsCallback(
std::unique_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacks,
blink::mojom::BackgroundSyncError error,
- const mojo::Array<blink::mojom::SyncRegistrationPtr>& registrations) {
+ mojo::Array<blink::mojom::SyncRegistrationPtr> registrations) {
// TODO(iclelland): Determine the correct error message to return in each case
switch (error) {
case blink::mojom::BackgroundSyncError::NONE: {
diff --git a/chromium/content/child/background_sync/background_sync_provider.h b/chromium/content/child/background_sync/background_sync_provider.h
index fc3f0a13d0f..7dd44064a0b 100644
--- a/chromium/content/child/background_sync/background_sync_provider.h
+++ b/chromium/content/child/background_sync/background_sync_provider.h
@@ -61,11 +61,11 @@ class BackgroundSyncProvider : public blink::WebSyncProvider,
void RegisterCallback(
std::unique_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
blink::mojom::BackgroundSyncError error,
- const blink::mojom::SyncRegistrationPtr& options);
+ blink::mojom::SyncRegistrationPtr options);
void GetRegistrationsCallback(
std::unique_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacks,
blink::mojom::BackgroundSyncError error,
- const mojo::Array<blink::mojom::SyncRegistrationPtr>& registrations);
+ mojo::Array<blink::mojom::SyncRegistrationPtr> registrations);
// Helper method that returns an initialized BackgroundSyncServicePtr.
blink::mojom::BackgroundSyncServicePtr& GetBackgroundSyncServicePtr();
diff --git a/chromium/content/child/blink_platform_impl.cc b/chromium/content/child/blink_platform_impl.cc
index 686cad5353f..3fd72bf3682 100644
--- a/chromium/content/child/blink_platform_impl.cc
+++ b/chromium/content/child/blink_platform_impl.cc
@@ -58,7 +58,6 @@
#include "net/base/net_errors.h"
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebMemoryDumpProvider.h"
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -388,7 +387,7 @@ void BlinkPlatformImpl::InternalInit() {
ChildThreadImpl::current()->notification_dispatcher();
push_dispatcher_ = ChildThreadImpl::current()->push_dispatcher();
permission_client_.reset(new PermissionDispatcher(
- ChildThreadImpl::current()->service_registry()));
+ ChildThreadImpl::current()->GetRemoteInterfaces()));
main_thread_sync_provider_.reset(
new BackgroundSyncProvider(main_thread_task_runner_.get()));
}
@@ -396,7 +395,8 @@ void BlinkPlatformImpl::InternalInit() {
void BlinkPlatformImpl::WaitUntilWebThreadTLSUpdate(
scheduler::WebThreadBase* thread) {
- base::WaitableEvent event(false, false);
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
thread->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&BlinkPlatformImpl::UpdateWebThreadTLS, base::Unretained(this),
@@ -676,10 +676,6 @@ const DataResource kDataResources[] = {
ui::SCALE_FACTOR_100P},
{"searchCancel", IDR_SEARCH_CANCEL, ui::SCALE_FACTOR_100P},
{"searchCancelPressed", IDR_SEARCH_CANCEL_PRESSED, ui::SCALE_FACTOR_100P},
- {"searchMagnifier", IDR_SEARCH_MAGNIFIER, ui::SCALE_FACTOR_100P},
- {"searchMagnifierResults",
- IDR_SEARCH_MAGNIFIER_RESULTS,
- ui::SCALE_FACTOR_100P},
{"textAreaResizeCorner", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_100P},
{"textAreaResizeCorner@2x", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_200P},
{"generatePassword", IDR_PASSWORD_GENERATION_ICON, ui::SCALE_FACTOR_100P},
@@ -858,6 +854,11 @@ void BlinkPlatformImpl::willStopWorkerThread() {
WorkerThreadRegistry::Instance()->WillStopCurrentWorkerThread();
}
+bool BlinkPlatformImpl::allowScriptExtensionForServiceWorker(
+ const blink::WebURL& scriptUrl) {
+ return GetContentClient()->AllowScriptExtensionForServiceWorker(scriptUrl);
+}
+
blink::WebCrypto* BlinkPlatformImpl::crypto() {
return &web_crypto_;
}
diff --git a/chromium/content/child/blink_platform_impl.h b/chromium/content/child/blink_platform_impl.h
index bb76571f2e7..2c15044e195 100644
--- a/chromium/content/child/blink_platform_impl.h
+++ b/chromium/content/child/blink_platform_impl.h
@@ -122,6 +122,8 @@ class CONTENT_EXPORT BlinkPlatformImpl
const blink::WebSize& cumulative_scroll) override;
void didStartWorkerThread() override;
void willStopWorkerThread() override;
+ bool allowScriptExtensionForServiceWorker(
+ const blink::WebURL& script_url) override;
blink::WebCrypto* crypto() override;
blink::WebNotificationManager* notificationManager() override;
blink::WebPushProvider* pushProvider() override;
diff --git a/chromium/content/child/blob_storage/blob_consolidation.cc b/chromium/content/child/blob_storage/blob_consolidation.cc
index c912699d375..ffcd12f089e 100644
--- a/chromium/content/child/blob_storage/blob_consolidation.cc
+++ b/chromium/content/child/blob_storage/blob_consolidation.cc
@@ -4,16 +4,27 @@
#include "content/child/blob_storage/blob_consolidation.h"
-#include <stdint.h>
-
#include <algorithm>
#include <limits>
#include <string>
+#include "base/bind.h"
+#include "base/callback.h"
+
using storage::DataElement;
using blink::WebThreadSafeData;
namespace content {
+namespace {
+bool WriteMemory(void* memory_out,
+ size_t* total_read,
+ const char* memory,
+ size_t size) {
+ memcpy(static_cast<char*>(memory_out) + *total_read, memory, size);
+ *total_read += size;
+ return true;
+}
+} // namespace
using ReadStatus = BlobConsolidation::ReadStatus;
@@ -99,11 +110,10 @@ void BlobConsolidation::AddFileSystemItem(const GURL& url,
item.expected_modification_time = expected_modification_time;
}
-ReadStatus BlobConsolidation::ReadMemory(size_t consolidated_item_index,
- size_t consolidated_offset,
- size_t consolidated_size,
- void* memory_out) {
- CHECK(memory_out);
+ReadStatus BlobConsolidation::VisitMemory(size_t consolidated_item_index,
+ size_t consolidated_offset,
+ size_t consolidated_size,
+ const MemoryVisitor& visitor) const {
if (consolidated_item_index >= consolidated_items_.size())
return ReadStatus::ERROR_OUT_OF_BOUNDS;
@@ -112,9 +122,6 @@ ReadStatus BlobConsolidation::ReadMemory(size_t consolidated_item_index,
return ReadStatus::ERROR_WRONG_TYPE;
if (consolidated_size + consolidated_offset > item.length) {
- LOG(ERROR) << "Invalid consolidated size " << consolidated_size
- << " and offset " << consolidated_offset << " vs item length of "
- << item.length;
return ReadStatus::ERROR_OUT_OF_BOUNDS;
}
@@ -155,12 +162,24 @@ ReadStatus BlobConsolidation::ReadMemory(size_t consolidated_item_index,
mid < num_items && memory_read < consolidated_size; mid++) {
size_t read_size = std::min(item.data[mid].size() - offset_from_mid,
consolidated_size - memory_read);
- memcpy(static_cast<char*>(memory_out) + memory_read,
- item.data[mid].data() + offset_from_mid, read_size);
+ bool continu =
+ visitor.Run(item.data[mid].data() + offset_from_mid, read_size);
+ if (!continu)
+ return ReadStatus::CANCELLED_BY_VISITOR;
offset_from_mid = 0;
memory_read += read_size;
}
return ReadStatus::OK;
}
+ReadStatus BlobConsolidation::ReadMemory(size_t consolidated_item_index,
+ size_t consolidated_offset,
+ size_t consolidated_size,
+ void* memory_out) const {
+ size_t total_read = 0;
+ return VisitMemory(consolidated_item_index, consolidated_offset,
+ consolidated_size,
+ base::Bind(&WriteMemory, memory_out, &total_read));
+}
+
} // namespace content
diff --git a/chromium/content/child/blob_storage/blob_consolidation.h b/chromium/content/child/blob_storage/blob_consolidation.h
index 7c581d4cf95..06d1051424d 100644
--- a/chromium/content/child/blob_storage/blob_consolidation.h
+++ b/chromium/content/child/blob_storage/blob_consolidation.h
@@ -13,8 +13,10 @@
#include <string>
#include <vector>
+#include "base/callback_forward.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "storage/common/data_element.h"
#include "third_party/WebKit/public/platform/WebThreadSafeData.h"
@@ -33,14 +35,17 @@ namespace content {
//
// NOTE: this class does not do memory accounting or garbage collecting. The
// memory for the blob sticks around until this class is destructed.
-class CONTENT_EXPORT BlobConsolidation {
+class CONTENT_EXPORT BlobConsolidation
+ : public base::RefCountedThreadSafe<BlobConsolidation> {
public:
enum class ReadStatus {
ERROR_UNKNOWN,
ERROR_WRONG_TYPE,
ERROR_OUT_OF_BOUNDS,
+ CANCELLED_BY_VISITOR,
OK
};
+
struct ConsolidatedItem {
ConsolidatedItem();
ConsolidatedItem(storage::DataElement::Type type,
@@ -63,8 +68,10 @@ class CONTENT_EXPORT BlobConsolidation {
std::vector<blink::WebThreadSafeData> data; // For TYPE_BYTES.
};
+ using MemoryVisitor =
+ base::Callback<bool(const char* memory, size_t memory_size)>;
+
BlobConsolidation();
- ~BlobConsolidation();
void AddDataItem(const blink::WebThreadSafeData& data);
void AddFileItem(const base::FilePath& path,
@@ -91,19 +98,38 @@ class CONTENT_EXPORT BlobConsolidation {
size_t total_memory() const { return total_memory_; }
- // Reads memory from the given item into the given buffer. Returns:
- // * ReadStatus::ERROR if the state or arguments are invalid (see error log),
+ // This method calls the |visitor| callback with the given memory item,
+ // offset, and size. Since items are consolidated, |visitor| can be called
+ // multiple times. The return value of |visitor| determines if we should
+ // continue reading memory, where 'false' triggers an early return and we
+ // return EARLY_ABORT. |visitor| is guaranteed to be called only during this
+ // method call.
+ // Returns:
+ // * ReadStatus::ERROR_UNKNOWN if the state or arguments are invalid,
// * ReadStatus::ERROR_WRONG_TYPE if the item at the index isn't memory,
// * ReadStatus::ERROR_OUT_OF_BOUNDS if index, offset, or size are invalid,
- // * ReadStatus::DONE if the memory has been successfully read.
+ // * ReadStatus::CANCELLED_BY_VISITOR if the visitor returns false before
+ // completion, and
+ // * ReadStatus::DONE if the memory has been successfully visited.
+ ReadStatus VisitMemory(size_t consolidated_item_index,
+ size_t consolidated_offset,
+ size_t consolidated_size,
+ const MemoryVisitor& visitor) const;
+
+ // Reads memory from the given item into the given buffer. This is a simple
+ // wrapper of VisitMemory. Returns the same values as VisitMemory, except we
+ // don't return CANCELLED_BY_VISITOR.
// Precondition: memory_out must be a valid pointer to memory with a size of
// at least consolidated_size.
ReadStatus ReadMemory(size_t consolidated_item_index,
size_t consolidated_offset,
size_t consolidated_size,
- void* memory_out);
+ void* memory_out) const;
private:
+ friend class base::RefCountedThreadSafe<BlobConsolidation>;
+ ~BlobConsolidation();
+
size_t total_memory_;
std::set<std::string> referenced_blobs_;
std::vector<ConsolidatedItem> consolidated_items_;
diff --git a/chromium/content/child/blob_storage/blob_consolidation_unittest.cc b/chromium/content/child/blob_storage/blob_consolidation_unittest.cc
index 64824e92e8a..ee1bfb06915 100644
--- a/chromium/content/child/blob_storage/blob_consolidation_unittest.cc
+++ b/chromium/content/child/blob_storage/blob_consolidation_unittest.cc
@@ -21,37 +21,37 @@ static blink::WebThreadSafeData CreateData(const std::string& str) {
}
TEST(BlobConsolidationTest, TestSegmentation) {
- BlobConsolidation consolidation;
- consolidation.AddDataItem(CreateData("12345"));
- EXPECT_EQ(5lu, consolidation.total_memory());
+ scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation());
+ consolidation->AddDataItem(CreateData("12345"));
+ EXPECT_EQ(5lu, consolidation->total_memory());
- const auto& items = consolidation.consolidated_items();
+ const auto& items = consolidation->consolidated_items();
EXPECT_EQ(1u, items.size());
EXPECT_EQ(5lu, items[0].length);
EXPECT_EQ(DataElement::TYPE_BYTES, items[0].type);
EXPECT_EQ(0lu, items[0].offset);
char memory[] = {'E'};
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 0, 1, memory));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 0, 1, memory));
EXPECT_EQ('1', memory[0]);
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 1, 1, memory));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 1, 1, memory));
EXPECT_EQ('2', memory[0]);
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 2, 1, memory));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 2, 1, memory));
EXPECT_EQ('3', memory[0]);
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 3, 1, memory));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 3, 1, memory));
EXPECT_EQ('4', memory[0]);
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 4, 1, memory));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 4, 1, memory));
EXPECT_EQ('5', memory[0]);
}
TEST(BlobConsolidationTest, TestConsolidation) {
- BlobConsolidation consolidation;
- consolidation.AddDataItem(CreateData("1"));
- consolidation.AddDataItem(CreateData("23"));
- consolidation.AddDataItem(CreateData("4"));
- EXPECT_EQ(4u, consolidation.total_memory());
+ scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation());
+ consolidation->AddDataItem(CreateData("1"));
+ consolidation->AddDataItem(CreateData("23"));
+ consolidation->AddDataItem(CreateData("4"));
+ EXPECT_EQ(4u, consolidation->total_memory());
- const auto& items = consolidation.consolidated_items();
+ const auto& items = consolidation->consolidated_items();
EXPECT_EQ(1u, items.size());
EXPECT_EQ(4lu, items[0].length);
EXPECT_EQ(DataElement::TYPE_BYTES, items[0].type);
@@ -59,19 +59,19 @@ TEST(BlobConsolidationTest, TestConsolidation) {
char memory[4];
EXPECT_EQ(ReadStatus::ERROR_OUT_OF_BOUNDS,
- consolidation.ReadMemory(0, 0, 5, memory));
+ consolidation->ReadMemory(0, 0, 5, memory));
EXPECT_EQ(ReadStatus::ERROR_OUT_OF_BOUNDS,
- consolidation.ReadMemory(1, 0, 4, memory));
+ consolidation->ReadMemory(1, 0, 4, memory));
EXPECT_EQ(ReadStatus::ERROR_OUT_OF_BOUNDS,
- consolidation.ReadMemory(0, 1, 4, memory));
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 0, 4, memory));
+ consolidation->ReadMemory(0, 1, 4, memory));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 0, 4, memory));
char expected_memory[] = {'1', '2', '3', '4'};
EXPECT_THAT(memory, testing::ElementsAreArray(expected_memory));
}
TEST(BlobConsolidationTest, TestMassiveConsolidation) {
- BlobConsolidation consolidation;
+ scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation());
const size_t kNumParts = 300;
const size_t kPartSize = 5;
const size_t kTotalMemory = kNumParts * kPartSize;
@@ -85,11 +85,11 @@ TEST(BlobConsolidationTest, TestMassiveConsolidation) {
data[j] = current_value;
++current_value;
}
- consolidation.AddDataItem(blink::WebThreadSafeData(data, kPartSize));
+ consolidation->AddDataItem(blink::WebThreadSafeData(data, kPartSize));
}
- EXPECT_EQ(kTotalMemory, consolidation.total_memory());
+ EXPECT_EQ(kTotalMemory, consolidation->total_memory());
- const auto& items = consolidation.consolidated_items();
+ const auto& items = consolidation->consolidated_items();
EXPECT_EQ(1u, items.size());
EXPECT_EQ(kTotalMemory, items[0].length);
@@ -97,8 +97,8 @@ TEST(BlobConsolidationTest, TestMassiveConsolidation) {
char read_buffer[kReadSegmentSize];
for (size_t i = 0; i < kNumReadSegments; i++) {
EXPECT_EQ(ReadStatus::OK,
- consolidation.ReadMemory(0, i * kReadSegmentSize,
- kReadSegmentSize, read_buffer));
+ consolidation->ReadMemory(0, i * kReadSegmentSize,
+ kReadSegmentSize, read_buffer));
for (size_t j = 0; j < kReadSegmentSize; j++) {
EXPECT_EQ(expected_value, read_buffer[j]);
++expected_value;
@@ -107,45 +107,45 @@ TEST(BlobConsolidationTest, TestMassiveConsolidation) {
}
TEST(BlobConsolidationTest, TestPartialRead) {
- BlobConsolidation consolidation;
- consolidation.AddDataItem(CreateData("1"));
- consolidation.AddDataItem(CreateData("23"));
- consolidation.AddDataItem(CreateData("45"));
- EXPECT_EQ(5u, consolidation.total_memory());
+ scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation());
+ consolidation->AddDataItem(CreateData("1"));
+ consolidation->AddDataItem(CreateData("23"));
+ consolidation->AddDataItem(CreateData("45"));
+ EXPECT_EQ(5u, consolidation->total_memory());
- const auto& items = consolidation.consolidated_items();
+ const auto& items = consolidation->consolidated_items();
EXPECT_EQ(1u, items.size());
EXPECT_EQ(5lu, items[0].length);
EXPECT_EQ(0lu, items[0].offset);
char memory_part1[] = {'X', 'X'};
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 0, 2, memory_part1));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 0, 2, memory_part1));
char expected_memory_part1[] = {'1', '2'};
EXPECT_THAT(memory_part1, testing::ElementsAreArray(expected_memory_part1));
char memory_part2[] = {'X', 'X'};
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 2, 2, memory_part2));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 2, 2, memory_part2));
char expected_memory_part2[] = {'3', '4'};
EXPECT_THAT(memory_part2, testing::ElementsAreArray(expected_memory_part2));
char memory_part3[] = {'X'};
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 4, 1, memory_part3));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 4, 1, memory_part3));
char expected_memory_part3[] = {'5'};
EXPECT_THAT(memory_part3, testing::ElementsAreArray(expected_memory_part3));
}
TEST(BlobConsolidationTest, TestBoundaries) {
- BlobConsolidation consolidation;
- consolidation.AddDataItem(CreateData("1"));
- consolidation.AddFileItem(base::FilePath(FILE_PATH_LITERAL("testPath")), 1,
- 10, 5.0);
- consolidation.AddDataItem(CreateData("2"));
- consolidation.AddDataItem(CreateData("3"));
- consolidation.AddBlobItem("testUUID", 1, 2);
- consolidation.AddDataItem(CreateData("45"));
- EXPECT_EQ(5u, consolidation.total_memory());
-
- const auto& items = consolidation.consolidated_items();
+ scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation());
+ consolidation->AddDataItem(CreateData("1"));
+ consolidation->AddFileItem(base::FilePath(FILE_PATH_LITERAL("testPath")), 1,
+ 10, 5.0);
+ consolidation->AddDataItem(CreateData("2"));
+ consolidation->AddDataItem(CreateData("3"));
+ consolidation->AddBlobItem("testUUID", 1, 2);
+ consolidation->AddDataItem(CreateData("45"));
+ EXPECT_EQ(5u, consolidation->total_memory());
+
+ const auto& items = consolidation->consolidated_items();
EXPECT_EQ(5u, items.size());
EXPECT_EQ(1lu, items[0].length);
@@ -165,22 +165,22 @@ TEST(BlobConsolidationTest, TestBoundaries) {
char test_memory[5];
EXPECT_EQ(ReadStatus::ERROR_WRONG_TYPE,
- consolidation.ReadMemory(1, 0, 1, test_memory));
+ consolidation->ReadMemory(1, 0, 1, test_memory));
EXPECT_EQ(ReadStatus::ERROR_WRONG_TYPE,
- consolidation.ReadMemory(3, 0, 1, test_memory));
+ consolidation->ReadMemory(3, 0, 1, test_memory));
char memory_part1[1];
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(0, 0, 1, memory_part1));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(0, 0, 1, memory_part1));
char expected_memory_part1[] = {'1'};
EXPECT_THAT(memory_part1, testing::ElementsAreArray(expected_memory_part1));
char memory_part2[2];
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(2, 0, 2, memory_part2));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(2, 0, 2, memory_part2));
char expected_memory_part2[] = {'2', '3'};
EXPECT_THAT(memory_part2, testing::ElementsAreArray(expected_memory_part2));
char memory_part3[2];
- EXPECT_EQ(ReadStatus::OK, consolidation.ReadMemory(4, 0, 2, memory_part3));
+ EXPECT_EQ(ReadStatus::OK, consolidation->ReadMemory(4, 0, 2, memory_part3));
char expected_memory_part3[] = {'4', '5'};
EXPECT_THAT(memory_part3, testing::ElementsAreArray(expected_memory_part3));
}
diff --git a/chromium/content/child/blob_storage/blob_message_filter.cc b/chromium/content/child/blob_storage/blob_message_filter.cc
index 19491d655fd..66ec62de411 100644
--- a/chromium/content/child/blob_storage/blob_message_filter.cc
+++ b/chromium/content/child/blob_storage/blob_message_filter.cc
@@ -4,17 +4,21 @@
#include "content/child/blob_storage/blob_message_filter.h"
+#include "base/bind.h"
+#include "base/task_runner.h"
#include "content/child/blob_storage/blob_transport_controller.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/fileapi/webblob_messages.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
#include "storage/common/blob_storage/blob_item_bytes_request.h"
+#include "storage/common/blob_storage/blob_item_bytes_response.h"
namespace content {
-BlobMessageFilter::BlobMessageFilter()
- : IPC::MessageFilter(), sender_(nullptr) {}
+BlobMessageFilter::BlobMessageFilter(
+ scoped_refptr<base::TaskRunner> file_runner)
+ : sender_(nullptr), file_runner_(std::move(file_runner)) {}
BlobMessageFilter::~BlobMessageFilter() {}
@@ -22,6 +26,11 @@ void BlobMessageFilter::OnFilterAdded(IPC::Sender* sender) {
sender_ = sender;
}
+void BlobMessageFilter::OnChannelClosing() {
+ BlobTransportController::GetInstance()->CancelAllBlobTransfers();
+ sender_ = nullptr;
+}
+
bool BlobMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(BlobMessageFilter, message)
@@ -45,7 +54,8 @@ void BlobMessageFilter::OnRequestMemoryItem(
std::vector<base::SharedMemoryHandle> memory_handles,
const std::vector<IPC::PlatformFileForTransit>& file_handles) {
BlobTransportController::GetInstance()->OnMemoryRequest(
- uuid, requests, &memory_handles, file_handles, sender_);
+ uuid, requests, &memory_handles, file_handles, file_runner_.get(),
+ sender_);
}
void BlobMessageFilter::OnCancelBuildingBlob(
diff --git a/chromium/content/child/blob_storage/blob_message_filter.h b/chromium/content/child/blob_storage/blob_message_filter.h
index 26266658a22..7f4ed917969 100644
--- a/chromium/content/child/blob_storage/blob_message_filter.h
+++ b/chromium/content/child/blob_storage/blob_message_filter.h
@@ -7,15 +7,21 @@
#include <stddef.h>
+#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "ipc/ipc_platform_file.h"
#include "ipc/message_filter.h"
#include "storage/common/blob_storage/blob_storage_constants.h"
+namespace base {
+class TaskRunner;
+}
+
namespace IPC {
class Sender;
class Message;
@@ -23,6 +29,7 @@ class Message;
namespace storage {
struct BlobItemBytesRequest;
+struct BlobItemBytesResponse;
}
namespace content {
@@ -32,8 +39,9 @@ namespace content {
// operated on by the IO thread.
class BlobMessageFilter : public IPC::MessageFilter {
public:
- BlobMessageFilter();
+ BlobMessageFilter(scoped_refptr<base::TaskRunner> file_runner);
+ void OnChannelClosing() override;
void OnFilterAdded(IPC::Sender* sender) override;
bool OnMessageReceived(const IPC::Message& message) override;
bool GetSupportedMessageClasses(
@@ -55,6 +63,7 @@ class BlobMessageFilter : public IPC::MessageFilter {
void OnDoneBuildingBlob(const std::string& uuid);
IPC::Sender* sender_;
+ scoped_refptr<base::TaskRunner> file_runner_;
DISALLOW_COPY_AND_ASSIGN(BlobMessageFilter);
};
diff --git a/chromium/content/child/blob_storage/blob_transport_controller.cc b/chromium/content/child/blob_storage/blob_transport_controller.cc
index 706b56d1402..b5cc88416ca 100644
--- a/chromium/content/child/blob_storage/blob_transport_controller.cc
+++ b/chromium/content/child/blob_storage/blob_transport_controller.cc
@@ -4,24 +4,41 @@
#include "content/child/blob_storage/blob_transport_controller.h"
+#include <limits>
+#include <memory>
#include <utility>
#include <vector>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/files/file.h"
#include "base/lazy_instance.h"
+#include "base/location.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/shared_memory.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.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/child/blob_storage/blob_consolidation.h"
#include "content/child/child_process.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/fileapi/webblob_messages.h"
+#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
#include "storage/common/blob_storage/blob_item_bytes_request.h"
#include "storage/common/blob_storage/blob_item_bytes_response.h"
#include "storage/common/data_element.h"
#include "third_party/WebKit/public/platform/Platform.h"
+using base::File;
using base::SharedMemory;
using base::SharedMemoryHandle;
using storage::BlobItemBytesRequest;
@@ -30,10 +47,11 @@ using storage::IPCBlobItemRequestStrategy;
using storage::DataElement;
using storage::kBlobStorageIPCThresholdBytes;
-namespace content {
-
+using storage::BlobItemBytesResponse;
+using storage::BlobItemBytesRequest;
using storage::IPCBlobCreationCancelCode;
+namespace content {
using ConsolidatedItem = BlobConsolidation::ConsolidatedItem;
using ReadStatus = BlobConsolidation::ReadStatus;
@@ -52,6 +70,86 @@ void DecChildProcessRefCount() {
blink::Platform::current()->suddenTerminationChanged(true);
ChildProcess::current()->ReleaseProcess();
}
+
+void DecChildProcessRefCountTimes(size_t times) {
+ for (size_t i = 0; i < times; i++) {
+ DecChildProcessRefCount();
+ }
+}
+
+bool WriteSingleChunk(base::File* file, const char* memory, size_t size) {
+ size_t written = 0;
+ while (written < size) {
+ size_t writing_size = base::saturated_cast<int>(size - written);
+ int actual_written =
+ file->WriteAtCurrentPos(memory, static_cast<int>(writing_size));
+ bool write_failed = actual_written < 0;
+ UMA_HISTOGRAM_BOOLEAN("Storage.Blob.RendererFileWriteFailed", write_failed);
+ if (write_failed)
+ return false;
+ written += actual_written;
+ }
+ return true;
+}
+
+base::Optional<base::Time> WriteSingleRequestToDisk(
+ const BlobConsolidation* consolidation,
+ const BlobItemBytesRequest& request,
+ File* file) {
+ if (!file->IsValid())
+ return base::nullopt;
+ int64_t seek_distance = file->Seek(
+ File::FROM_BEGIN, base::checked_cast<int64_t>(request.handle_offset));
+ bool seek_failed = seek_distance < 0;
+ UMA_HISTOGRAM_BOOLEAN("Storage.Blob.RendererFileSeekFailed", seek_failed);
+ if (seek_failed) {
+ return base::nullopt;
+ }
+ BlobConsolidation::ReadStatus status = consolidation->VisitMemory(
+ request.renderer_item_index, request.renderer_item_offset, request.size,
+ base::Bind(&WriteSingleChunk, file));
+ if (status != BlobConsolidation::ReadStatus::OK)
+ return base::nullopt;
+ File::Info info;
+ file->GetInfo(&info);
+ return base::make_optional(info.last_modified);
+}
+
+// This returns either the responses, or if they're empty, an error code.
+std::pair<std::vector<storage::BlobItemBytesResponse>,
+ IPCBlobCreationCancelCode>
+WriteDiskRequests(
+ scoped_refptr<BlobConsolidation> consolidation,
+ std::unique_ptr<std::vector<BlobItemBytesRequest>> requests,
+ const std::vector<IPC::PlatformFileForTransit>& file_handles) {
+ std::vector<BlobItemBytesResponse> responses;
+ std::vector<base::Time> last_modified_times;
+ last_modified_times.resize(file_handles.size());
+ // We grab ownership of the file handles here. When this vector is destroyed
+ // it will close the files.
+ std::vector<File> files;
+ files.reserve(file_handles.size());
+ for (const auto& file_handle : file_handles) {
+ files.emplace_back(IPC::PlatformFileForTransitToFile(file_handle));
+ }
+ for (const auto& request : *requests) {
+ base::Optional<base::Time> last_modified = WriteSingleRequestToDisk(
+ consolidation.get(), request, &files[request.handle_index]);
+ if (!last_modified) {
+ return std::make_pair(std::vector<storage::BlobItemBytesResponse>(),
+ IPCBlobCreationCancelCode::FILE_WRITE_FAILED);
+ }
+ last_modified_times[request.handle_index] = last_modified.value();
+ }
+ for (const auto& request : *requests) {
+ responses.push_back(BlobItemBytesResponse(request.request_number));
+ responses.back().time_file_modified =
+ last_modified_times[request.handle_index];
+ }
+
+ return std::make_pair(responses, IPCBlobCreationCancelCode::UNKNOWN);
+}
+
} // namespace
BlobTransportController* BlobTransportController::GetInstance() {
@@ -62,7 +160,7 @@ BlobTransportController* BlobTransportController::GetInstance() {
void BlobTransportController::InitiateBlobTransfer(
const std::string& uuid,
const std::string& content_type,
- std::unique_ptr<BlobConsolidation> consolidation,
+ scoped_refptr<BlobConsolidation> consolidation,
scoped_refptr<ThreadSafeSender> sender,
base::SingleThreadTaskRunner* io_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_runner) {
@@ -95,29 +193,115 @@ void BlobTransportController::OnMemoryRequest(
const std::vector<storage::BlobItemBytesRequest>& requests,
std::vector<base::SharedMemoryHandle>* memory_handles,
const std::vector<IPC::PlatformFileForTransit>& file_handles,
+ base::TaskRunner* file_runner,
IPC::Sender* sender) {
- std::vector<storage::BlobItemBytesResponse> responses;
- ResponsesStatus status =
- GetResponses(uuid, requests, memory_handles, file_handles, &responses);
-
- switch (status) {
- case ResponsesStatus::BLOB_NOT_FOUND:
- // sender->Send(new BlobStorageMsg_CancelBuildingBlob(uuid,
- // IPCBlobCreationCancelCode::UNKNOWN));
- return;
- case ResponsesStatus::SHARED_MEMORY_MAP_FAILED:
- // This would happen if the renderer process doesn't have enough memory
- // to map the shared memory, which is possible if we don't have much
- // memory. If this scenario happens often, we could delay the response
- // until we have enough memory. For now we just fail.
- CHECK(false) << "Unable to map shared memory to send blob " << uuid
- << ".";
- break;
- case ResponsesStatus::SUCCESS:
- break;
+ std::vector<BlobItemBytesResponse> responses;
+ auto it = blob_storage_.find(uuid);
+ // Ignore invalid messages.
+ if (it == blob_storage_.end())
+ return;
+
+ BlobConsolidation* consolidation = it->second.get();
+ const auto& consolidated_items = consolidation->consolidated_items();
+
+ std::unique_ptr<std::vector<BlobItemBytesRequest>> file_requests(
+ new std::vector<BlobItemBytesRequest>());
+
+ // Since we can be writing to the same shared memory handle from multiple
+ // requests, we keep them in a vector and lazily create them.
+ ScopedVector<SharedMemory> opened_memory;
+ opened_memory.resize(memory_handles->size());
+
+ // We need to calculate how much memory we expect to be writing to the memory
+ // segments so we can correctly map it the first time.
+ std::vector<size_t> shared_memory_sizes(memory_handles->size());
+ for (const BlobItemBytesRequest& request : requests) {
+ if (request.transport_strategy !=
+ IPCBlobItemRequestStrategy::SHARED_MEMORY) {
+ continue;
+ }
+ DCHECK_LT(request.handle_index, memory_handles->size())
+ << "Invalid handle index.";
+ shared_memory_sizes[request.handle_index] =
+ std::max<size_t>(shared_memory_sizes[request.handle_index],
+ request.size + request.handle_offset);
}
- sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses));
+ for (const BlobItemBytesRequest& request : requests) {
+ DCHECK_LT(request.renderer_item_index, consolidated_items.size())
+ << "Invalid item index";
+
+ const ConsolidatedItem& item =
+ consolidated_items[request.renderer_item_index];
+ DCHECK_LE(request.renderer_item_offset + request.size, item.length)
+ << "Invalid data range";
+ DCHECK_EQ(item.type, DataElement::TYPE_BYTES) << "Invalid element type";
+
+ switch (request.transport_strategy) {
+ case IPCBlobItemRequestStrategy::IPC: {
+ responses.push_back(BlobItemBytesResponse(request.request_number));
+ BlobItemBytesResponse& response = responses.back();
+ ReadStatus status = consolidation->ReadMemory(
+ request.renderer_item_index, request.renderer_item_offset,
+ request.size, response.allocate_mutable_data(request.size));
+ DCHECK(status == ReadStatus::OK)
+ << "Error reading from consolidated blob: "
+ << static_cast<int>(status);
+ break;
+ }
+ case IPCBlobItemRequestStrategy::SHARED_MEMORY: {
+ responses.push_back(BlobItemBytesResponse(request.request_number));
+ SharedMemory* memory = opened_memory[request.handle_index];
+ if (!memory) {
+ SharedMemoryHandle& handle = (*memory_handles)[request.handle_index];
+ size_t size = shared_memory_sizes[request.handle_index];
+ DCHECK(SharedMemory::IsHandleValid(handle));
+ std::unique_ptr<SharedMemory> shared_memory(
+ new SharedMemory(handle, false));
+
+ if (!shared_memory->Map(size)) {
+ // This would happen if the renderer process doesn't have enough
+ // memory to map the shared memory, which is possible if we don't
+ // have much memory. If this scenario happens often, we could delay
+ // the response until we have enough memory. For now we just fail.
+ CHECK(false) << "Unable to map shared memory to send blob " << uuid
+ << ".";
+ return;
+ }
+ memory = shared_memory.get();
+ opened_memory[request.handle_index] = shared_memory.release();
+ }
+ CHECK(memory->memory()) << "Couldn't map memory for blob transfer.";
+ ReadStatus status = consolidation->ReadMemory(
+ request.renderer_item_index, request.renderer_item_offset,
+ request.size,
+ static_cast<char*>(memory->memory()) + request.handle_offset);
+ DCHECK(status == ReadStatus::OK)
+ << "Error reading from consolidated blob: "
+ << static_cast<int>(status);
+ break;
+ }
+ case IPCBlobItemRequestStrategy::FILE:
+ DCHECK_LT(request.handle_index, file_handles.size())
+ << "Invalid handle index.";
+ file_requests->push_back(request);
+ break;
+ case IPCBlobItemRequestStrategy::UNKNOWN:
+ NOTREACHED();
+ break;
+ }
+ }
+ if (!file_requests->empty()) {
+ base::PostTaskAndReplyWithResult(
+ file_runner, FROM_HERE,
+ base::Bind(&WriteDiskRequests, make_scoped_refptr(consolidation),
+ base::Passed(&file_requests), file_handles),
+ base::Bind(&BlobTransportController::OnFileWriteComplete,
+ weak_factory_.GetWeakPtr(), sender, uuid));
+ }
+
+ if (!responses.empty())
+ sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses));
}
void BlobTransportController::OnCancel(
@@ -132,6 +316,17 @@ void BlobTransportController::OnDone(const std::string& uuid) {
ReleaseBlobConsolidation(uuid);
}
+void BlobTransportController::CancelAllBlobTransfers() {
+ weak_factory_.InvalidateWeakPtrs();
+ if (!blob_storage_.empty() && main_thread_runner_) {
+ main_thread_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DecChildProcessRefCountTimes, blob_storage_.size()));
+ }
+ main_thread_runner_ = nullptr;
+ blob_storage_.clear();
+}
+
// static
void BlobTransportController::GetDescriptions(
BlobConsolidation* consolidation,
@@ -186,21 +381,28 @@ void BlobTransportController::GetDescriptions(
}
}
-BlobTransportController::BlobTransportController() {}
+BlobTransportController::BlobTransportController() : weak_factory_(this) {}
BlobTransportController::~BlobTransportController() {}
-void BlobTransportController::ClearForTesting() {
- if (!blob_storage_.empty() && main_thread_runner_) {
- main_thread_runner_->PostTask(FROM_HERE,
- base::Bind(&DecChildProcessRefCount));
+void BlobTransportController::OnFileWriteComplete(
+ IPC::Sender* sender,
+ const std::string& uuid,
+ const std::pair<std::vector<BlobItemBytesResponse>,
+ IPCBlobCreationCancelCode>& result) {
+ if (blob_storage_.find(uuid) == blob_storage_.end())
+ return;
+ if (!result.first.empty()) {
+ sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, result.first));
+ return;
}
- blob_storage_.clear();
+ sender->Send(new BlobStorageMsg_CancelBuildingBlob(uuid, result.second));
+ ReleaseBlobConsolidation(uuid);
}
void BlobTransportController::StoreBlobDataForRequests(
const std::string& uuid,
- std::unique_ptr<BlobConsolidation> consolidation,
+ scoped_refptr<BlobConsolidation> consolidation,
scoped_refptr<base::SingleThreadTaskRunner> main_runner) {
if (!main_thread_runner_.get()) {
main_thread_runner_ = std::move(main_runner);
@@ -208,97 +410,6 @@ void BlobTransportController::StoreBlobDataForRequests(
blob_storage_[uuid] = std::move(consolidation);
}
-BlobTransportController::ResponsesStatus BlobTransportController::GetResponses(
- const std::string& uuid,
- const std::vector<BlobItemBytesRequest>& requests,
- std::vector<SharedMemoryHandle>* memory_handles,
- const std::vector<IPC::PlatformFileForTransit>& file_handles,
- std::vector<BlobItemBytesResponse>* out) {
- DCHECK(out->empty());
- auto it = blob_storage_.find(uuid);
- if (it == blob_storage_.end())
- return ResponsesStatus::BLOB_NOT_FOUND;
-
- BlobConsolidation* consolidation = it->second.get();
- const auto& consolidated_items = consolidation->consolidated_items();
-
- // We need to calculate how much memory we expect to be writing to the memory
- // segments so we can correctly map it the first time.
- std::vector<size_t> shared_memory_sizes(memory_handles->size());
- for (const BlobItemBytesRequest& request : requests) {
- if (request.transport_strategy !=
- IPCBlobItemRequestStrategy::SHARED_MEMORY) {
- continue;
- }
- DCHECK_LT(request.handle_index, memory_handles->size())
- << "Invalid handle index.";
- shared_memory_sizes[request.handle_index] =
- std::max<size_t>(shared_memory_sizes[request.handle_index],
- request.size + request.handle_offset);
- }
-
- // Since we can be writing to the same shared memory handle from multiple
- // requests, we keep them in a vector and lazily create them.
- ScopedVector<SharedMemory> opened_memory;
- opened_memory.resize(memory_handles->size());
- for (const BlobItemBytesRequest& request : requests) {
- DCHECK_LT(request.renderer_item_index, consolidated_items.size())
- << "Invalid item index";
-
- const ConsolidatedItem& item =
- consolidated_items[request.renderer_item_index];
- DCHECK_LE(request.renderer_item_offset + request.size, item.length)
- << "Invalid data range";
- DCHECK_EQ(item.type, DataElement::TYPE_BYTES) << "Invalid element type";
-
- out->push_back(BlobItemBytesResponse(request.request_number));
- switch (request.transport_strategy) {
- case IPCBlobItemRequestStrategy::IPC: {
- BlobItemBytesResponse& response = out->back();
- ReadStatus status = consolidation->ReadMemory(
- request.renderer_item_index, request.renderer_item_offset,
- request.size, response.allocate_mutable_data(request.size));
- DCHECK(status == ReadStatus::OK)
- << "Error reading from consolidated blob: "
- << static_cast<int>(status);
- break;
- }
- case IPCBlobItemRequestStrategy::SHARED_MEMORY: {
- DCHECK_LT(request.handle_index, memory_handles->size())
- << "Invalid handle index.";
- SharedMemory* memory = opened_memory[request.handle_index];
- if (!memory) {
- SharedMemoryHandle& handle = (*memory_handles)[request.handle_index];
- size_t size = shared_memory_sizes[request.handle_index];
- DCHECK(SharedMemory::IsHandleValid(handle));
- std::unique_ptr<SharedMemory> shared_memory(
- new SharedMemory(handle, false));
- if (!shared_memory->Map(size))
- return ResponsesStatus::SHARED_MEMORY_MAP_FAILED;
- memory = shared_memory.get();
- opened_memory[request.handle_index] = shared_memory.release();
- }
- CHECK(memory->memory()) << "Couldn't map memory for blob transfer.";
- ReadStatus status = consolidation->ReadMemory(
- request.renderer_item_index, request.renderer_item_offset,
- request.size,
- static_cast<char*>(memory->memory()) + request.handle_offset);
- DCHECK(status == ReadStatus::OK)
- << "Error reading from consolidated blob: "
- << static_cast<int>(status);
- break;
- }
- case IPCBlobItemRequestStrategy::FILE:
- NOTREACHED() << "TODO(dmurph): Not implemented.";
- break;
- case IPCBlobItemRequestStrategy::UNKNOWN:
- NOTREACHED();
- break;
- }
- }
- return ResponsesStatus::SUCCESS;
-}
-
void BlobTransportController::ReleaseBlobConsolidation(
const std::string& uuid) {
if (blob_storage_.erase(uuid)) {
diff --git a/chromium/content/child/blob_storage/blob_transport_controller.h b/chromium/content/child/blob_storage/blob_transport_controller.h
index c9c62ce55ba..a0897e7519c 100644
--- a/chromium/content/child/blob_storage/blob_transport_controller.h
+++ b/chromium/content/child/blob_storage/blob_transport_controller.h
@@ -10,12 +10,15 @@
#include <map>
#include <memory>
#include <string>
+#include <utility>
#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/memory/shared_memory_handle.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "ipc/ipc_platform_file.h"
#include "storage/common/blob_storage/blob_storage_constants.h"
@@ -24,6 +27,7 @@ namespace base {
template <typename T>
struct DefaultLazyInstanceTraits;
class SingleThreadTaskRunner;
+class TaskRunner;
}
namespace storage {
@@ -33,6 +37,7 @@ struct BlobItemBytesResponse;
}
namespace IPC {
+class Message;
class Sender;
}
@@ -50,6 +55,9 @@ class ThreadSafeSender;
// * include shortcut data in the descriptions,
// * generate responses to blob memory requests, and
// * send IPC responses.
+// We try to keep the renderer alive during blob transportation by calling
+// ChildProcess::AddProcessRef and
+// blink::Platform::current()->suddenTerminationChanged.
// Must be used on the IO thread.
class CONTENT_EXPORT BlobTransportController {
public:
@@ -63,17 +71,21 @@ class CONTENT_EXPORT BlobTransportController {
static void InitiateBlobTransfer(
const std::string& uuid,
const std::string& content_type,
- std::unique_ptr<BlobConsolidation> consolidation,
+ scoped_refptr<BlobConsolidation> consolidation,
scoped_refptr<ThreadSafeSender> sender,
base::SingleThreadTaskRunner* io_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_runner);
- // This responds to the request using the sender.
+ // This responds to the request using the |sender|. If we need to save files
+ // then we we hold onto the sender to send the (possibly multiple) reponses
+ // asynchronously. Use CancelAllBlobTransfers to stop usage of the |sender|.
+ // We close the file handles once we're done writing to them.
void OnMemoryRequest(
const std::string& uuid,
const std::vector<storage::BlobItemBytesRequest>& requests,
std::vector<base::SharedMemoryHandle>* memory_handles,
const std::vector<IPC::PlatformFileForTransit>& file_handles,
+ base::TaskRunner* file_runner,
IPC::Sender* sender);
void OnCancel(const std::string& uuid,
@@ -85,13 +97,27 @@ class CONTENT_EXPORT BlobTransportController {
return blob_storage_.find(uuid) != blob_storage_.end();
}
+ // Invalidates all asynchronously running memory request handlers and clears
+ // the internal state. If our map wasn't previously empty, then we call
+ // ChildProcess::ReleaseProcess to release our previous reference.
+ void CancelAllBlobTransfers();
+
private:
+ friend struct base::DefaultLazyInstanceTraits<BlobTransportController>;
friend class BlobTransportControllerTest;
FRIEND_TEST_ALL_PREFIXES(BlobTransportControllerTest, Descriptions);
FRIEND_TEST_ALL_PREFIXES(BlobTransportControllerTest, Responses);
FRIEND_TEST_ALL_PREFIXES(BlobTransportControllerTest, SharedMemory);
+ FRIEND_TEST_ALL_PREFIXES(BlobTransportControllerTest, Disk);
FRIEND_TEST_ALL_PREFIXES(BlobTransportControllerTest, ResponsesErrors);
+ enum class ResponsesStatus {
+ BLOB_NOT_FOUND,
+ SHARED_MEMORY_MAP_FAILED,
+ PENDING_IO,
+ SUCCESS
+ };
+
static void GetDescriptions(BlobConsolidation* consolidation,
size_t max_data_population,
std::vector<storage::DataElement>* out);
@@ -99,36 +125,23 @@ class CONTENT_EXPORT BlobTransportController {
BlobTransportController();
~BlobTransportController();
- // Clears all internal state. If our map wasn't previously empty, then we call
- // ChildProcess::ReleaseProcess to release our previous reference.
- void ClearForTesting();
-
- enum class ResponsesStatus {
- BLOB_NOT_FOUND,
- SHARED_MEMORY_MAP_FAILED,
- SUCCESS
- };
- friend struct base::DefaultLazyInstanceTraits<BlobTransportController>;
+ void OnFileWriteComplete(
+ IPC::Sender* sender,
+ const std::string& uuid,
+ const std::pair<std::vector<storage::BlobItemBytesResponse>,
+ storage::IPCBlobCreationCancelCode>& result);
void StoreBlobDataForRequests(
const std::string& uuid,
- std::unique_ptr<BlobConsolidation> consolidation,
+ scoped_refptr<BlobConsolidation> consolidation,
scoped_refptr<base::SingleThreadTaskRunner> main_runner);
- ResponsesStatus GetResponses(
- const std::string& uuid,
- const std::vector<storage::BlobItemBytesRequest>& requests,
- std::vector<base::SharedMemoryHandle>* memory_handles,
- const std::vector<IPC::PlatformFileForTransit>& file_handles,
- std::vector<storage::BlobItemBytesResponse>* output);
-
- // Deletes the consolidation, and if we removed the last consolidation from
- // our map, we call ChildProcess::ReleaseProcess to release our previous
- // reference.
+ // Deletes the consolidation and calls ChildProcess::ReleaseProcess.
void ReleaseBlobConsolidation(const std::string& uuid);
scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_;
- std::map<std::string, std::unique_ptr<BlobConsolidation>> blob_storage_;
+ std::map<std::string, scoped_refptr<BlobConsolidation>> blob_storage_;
+ base::WeakPtrFactory<BlobTransportController> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(BlobTransportController);
};
diff --git a/chromium/content/child/blob_storage/blob_transport_controller_unittest.cc b/chromium/content/child/blob_storage/blob_transport_controller_unittest.cc
index 1669e44bfe8..67357427861 100644
--- a/chromium/content/child/blob_storage/blob_transport_controller_unittest.cc
+++ b/chromium/content/child/blob_storage/blob_transport_controller_unittest.cc
@@ -6,14 +6,24 @@
#include <stddef.h>
#include <stdint.h>
+#include <tuple>
-#include "base/memory/ptr_util.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/memory/shared_memory.h"
+#include "base/message_loop/message_loop.h"
+#include "base/process/process_handle.h"
+#include "base/test/test_file_util.h"
#include "base/test/test_simple_task_runner.h"
-#include "base/tuple.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/child/blob_storage/blob_consolidation.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/fileapi/webblob_messages.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_platform_file.h"
#include "ipc/ipc_sender.h"
#include "ipc/ipc_sync_message_filter.h"
#include "ipc/ipc_test_sink.h"
@@ -22,9 +32,13 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::File;
+using base::FilePath;
+using base::TestSimpleTaskRunner;
using storage::BlobItemBytesRequest;
using storage::BlobItemBytesResponse;
using storage::DataElement;
+using storage::IPCBlobCreationCancelCode;
namespace content {
namespace {
@@ -87,13 +101,28 @@ static blink::WebThreadSafeData CreateData(const std::string& str) {
class BlobTransportControllerTest : public testing::Test {
public:
- BlobTransportControllerTest()
- : io_thread_runner_(new base::TestSimpleTaskRunner()),
- main_thread_runner_(new OtherThreadTestSimpleTaskRunner()) {}
+ BlobTransportControllerTest() : thread_runner_handle_(io_thread_runner_) {}
void SetUp() override {
sender_ = new BlobTransportControllerTestSender(&sink_);
- BlobTransportController::GetInstance()->ClearForTesting();
+ BlobTransportController::GetInstance()->CancelAllBlobTransfers();
+ }
+
+ void OnMemoryRequest(
+ BlobTransportController* holder,
+ const std::string uuid,
+ const std::vector<storage::BlobItemBytesRequest>& requests,
+ std::vector<base::SharedMemoryHandle>* memory_handles,
+ std::vector<IPC::PlatformFileForTransit> file_handles) {
+ holder->OnMemoryRequest(uuid, requests, memory_handles, file_handles,
+ file_thread_runner_.get(), &sink_);
+ }
+
+ FilePath CreateTemporaryFile() {
+ FilePath path;
+ EXPECT_TRUE(base::CreateTemporaryFile(&path));
+ files_opened_.push_back(path);
+ return path;
}
void ExpectRegisterAndStartMessage(const std::string& expected_uuid,
@@ -105,28 +134,74 @@ class BlobTransportControllerTest : public testing::Test {
sink_.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID);
ASSERT_TRUE(register_message);
ASSERT_TRUE(start_message);
- base::Tuple<std::string, std::string, std::string, std::set<std::string>>
+ std::tuple<std::string, std::string, std::string, std::set<std::string>>
register_contents;
- base::Tuple<std::string, std::vector<DataElement>> start_contents;
+ std::tuple<std::string, std::vector<DataElement>> start_contents;
BlobStorageMsg_RegisterBlobUUID::Read(register_message, &register_contents);
BlobStorageMsg_StartBuildingBlob::Read(start_message, &start_contents);
- EXPECT_EQ(expected_uuid, base::get<0>(register_contents));
- EXPECT_EQ(expected_uuid, base::get<0>(start_contents));
- EXPECT_EQ(expected_content_type, base::get<1>(register_contents));
+ EXPECT_EQ(expected_uuid, std::get<0>(register_contents));
+ EXPECT_EQ(expected_uuid, std::get<0>(start_contents));
+ EXPECT_EQ(expected_content_type, std::get<1>(register_contents));
if (descriptions)
- *descriptions = base::get<1>(start_contents);
+ *descriptions = std::get<1>(start_contents);
// We don't have dispositions from the renderer.
- EXPECT_TRUE(base::get<2>(register_contents).empty());
+ EXPECT_TRUE(std::get<2>(register_contents).empty());
+ sink_.ClearMessages();
+ }
+
+ void ExpectMemoryResponses(
+ const std::string& expected_uuid,
+ std::vector<storage::BlobItemBytesResponse> expected_responses) {
+ const IPC::Message* responses_message =
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_MemoryItemResponse::ID);
+ ASSERT_TRUE(responses_message);
+ std::tuple<std::string, std::vector<storage::BlobItemBytesResponse>>
+ responses_content;
+ BlobStorageMsg_MemoryItemResponse::Read(responses_message,
+ &responses_content);
+ EXPECT_EQ(expected_uuid, std::get<0>(responses_content));
+ EXPECT_EQ(expected_responses, std::get<1>(responses_content));
+ sink_.ClearMessages();
+ }
+
+ void ExpectCancel(const std::string& expected_uuid,
+ storage::IPCBlobCreationCancelCode expected_code) {
+ const IPC::Message* cancel_message =
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID);
+ ASSERT_TRUE(cancel_message);
+ std::tuple<std::string, storage::IPCBlobCreationCancelCode> cancel_content;
+ BlobStorageMsg_CancelBuildingBlob::Read(cancel_message, &cancel_content);
+ EXPECT_EQ(expected_uuid, std::get<0>(cancel_content));
+ EXPECT_EQ(expected_code, std::get<1>(cancel_content));
}
void TearDown() override {
- BlobTransportController::GetInstance()->ClearForTesting();
+ BlobTransportController::GetInstance()->CancelAllBlobTransfers();
+ for (const FilePath& path : files_opened_) {
+ EXPECT_TRUE(base::DeleteFile(path, false));
+ }
+ EXPECT_FALSE(io_thread_runner_->HasPendingTask());
+ EXPECT_FALSE(file_thread_runner_->HasPendingTask());
+ EXPECT_FALSE(main_thread_runner_->HasPendingTask());
}
+ protected:
+ std::vector<FilePath> files_opened_;
+
IPC::TestSink sink_;
scoped_refptr<BlobTransportControllerTestSender> sender_;
- scoped_refptr<base::TestSimpleTaskRunner> io_thread_runner_;
- scoped_refptr<OtherThreadTestSimpleTaskRunner> main_thread_runner_;
+
+ // Thread runners.
+ scoped_refptr<base::TestSimpleTaskRunner> io_thread_runner_ =
+ new TestSimpleTaskRunner();
+ scoped_refptr<base::TestSimpleTaskRunner> file_thread_runner_ =
+ new TestSimpleTaskRunner();
+ scoped_refptr<OtherThreadTestSimpleTaskRunner> main_thread_runner_ =
+ new OtherThreadTestSimpleTaskRunner();
+
+ // We set this to the IO thread runner, as this is used for the
+ // OnMemoryRequest calls, which are on that thread.
+ base::ThreadTaskRunnerHandle thread_runner_handle_;
};
TEST_F(BlobTransportControllerTest, Descriptions) {
@@ -136,7 +211,7 @@ TEST_F(BlobTransportControllerTest, Descriptions) {
const size_t kShortcutSize = 11;
// The first two data elements should be combined and the data shortcut.
- std::unique_ptr<BlobConsolidation> consolidation(new BlobConsolidation());
+ scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation());
consolidation->AddBlobItem(KRefBlobUUID, 10, 10);
consolidation->AddDataItem(CreateData("Hello"));
consolidation->AddDataItem(CreateData("Hello2"));
@@ -156,14 +231,13 @@ TEST_F(BlobTransportControllerTest, Descriptions) {
}
TEST_F(BlobTransportControllerTest, Responses) {
- using ResponsesStatus = BlobTransportController::ResponsesStatus;
const std::string kBlobUUID = "uuid";
const std::string KRefBlobUUID = "refuuid";
const std::string kBadBlobUUID = "uuuidBad";
BlobTransportController* holder = BlobTransportController::GetInstance();
// The first two data elements should be combined.
- BlobConsolidation* consolidation = new BlobConsolidation();
+ scoped_refptr<BlobConsolidation> consolidation = new BlobConsolidation();
consolidation->AddBlobItem(KRefBlobUUID, 10, 10);
consolidation->AddDataItem(CreateData("Hello"));
consolidation->AddDataItem(CreateData("Hello2"));
@@ -171,57 +245,44 @@ TEST_F(BlobTransportControllerTest, Responses) {
consolidation->AddDataItem(CreateData("Hello3"));
// See the above test for the expected descriptions layout.
- holder->blob_storage_[kBlobUUID] = base::WrapUnique(consolidation);
+ holder->blob_storage_[kBlobUUID] = consolidation;
std::vector<BlobItemBytesRequest> requests;
std::vector<base::SharedMemoryHandle> memory_handles;
std::vector<IPC::PlatformFileForTransit> file_handles;
- std::vector<storage::BlobItemBytesResponse> output;
// Request for all of first data
requests.push_back(BlobItemBytesRequest::CreateIPCRequest(0, 1, 0, 11));
- EXPECT_EQ(ResponsesStatus::SUCCESS,
- holder->GetResponses(kBlobUUID, requests, &memory_handles,
- file_handles, &output));
- EXPECT_EQ(1u, output.size());
+ OnMemoryRequest(holder, kBlobUUID, requests, &memory_handles, file_handles);
std::vector<storage::BlobItemBytesResponse> expected;
expected.push_back(ResponseWithData(0, "HelloHello2"));
- EXPECT_EQ(expected, output);
+ ExpectMemoryResponses(kBlobUUID, expected);
// Part of second data
- output.clear();
requests[0] = BlobItemBytesRequest::CreateIPCRequest(1000, 3, 1, 5);
- EXPECT_EQ(ResponsesStatus::SUCCESS,
- holder->GetResponses(kBlobUUID, requests, &memory_handles,
- file_handles, &output));
- EXPECT_EQ(1u, output.size());
+ OnMemoryRequest(holder, kBlobUUID, requests, &memory_handles, file_handles);
expected.clear();
expected.push_back(ResponseWithData(1000, "ello3"));
- EXPECT_EQ(expected, output);
+ ExpectMemoryResponses(kBlobUUID, expected);
// Both data segments
- output.clear();
requests[0] = BlobItemBytesRequest::CreateIPCRequest(0, 1, 0, 11);
requests.push_back(BlobItemBytesRequest::CreateIPCRequest(1, 3, 0, 6));
- EXPECT_EQ(ResponsesStatus::SUCCESS,
- holder->GetResponses(kBlobUUID, requests, &memory_handles,
- file_handles, &output));
- EXPECT_EQ(2u, output.size());
+ OnMemoryRequest(holder, kBlobUUID, requests, &memory_handles, file_handles);
expected.clear();
expected.push_back(ResponseWithData(0, "HelloHello2"));
expected.push_back(ResponseWithData(1, "Hello3"));
- EXPECT_EQ(expected, output);
+ ExpectMemoryResponses(kBlobUUID, expected);
}
TEST_F(BlobTransportControllerTest, SharedMemory) {
- using ResponsesStatus = BlobTransportController::ResponsesStatus;
const std::string kBlobUUID = "uuid";
const std::string KRefBlobUUID = "refuuid";
const std::string kBadBlobUUID = "uuuidBad";
BlobTransportController* holder = BlobTransportController::GetInstance();
// The first two data elements should be combined.
- BlobConsolidation* consolidation = new BlobConsolidation();
+ scoped_refptr<BlobConsolidation> consolidation = new BlobConsolidation();
consolidation->AddBlobItem(KRefBlobUUID, 10, 10);
consolidation->AddDataItem(CreateData("Hello"));
consolidation->AddDataItem(CreateData("Hello2"));
@@ -229,12 +290,11 @@ TEST_F(BlobTransportControllerTest, SharedMemory) {
consolidation->AddDataItem(CreateData("Hello3"));
// See the above test for the expected descriptions layout.
- holder->blob_storage_[kBlobUUID] = base::WrapUnique(consolidation);
+ holder->blob_storage_[kBlobUUID] = consolidation;
std::vector<BlobItemBytesRequest> requests;
std::vector<base::SharedMemoryHandle> memory_handles;
std::vector<IPC::PlatformFileForTransit> file_handles;
- std::vector<storage::BlobItemBytesResponse> output;
// Request for all data in shared memory
requests.push_back(
@@ -248,14 +308,11 @@ TEST_F(BlobTransportControllerTest, SharedMemory) {
CHECK(base::SharedMemory::NULLHandle() != handle);
memory_handles.push_back(handle);
- EXPECT_EQ(ResponsesStatus::SUCCESS,
- holder->GetResponses(kBlobUUID, requests, &memory_handles,
- file_handles, &output));
- EXPECT_EQ(2u, output.size());
+ OnMemoryRequest(holder, kBlobUUID, requests, &memory_handles, file_handles);
std::vector<storage::BlobItemBytesResponse> expected;
expected.push_back(BlobItemBytesResponse(0));
expected.push_back(BlobItemBytesResponse(1));
- EXPECT_EQ(expected, output);
+ ExpectMemoryResponses(kBlobUUID, expected);
std::string expected_memory = "HelloHello2Hello3";
memory.Map(11 + 6);
const char* mem_location = static_cast<const char*>(memory.memory());
@@ -264,19 +321,90 @@ TEST_F(BlobTransportControllerTest, SharedMemory) {
expected_memory.size()));
}
-TEST_F(BlobTransportControllerTest, TestPublicMethods) {
+TEST_F(BlobTransportControllerTest, Disk) {
+ const std::string kBlobUUID = "uuid";
+ const std::string kRefBlobUUID = "refuuid";
+ const std::string kBadBlobUUID = "uuuidBad";
+ const std::string kDataPart1 = "Hello";
+ const std::string kDataPart2 = "Hello2";
+ const std::string kDataPart3 = "Hello3";
+ const std::string kData = "HelloHello2Hello3";
+ BlobTransportController* holder = BlobTransportController::GetInstance();
+ FilePath path1 = CreateTemporaryFile();
+ File file(path1, File::FLAG_OPEN | File::FLAG_WRITE | File::FLAG_READ);
+ ASSERT_TRUE(file.IsValid());
+ ASSERT_TRUE(file.SetLength(11 + 6));
+ // The first two data elements should be combined.
+ scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation());
+ consolidation->AddBlobItem(kRefBlobUUID, 10, 10);
+ consolidation->AddDataItem(CreateData(kDataPart1));
+ consolidation->AddDataItem(CreateData(kDataPart2));
+ consolidation->AddBlobItem(kRefBlobUUID, 0, 10);
+ consolidation->AddDataItem(CreateData(kDataPart3));
+ // See the above test for the expected descriptions layout.
+ holder->blob_storage_[kBlobUUID] = consolidation;
+ holder->main_thread_runner_ = main_thread_runner_;
+ std::vector<BlobItemBytesRequest> requests;
+ std::vector<base::SharedMemoryHandle> memory_handles;
+ std::vector<IPC::PlatformFileForTransit> file_handles;
+ // Request for all data in files.
+ requests.push_back(
+ BlobItemBytesRequest::CreateFileRequest(0, 1, 0, 11, 0, 0));
+ requests.push_back(
+ BlobItemBytesRequest::CreateFileRequest(1, 3, 0, 6, 0, 11));
+ file_handles.push_back(IPC::TakePlatformFileForTransit(std::move(file)));
+ OnMemoryRequest(holder, kBlobUUID, requests, &memory_handles, file_handles);
+ file_handles.clear();
+ EXPECT_TRUE(file_thread_runner_->HasPendingTask());
+ EXPECT_FALSE(io_thread_runner_->HasPendingTask());
+ file_thread_runner_->RunPendingTasks();
+ EXPECT_FALSE(file_thread_runner_->HasPendingTask());
+ EXPECT_TRUE(io_thread_runner_->HasPendingTask());
+ io_thread_runner_->RunPendingTasks();
+ std::vector<storage::BlobItemBytesResponse> expected = {
+ BlobItemBytesResponse(0), BlobItemBytesResponse(1)};
+ ExpectMemoryResponses(kBlobUUID, expected);
+ file = File(path1, File::FLAG_OPEN | File::FLAG_READ);
+ char data[11 + 6];
+ file.Read(0, data, 11 + 6);
+ std::vector<char> value(data, data + 11 + 6);
+ EXPECT_THAT(value, testing::ElementsAreArray(kData.c_str(), kData.size()));
+
+ // Finally, test that we get errors correctly.
+ FilePath path2 = CreateTemporaryFile();
+ EXPECT_TRUE(base::MakeFileUnwritable(path2));
+ File file2(path2, File::FLAG_OPEN | File::FLAG_WRITE);
+ EXPECT_FALSE(file2.IsValid());
+ file_handles.push_back(IPC::TakePlatformFileForTransit(std::move(file2)));
+ OnMemoryRequest(holder, kBlobUUID, requests, &memory_handles, file_handles);
+ EXPECT_TRUE(file_thread_runner_->HasPendingTask());
+ file_thread_runner_->RunPendingTasks();
+ EXPECT_TRUE(io_thread_runner_->HasPendingTask());
+ io_thread_runner_->RunPendingTasks();
+ // Clear the main thread task, as it has the AddRef job.
+ EXPECT_TRUE(main_thread_runner_->HasPendingTask());
+ main_thread_runner_->ClearPendingTasks();
+ ExpectCancel(kBlobUUID, IPCBlobCreationCancelCode::FILE_WRITE_FAILED);
+}
+
+TEST_F(BlobTransportControllerTest, PublicMethods) {
const std::string kBlobUUID = "uuid";
const std::string kBlobContentType = "content_type";
const std::string kBlob2UUID = "uuid2";
const std::string kBlob2ContentType = "content_type2";
const std::string KRefBlobUUID = "refuuid";
+ const std::string kDataPart1 = "Hello";
+ const std::string kDataPart2 = "Hello2";
+ const std::string kDataPart3 = "Hello3";
+ const std::string kData = "HelloHello2Hello3";
std::vector<DataElement> message_descriptions;
BlobTransportController* holder = BlobTransportController::GetInstance();
- BlobConsolidation* consolidation = new BlobConsolidation();
+ // Here we test that the
+ scoped_refptr<BlobConsolidation> consolidation = new BlobConsolidation();
consolidation->AddBlobItem(KRefBlobUUID, 10, 10);
BlobTransportController::InitiateBlobTransfer(
- kBlobUUID, kBlobContentType, base::WrapUnique(consolidation), sender_,
+ kBlobUUID, kBlobContentType, consolidation, sender_,
io_thread_runner_.get(), main_thread_runner_);
// Check that we have the 'increase ref' pending task.
EXPECT_TRUE(main_thread_runner_->HasPendingTask());
@@ -291,11 +419,11 @@ TEST_F(BlobTransportControllerTest, TestPublicMethods) {
EXPECT_FALSE(holder->IsTransporting(kBlobUUID));
io_thread_runner_->RunPendingTasks();
EXPECT_TRUE(holder->IsTransporting(kBlobUUID));
- base::Tuple<std::string, std::vector<DataElement>> message_contents;
+ std::tuple<std::string, std::vector<DataElement>> message_contents;
+ EXPECT_TRUE(holder->IsTransporting(kBlobUUID));
EXPECT_EQ(MakeBlobElement(KRefBlobUUID, 10, 10), message_descriptions[0]);
- holder->OnCancel(kBlobUUID,
- storage::IPCBlobCreationCancelCode::OUT_OF_MEMORY);
+ holder->OnCancel(kBlobUUID, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
EXPECT_FALSE(holder->IsTransporting(kBlobUUID));
// Check we have the 'decrease ref' task.
EXPECT_TRUE(main_thread_runner_->HasPendingTask());
@@ -303,17 +431,48 @@ TEST_F(BlobTransportControllerTest, TestPublicMethods) {
sink_.ClearMessages();
// Add the second.
- BlobConsolidation* consolidation2 = new BlobConsolidation();
+ scoped_refptr<BlobConsolidation> consolidation2 = new BlobConsolidation();
consolidation2->AddBlobItem(KRefBlobUUID, 10, 10);
+ // These items should be combined.
+ consolidation2->AddDataItem(CreateData(kDataPart1));
+ consolidation2->AddDataItem(CreateData(kDataPart2));
+ consolidation2->AddDataItem(CreateData(kDataPart3));
BlobTransportController::InitiateBlobTransfer(
- kBlob2UUID, kBlob2ContentType, base::WrapUnique(consolidation2), sender_,
+ kBlob2UUID, kBlob2ContentType, consolidation2, sender_,
io_thread_runner_.get(), main_thread_runner_);
+ // Check that we have the 'increase ref' pending task.
EXPECT_TRUE(main_thread_runner_->HasPendingTask());
+ // Check that we have the 'store' pending task.
+ EXPECT_TRUE(io_thread_runner_->HasPendingTask());
+ // Check that we've sent the data.
+ message_descriptions.clear();
+ ExpectRegisterAndStartMessage(kBlob2UUID, kBlob2ContentType,
+ &message_descriptions);
main_thread_runner_->ClearPendingTasks();
- sink_.ClearMessages();
+ // Check that we got the correct start message.
+ EXPECT_FALSE(holder->IsTransporting(kBlob2UUID));
io_thread_runner_->RunPendingTasks();
EXPECT_TRUE(holder->IsTransporting(kBlob2UUID));
+ ASSERT_EQ(2u, message_descriptions.size());
+ EXPECT_EQ(MakeBlobElement(KRefBlobUUID, 10, 10), message_descriptions[0]);
+ EXPECT_EQ(MakeDataElement(kData), message_descriptions[1]);
+ EXPECT_FALSE(main_thread_runner_->HasPendingTask());
+
+ // Now we request the memory.
+ std::vector<BlobItemBytesRequest> requests;
+ std::vector<base::SharedMemoryHandle> memory_handles;
+ std::vector<IPC::PlatformFileForTransit> file_handles;
+ requests.push_back(
+ BlobItemBytesRequest::CreateIPCRequest(0, 1, 0, kData.size()));
+ OnMemoryRequest(holder, kBlob2UUID, requests, &memory_handles, file_handles);
+
+ std::vector<BlobItemBytesResponse> expected_responses;
+ BlobItemBytesResponse expected(0);
+ expected.inline_data = std::vector<char>(kData.begin(), kData.end());
+ expected_responses.push_back(expected);
+ ExpectMemoryResponses(kBlob2UUID, expected_responses);
+ EXPECT_FALSE(main_thread_runner_->HasPendingTask());
// Finish the second one.
holder->OnDone(kBlob2UUID);
@@ -322,28 +481,4 @@ TEST_F(BlobTransportControllerTest, TestPublicMethods) {
main_thread_runner_->ClearPendingTasks();
}
-TEST_F(BlobTransportControllerTest, ResponsesErrors) {
- using ResponsesStatus = BlobTransportController::ResponsesStatus;
- const std::string kBlobUUID = "uuid";
- const std::string KRefBlobUUID = "refuuid";
- const std::string kBadBlobUUID = "uuuidBad";
- BlobTransportController* holder = BlobTransportController::GetInstance();
-
- BlobConsolidation* consolidation = new BlobConsolidation();
- consolidation->AddBlobItem(KRefBlobUUID, 10, 10);
-
- holder->blob_storage_[kBlobUUID] = base::WrapUnique(consolidation);
-
- std::vector<BlobItemBytesRequest> requests;
- std::vector<base::SharedMemoryHandle> memory_handles;
- std::vector<IPC::PlatformFileForTransit> file_handles;
- std::vector<storage::BlobItemBytesResponse> output;
-
- // Error conditions
- EXPECT_EQ(ResponsesStatus::BLOB_NOT_FOUND,
- holder->GetResponses(kBadBlobUUID, requests, &memory_handles,
- file_handles, &output));
- EXPECT_EQ(0u, output.size());
-}
-
} // namespace content
diff --git a/chromium/content/child/blob_storage/webblobregistry_impl.h b/chromium/content/child/blob_storage/webblobregistry_impl.h
index 474e9b83055..601fded9dc3 100644
--- a/chromium/content/child/blob_storage/webblobregistry_impl.h
+++ b/chromium/content/child/blob_storage/webblobregistry_impl.h
@@ -92,7 +92,7 @@ class WebBlobRegistryImpl : public blink::WebBlobRegistry {
private:
const std::string uuid_;
const std::string content_type_;
- std::unique_ptr<BlobConsolidation> consolidation_;
+ scoped_refptr<BlobConsolidation> consolidation_;
scoped_refptr<ThreadSafeSender> sender_;
scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
scoped_refptr<base::SingleThreadTaskRunner> main_runner_;
diff --git a/chromium/content/child/child_discardable_shared_memory_manager.cc b/chromium/content/child/child_discardable_shared_memory_manager.cc
index 1bb4ac5af4a..8cf113a7556 100644
--- a/chromium/content/child/child_discardable_shared_memory_manager.cc
+++ b/chromium/content/child/child_discardable_shared_memory_manager.cc
@@ -4,6 +4,8 @@
#include "content/child/child_discardable_shared_memory_manager.h"
+#include <inttypes.h>
+
#include <algorithm>
#include <utility>
@@ -18,6 +20,7 @@
#include "base/process/memory.h"
#include "base/process/process_metrics.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
@@ -214,6 +217,23 @@ bool ChildDiscardableSharedMemoryManager::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
base::AutoLock lock(lock_);
+ if (args.level_of_detail ==
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
+ base::trace_event::MemoryAllocatorDump* total_dump =
+ pmd->CreateAllocatorDump(
+ base::StringPrintf("discardable/child_0x%" PRIXPTR,
+ reinterpret_cast<uintptr_t>(this)));
+ const size_t total_size = heap_.GetSize();
+ const size_t freelist_size = heap_.GetSizeOfFreeLists();
+ total_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ total_size - freelist_size);
+ total_dump->AddScalar("freelist_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ freelist_size);
+ return true;
+ }
+
return heap_.OnMemoryDump(pmd);
}
diff --git a/chromium/content/child/child_process.cc b/chromium/content/child/child_process.cc
index 6d50239f14b..8411653ad8c 100644
--- a/chromium/content/child/child_process.cc
+++ b/chromium/content/child/child_process.cc
@@ -38,7 +38,8 @@ ChildProcess::ChildProcess() : ChildProcess(base::ThreadPriority::NORMAL) {}
ChildProcess::ChildProcess(base::ThreadPriority io_thread_priority)
: ref_count_(0),
- shutdown_event_(true, false),
+ shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
io_thread_("Chrome_ChildIOThread") {
DCHECK(!g_lazy_tls.Pointer()->Get());
g_lazy_tls.Pointer()->Set(this);
diff --git a/chromium/content/child/child_thread_impl.cc b/chromium/content/child/child_thread_impl.cc
index 0b5a69168c7..f8b6c1e26b5 100644
--- a/chromium/content/child/child_thread_impl.cc
+++ b/chromium/content/child/child_thread_impl.cc
@@ -31,7 +31,7 @@
#include "base/timer/elapsed_timer.h"
#include "base/tracked_objects.h"
#include "build/build_config.h"
-#include "components/tracing/child_trace_message_filter.h"
+#include "components/tracing/child/child_trace_message_filter.h"
#include "content/child/child_discardable_shared_memory_manager.h"
#include "content/child/child_gpu_memory_buffer_manager.h"
#include "content/child/child_histogram_message_filter.h"
@@ -41,7 +41,6 @@
#include "content/child/fileapi/file_system_dispatcher.h"
#include "content/child/fileapi/webfilesystem_impl.h"
#include "content/child/memory/child_memory_message_filter.h"
-#include "content/child/mojo/mojo_application.h"
#include "content/child/notifications/notification_dispatcher.h"
#include "content/child/power_monitor_broadcast_source.h"
#include "content/child/push_messaging/push_dispatcher.h"
@@ -51,22 +50,25 @@
#include "content/child/service_worker/service_worker_message_filter.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/websocket_dispatcher.h"
+#include "content/child/websocket_message_filter.h"
#include "content/common/child_process_messages.h"
#include "content/common/in_process_child_thread_params.h"
-#include "content/common/mojo/mojo_shell_connection_impl.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/mojo_channel_switches.h"
+#include "content/public/common/mojo_shell_connection.h"
#include "ipc/attachment_broker.h"
#include "ipc/attachment_broker_unprivileged.h"
+#include "ipc/ipc_channel_mojo.h"
#include "ipc/ipc_logging.h"
#include "ipc/ipc_platform_file.h"
#include "ipc/ipc_switches.h"
#include "ipc/ipc_sync_channel.h"
#include "ipc/ipc_sync_message_filter.h"
-#include "ipc/mojo/ipc_channel_mojo.h"
-#include "ipc/mojo/scoped_ipc_support.h"
#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/named_platform_channel_pair.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/scoped_ipc_support.h"
+#include "services/shell/runner/common/client_util.h"
#if defined(OS_POSIX)
#include "base/posix/global_descriptors.h"
@@ -228,9 +230,18 @@ base::LazyInstance<QuitClosure> g_quit_closure = LAZY_INSTANCE_INITIALIZER;
void InitializeMojoIPCChannel() {
mojo::edk::ScopedPlatformHandle platform_channel;
#if defined(OS_WIN)
- platform_channel =
- mojo::edk::PlatformChannelPair::PassClientHandleFromParentProcess(
- *base::CommandLine::ForCurrentProcess());
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch)) {
+ platform_channel =
+ mojo::edk::PlatformChannelPair::PassClientHandleFromParentProcess(
+ *base::CommandLine::ForCurrentProcess());
+ } else {
+ // If this process is elevated, it will have a pipe path passed on the
+ // command line.
+ platform_channel =
+ mojo::edk::NamedPlatformChannelPair::PassClientHandleFromParentProcess(
+ *base::CommandLine::ForCurrentProcess());
+ }
#elif defined(OS_POSIX)
platform_channel.reset(mojo::edk::PlatformHandle(
base::GlobalDescriptors::GetInstance()->Get(kMojoIPCChannel)));
@@ -251,7 +262,8 @@ ChildThread* ChildThread::Get() {
ChildThreadImpl::Options::Options()
: channel_name(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessChannelID)),
- use_mojo_channel(false) {
+ use_mojo_channel(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kMojoChannelToken)) {
}
ChildThreadImpl::Options::Options(const Options& other) = default;
@@ -385,27 +397,25 @@ void ChildThreadImpl::Init(const Options& options) {
if (!IsInBrowserProcess()) {
// Don't double-initialize IPC support in single-process mode.
- mojo_ipc_support_.reset(new IPC::ScopedIPCSupport(GetIOTaskRunner()));
+ mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport(GetIOTaskRunner()));
InitializeMojoIPCChannel();
}
-
- if (MojoShellConnectionImpl::Get()) {
- base::ElapsedTimer timer;
- MojoShellConnectionImpl::Get()->BindToRequestFromCommandLine();
- UMA_HISTOGRAM_TIMES("Mojo.Shell.ChildConnectionTime", timer.Elapsed());
- }
-
- mojo_application_.reset(new MojoApplication());
std::string mojo_application_token;
if (!IsInBrowserProcess()) {
mojo_application_token =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kMojoApplicationChannelToken);
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kMojoApplicationChannelToken);
} else {
mojo_application_token = options.in_process_application_token;
}
- if (!mojo_application_token.empty())
- mojo_application_->InitWithToken(mojo_application_token);
+ if (!mojo_application_token.empty()) {
+ mojo::ScopedMessagePipeHandle handle =
+ mojo::edk::CreateChildMessagePipe(mojo_application_token);
+ DCHECK(handle.is_valid());
+ mojo_shell_connection_ = MojoShellConnection::Create(
+ mojo::MakeRequest<shell::mojom::ShellClient>(std::move(handle)));
+ mojo_shell_connection_->AddEmbeddedShellClient(this);
+ }
sync_message_filter_ = channel_->CreateSyncMessageFilter();
thread_safe_sender_ = new ThreadSafeSender(
@@ -431,12 +441,16 @@ void ChildThreadImpl::Init(const Options& options) {
new NotificationDispatcher(thread_safe_sender_.get());
push_dispatcher_ = new PushDispatcher(thread_safe_sender_.get());
+ websocket_message_filter_ =
+ new WebSocketMessageFilter(websocket_dispatcher_.get());
+
channel_->AddFilter(histogram_message_filter_.get());
channel_->AddFilter(resource_message_filter_.get());
channel_->AddFilter(quota_message_filter_->GetFilter());
channel_->AddFilter(notification_dispatcher_->GetFilter());
channel_->AddFilter(push_dispatcher_->GetFilter());
channel_->AddFilter(service_worker_message_filter_->GetFilter());
+ channel_->AddFilter(websocket_message_filter_.get());
if (!IsInBrowserProcess()) {
// In single process mode, browser-side tracing and memory will cover the
@@ -503,6 +517,9 @@ void ChildThreadImpl::Init(const Options& options) {
}
ChildThreadImpl::~ChildThreadImpl() {
+ if (MojoShellConnection::GetForProcess())
+ MojoShellConnection::DestroyForProcess();
+
#ifdef IPC_MESSAGE_LOG_ENABLED
IPC::Logging::GetInstance()->SetIPCSender(NULL);
#endif
@@ -575,6 +592,30 @@ void ChildThreadImpl::RecordComputedAction(const std::string& action) {
NOTREACHED();
}
+MojoShellConnection* ChildThreadImpl::GetMojoShellConnection() {
+ return mojo_shell_connection_.get();
+}
+
+shell::InterfaceRegistry* ChildThreadImpl::GetInterfaceRegistry() {
+ if (!interface_registry_.get())
+ interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+ return interface_registry_.get();
+}
+
+shell::InterfaceProvider* ChildThreadImpl::GetRemoteInterfaces() {
+ if (!remote_interfaces_.get())
+ remote_interfaces_.reset(new shell::InterfaceProvider);
+ return remote_interfaces_.get();
+}
+
+shell::InterfaceRegistry* ChildThreadImpl::GetInterfaceRegistryForConnection() {
+ return GetInterfaceRegistry();
+}
+
+shell::InterfaceProvider* ChildThreadImpl::GetInterfaceProviderForConnection() {
+ return GetRemoteInterfaces();
+}
+
IPC::MessageRouter* ChildThreadImpl::GetRouter() {
DCHECK(base::MessageLoop::current() == message_loop());
return &router_;
@@ -618,8 +659,6 @@ bool ChildThreadImpl::OnMessageReceived(const IPC::Message& msg) {
// Resource responses are sent to the resource dispatcher.
if (resource_dispatcher_->OnMessageReceived(msg))
return true;
- if (websocket_dispatcher_->OnMessageReceived(msg))
- return true;
if (file_system_dispatcher_->OnMessageReceived(msg))
return true;
diff --git a/chromium/content/child/child_thread_impl.h b/chromium/content/child/child_thread_impl.h
index da51e2b4815..20c03e0e42f 100644
--- a/chromium/content/child/child_thread_impl.h
+++ b/chromium/content/child/child_thread_impl.h
@@ -18,12 +18,12 @@
#include "base/sequenced_task_runner.h"
#include "base/tracked_objects.h"
#include "build/build_config.h"
-#include "content/child/mojo/mojo_application.h"
#include "content/common/content_export.h"
#include "content/public/child/child_thread.h"
#include "ipc/ipc_message.h" // For IPC_MESSAGE_LOG_ENABLED.
#include "ipc/ipc_platform_file.h"
#include "ipc/message_router.h"
+#include "services/shell/public/cpp/shell_client.h"
namespace base {
class MessageLoop;
@@ -31,11 +31,16 @@ class MessageLoop;
namespace IPC {
class MessageFilter;
-class ScopedIPCSupport;
class SyncChannel;
class SyncMessageFilter;
} // namespace IPC
+namespace mojo {
+namespace edk {
+class ScopedIPCSupport;
+} // namespace edk
+} // namespace mojo
+
namespace blink {
class WebFrame;
} // namespace blink
@@ -57,12 +62,14 @@ class QuotaMessageFilter;
class ResourceDispatcher;
class ThreadSafeSender;
class WebSocketDispatcher;
+class WebSocketMessageFilter;
struct RequestInfo;
// The main thread of a child process derives from this class.
class CONTENT_EXPORT ChildThreadImpl
: public IPC::Listener,
- virtual public ChildThread {
+ virtual public ChildThread,
+ public NON_EXPORTED_BASE(shell::ShellClient){
public:
struct CONTENT_EXPORT Options;
@@ -90,6 +97,13 @@ class CONTENT_EXPORT ChildThreadImpl
#endif
void RecordAction(const base::UserMetricsAction& action) override;
void RecordComputedAction(const std::string& action) override;
+ MojoShellConnection* GetMojoShellConnection() override;
+ shell::InterfaceRegistry* GetInterfaceRegistry() override;
+ shell::InterfaceProvider* GetRemoteInterfaces() override;
+
+ // shell::ShellClient:
+ shell::InterfaceRegistry* GetInterfaceRegistryForConnection() override;
+ shell::InterfaceProvider* GetInterfaceProviderForConnection() override;
IPC::SyncChannel* channel() { return channel_.get(); }
@@ -174,6 +188,10 @@ class CONTENT_EXPORT ChildThreadImpl
return resource_message_filter_.get();
}
+ WebSocketMessageFilter* websocket_message_filter() const {
+ return websocket_message_filter_.get();
+ }
+
base::MessageLoop* message_loop() const { return message_loop_; }
// Returns the one child thread. Can only be called on the main thread.
@@ -185,10 +203,6 @@ class CONTENT_EXPORT ChildThreadImpl
static void ShutdownThread();
#endif
- ServiceRegistry* service_registry() const {
- return mojo_application_->service_registry();
- }
-
protected:
friend class ChildProcess;
@@ -238,8 +252,10 @@ class CONTENT_EXPORT ChildThreadImpl
void EnsureConnected();
- std::unique_ptr<IPC::ScopedIPCSupport> mojo_ipc_support_;
- std::unique_ptr<MojoApplication> mojo_application_;
+ std::unique_ptr<mojo::edk::ScopedIPCSupport> mojo_ipc_support_;
+ std::unique_ptr<MojoShellConnection> mojo_shell_connection_;
+ std::unique_ptr<shell::InterfaceRegistry> interface_registry_;
+ std::unique_ptr<shell::InterfaceProvider> remote_interfaces_;
std::string channel_name_;
std::unique_ptr<IPC::SyncChannel> channel_;
@@ -276,6 +292,8 @@ class CONTENT_EXPORT ChildThreadImpl
scoped_refptr<QuotaMessageFilter> quota_message_filter_;
+ scoped_refptr<WebSocketMessageFilter> websocket_message_filter_;
+
scoped_refptr<NotificationDispatcher> notification_dispatcher_;
scoped_refptr<PushDispatcher> push_dispatcher_;
diff --git a/chromium/content/child/child_thread_impl_browsertest.cc b/chromium/content/child/child_thread_impl_browsertest.cc
index 36aac676eec..f1f9d868031 100644
--- a/chromium/content/child/child_thread_impl_browsertest.cc
+++ b/chromium/content/child/child_thread_impl_browsertest.cc
@@ -204,7 +204,7 @@ INSTANTIATE_TEST_CASE_P(
gfx::BufferFormat::RGBA_4444,
gfx::BufferFormat::RGBA_8888,
gfx::BufferFormat::BGRA_8888,
- gfx::BufferFormat::YUV_420)));
+ gfx::BufferFormat::YVU_420)));
} // namespace
} // namespace content
diff --git a/chromium/content/child/database_util.cc b/chromium/content/child/database_util.cc
index 844799e1200..2dd4754a249 100644
--- a/chromium/content/child/database_util.cc
+++ b/chromium/content/child/database_util.cc
@@ -6,10 +6,12 @@
#include "content/common/database_messages.h"
#include "ipc/ipc_sync_message_filter.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/sqlite/sqlite3.h"
using blink::Platform;
+using blink::WebSecurityOrigin;
using blink::WebString;
namespace content {
@@ -56,11 +58,10 @@ long long DatabaseUtil::DatabaseGetFileSize(
}
long long DatabaseUtil::DatabaseGetSpaceAvailable(
- const WebString& origin_identifier,
+ const WebSecurityOrigin& origin,
IPC::SyncMessageFilter* sync_message_filter) {
int64_t rv = 0LL;
- sync_message_filter->Send(
- new DatabaseHostMsg_GetSpaceAvailable(origin_identifier.utf8(), &rv));
+ sync_message_filter->Send(new DatabaseHostMsg_GetSpaceAvailable(origin, &rv));
return rv;
}
diff --git a/chromium/content/child/database_util.h b/chromium/content/child/database_util.h
index adeb3972d88..df6e545c32c 100644
--- a/chromium/content/child/database_util.h
+++ b/chromium/content/child/database_util.h
@@ -34,7 +34,7 @@ class DatabaseUtil {
const blink::WebString& vfs_file_name,
IPC::SyncMessageFilter* sync_message_filter);
static long long DatabaseGetSpaceAvailable(
- const blink::WebString& origin_identifier,
+ const blink::WebSecurityOrigin& origin,
IPC::SyncMessageFilter* sync_message_filter);
static bool DatabaseSetFileSize(const blink::WebString& vfs_file_name,
int64_t size,
diff --git a/chromium/content/child/db_message_filter.cc b/chromium/content/child/db_message_filter.cc
index 9e65a38fc05..5c4045df4df 100644
--- a/chromium/content/child/db_message_filter.cc
+++ b/chromium/content/child/db_message_filter.cc
@@ -10,23 +10,13 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDatabase.h"
+#include "url/origin.h"
using blink::WebSecurityOrigin;
using blink::WebString;
namespace content {
-namespace {
-
-// TODO(jsbell): Pass url::Origin over IPC instead of database identifier/GURL.
-// https://crbug.com/591482
-WebSecurityOrigin OriginFromIdentifier(const std::string& identifier) {
- return WebSecurityOrigin::create(
- storage::GetOriginFromIdentifier(identifier));
-}
-
-} // namespace
-
DBMessageFilter::DBMessageFilter() {
}
@@ -45,31 +35,29 @@ bool DBMessageFilter::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void DBMessageFilter::OnDatabaseUpdateSize(const std::string& origin_identifier,
+void DBMessageFilter::OnDatabaseUpdateSize(const url::Origin& origin,
const base::string16& database_name,
int64_t database_size) {
- blink::WebDatabase::updateDatabaseSize(
- OriginFromIdentifier(origin_identifier), database_name, database_size);
+ DCHECK(!origin.unique());
+ blink::WebDatabase::updateDatabaseSize(origin, database_name, database_size);
}
-void DBMessageFilter::OnDatabaseUpdateSpaceAvailable(
- const std::string& origin_identifier,
- int64_t space_available) {
- blink::WebDatabase::updateSpaceAvailable(
- OriginFromIdentifier(origin_identifier), space_available);
+void DBMessageFilter::OnDatabaseUpdateSpaceAvailable(const url::Origin& origin,
+ int64_t space_available) {
+ DCHECK(!origin.unique());
+ blink::WebDatabase::updateSpaceAvailable(origin, space_available);
}
-void DBMessageFilter::OnDatabaseResetSpaceAvailable(
- const std::string& origin_identifier) {
- blink::WebDatabase::resetSpaceAvailable(
- OriginFromIdentifier(origin_identifier));
+void DBMessageFilter::OnDatabaseResetSpaceAvailable(const url::Origin& origin) {
+ DCHECK(!origin.unique());
+ blink::WebDatabase::resetSpaceAvailable(origin);
}
void DBMessageFilter::OnDatabaseCloseImmediately(
- const std::string& origin_identifier,
+ const url::Origin& origin,
const base::string16& database_name) {
- blink::WebDatabase::closeDatabaseImmediately(
- OriginFromIdentifier(origin_identifier), database_name);
+ DCHECK(!origin.unique());
+ blink::WebDatabase::closeDatabaseImmediately(origin, database_name);
}
} // namespace content
diff --git a/chromium/content/child/db_message_filter.h b/chromium/content/child/db_message_filter.h
index fb1875e2646..55cc2a72565 100644
--- a/chromium/content/child/db_message_filter.h
+++ b/chromium/content/child/db_message_filter.h
@@ -10,6 +10,10 @@
#include "base/strings/string16.h"
#include "ipc/message_filter.h"
+namespace url {
+class Origin;
+} // namespace url
+
namespace content {
// Receives database messages from the browser process and processes them on the
@@ -25,13 +29,13 @@ class DBMessageFilter : public IPC::MessageFilter {
~DBMessageFilter() override {}
private:
- void OnDatabaseUpdateSize(const std::string& origin_identifier,
+ void OnDatabaseUpdateSize(const url::Origin& origin,
const base::string16& database_name,
int64_t database_size);
- void OnDatabaseUpdateSpaceAvailable(const std::string& origin_identifier,
+ void OnDatabaseUpdateSpaceAvailable(const url::Origin& origin,
int64_t space_available);
- void OnDatabaseResetSpaceAvailable(const std::string& origin_identifier);
- void OnDatabaseCloseImmediately(const std::string& origin_identifier,
+ void OnDatabaseResetSpaceAvailable(const url::Origin& origin);
+ void OnDatabaseCloseImmediately(const url::Origin& origin,
const base::string16& database_name);
};
diff --git a/chromium/content/child/dwrite_font_proxy/font_fallback_win_unittest.cc b/chromium/content/child/dwrite_font_proxy/font_fallback_win_unittest.cc
index aab440c4872..b5faca2bcc0 100644
--- a/chromium/content/child/dwrite_font_proxy/font_fallback_win_unittest.cc
+++ b/chromium/content/child/dwrite_font_proxy/font_fallback_win_unittest.cc
@@ -12,9 +12,9 @@
#include "base/memory/ref_counted.h"
#include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
-#include "content/common/dwrite_text_analysis_source_win.h"
#include "content/test/dwrite_font_fake_sender_win.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/win/text_analysis_source.h"
namespace mswr = Microsoft::WRL;
@@ -78,8 +78,8 @@ TEST_F(FontFallbackUnitTest, MapCharacters) {
UINT32 mapped_length = 0;
float scale = 0.0;
- mswr::ComPtr<TextAnalysisSource> text;
- mswr::MakeAndInitialize<TextAnalysisSource>(
+ mswr::ComPtr<gfx::win::TextAnalysisSource> text;
+ mswr::MakeAndInitialize<gfx::win::TextAnalysisSource>(
&text, L"hello", L"en-us", number_substitution_.Get(),
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
fallback->MapCharacters(text.Get(), 0, 5, nullptr, nullptr,
@@ -100,8 +100,8 @@ TEST_F(FontFallbackUnitTest, DuplicateCallsShouldNotRepeatIPC) {
UINT32 mapped_length = 0;
float scale = 0.0;
- mswr::ComPtr<TextAnalysisSource> text;
- mswr::MakeAndInitialize<TextAnalysisSource>(
+ mswr::ComPtr<gfx::win::TextAnalysisSource> text;
+ mswr::MakeAndInitialize<gfx::win::TextAnalysisSource>(
&text, L"hello", L"en-us", number_substitution_.Get(),
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
fallback->MapCharacters(text.Get(), 0, 5, nullptr, nullptr,
@@ -127,8 +127,8 @@ TEST_F(FontFallbackUnitTest, DifferentFamilyShouldNotReuseCache) {
UINT32 mapped_length = 0;
float scale = 0.0;
- mswr::ComPtr<TextAnalysisSource> text;
- mswr::MakeAndInitialize<TextAnalysisSource>(
+ mswr::ComPtr<gfx::win::TextAnalysisSource> text;
+ mswr::MakeAndInitialize<gfx::win::TextAnalysisSource>(
&text, L"hello", L"en-us", number_substitution_.Get(),
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
fallback->MapCharacters(text.Get(), 0, 5, nullptr, L"font1",
@@ -152,12 +152,12 @@ TEST_F(FontFallbackUnitTest, CacheMissShouldRepeatIPC) {
UINT32 mapped_length = 0;
float scale = 0.0;
- mswr::ComPtr<TextAnalysisSource> text;
- mswr::MakeAndInitialize<TextAnalysisSource>(
+ mswr::ComPtr<gfx::win::TextAnalysisSource> text;
+ mswr::MakeAndInitialize<gfx::win::TextAnalysisSource>(
&text, L"hello", L"en-us", number_substitution_.Get(),
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
- mswr::ComPtr<TextAnalysisSource> unmappable_text;
- mswr::MakeAndInitialize<TextAnalysisSource>(
+ mswr::ComPtr<gfx::win::TextAnalysisSource> unmappable_text;
+ mswr::MakeAndInitialize<gfx::win::TextAnalysisSource>(
&unmappable_text, L"\uffff", L"en-us", number_substitution_.Get(),
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
fallback->MapCharacters(text.Get(), 0, 5, nullptr, nullptr,
@@ -181,12 +181,12 @@ TEST_F(FontFallbackUnitTest, SurrogatePairCacheHit) {
UINT32 mapped_length = 0;
float scale = 0.0;
- mswr::ComPtr<TextAnalysisSource> text;
- mswr::MakeAndInitialize<TextAnalysisSource>(
+ mswr::ComPtr<gfx::win::TextAnalysisSource> text;
+ mswr::MakeAndInitialize<gfx::win::TextAnalysisSource>(
&text, L"hello", L"en-us", number_substitution_.Get(),
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
- mswr::ComPtr<TextAnalysisSource> surrogate_pair_text;
- mswr::MakeAndInitialize<TextAnalysisSource>(
+ mswr::ComPtr<gfx::win::TextAnalysisSource> surrogate_pair_text;
+ mswr::MakeAndInitialize<gfx::win::TextAnalysisSource>(
&surrogate_pair_text, L"\U0001d300", L"en-us", number_substitution_.Get(),
DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
fallback->MapCharacters(text.Get(), 0, 5, nullptr, nullptr,
diff --git a/chromium/content/child/fileapi/OWNERS b/chromium/content/child/fileapi/OWNERS
index 4d4319a2c31..7c932798d9b 100644
--- a/chromium/content/child/fileapi/OWNERS
+++ b/chromium/content/child/fileapi/OWNERS
@@ -2,16 +2,3 @@ michaeln@chromium.org
jianli@chromium.org
tzik@chromium.org
nhiroki@chromium.org
-
-# For security review of IPC message files.
-per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/child/fileapi/webfilesystem_impl.cc b/chromium/content/child/fileapi/webfilesystem_impl.cc
index 640e57fa874..3187e16ac83 100644
--- a/chromium/content/child/fileapi/webfilesystem_impl.cc
+++ b/chromium/content/child/fileapi/webfilesystem_impl.cc
@@ -5,6 +5,7 @@
#include "content/child/fileapi/webfilesystem_impl.h"
#include <stddef.h>
+#include <tuple>
#include "base/bind.h"
#include "base/lazy_instance.h"
@@ -27,7 +28,6 @@
#include "third_party/WebKit/public/platform/WebURL.h"
#include "url/gurl.h"
-using base::MakeTuple;
using blink::WebFileInfo;
using blink::WebFileSystemCallbacks;
using blink::WebFileSystemEntry;
@@ -41,8 +41,9 @@ class WebFileSystemImpl::WaitableCallbackResults
: public base::RefCountedThreadSafe<WaitableCallbackResults> {
public:
WaitableCallbackResults()
- : results_available_event_(true /* manual_reset */,
- false /* initially_signaled */) {}
+ : results_available_event_(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED) {}
void AddResultsAndSignal(const base::Closure& results_closure) {
base::AutoLock lock(lock_);
@@ -415,14 +416,14 @@ void WebFileSystemImpl::openFileSystem(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::OpenFileSystem,
- MakeTuple(GURL(storage_partition),
- static_cast<storage::FileSystemType>(type),
- base::Bind(&OpenFileSystemCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results)),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(storage_partition), static_cast<storage::FileSystemType>(type),
+ base::Bind(&OpenFileSystemCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results)),
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -434,13 +435,14 @@ void WebFileSystemImpl::resolveURL(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::ResolveURL,
- MakeTuple(GURL(filesystem_url),
- base::Bind(&ResolveURLCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results)),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(filesystem_url),
+ base::Bind(&ResolveURLCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results)),
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -453,11 +455,11 @@ void WebFileSystemImpl::deleteFileSystem(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::DeleteFileSystem,
- MakeTuple(GURL(storage_partition),
- static_cast<storage::FileSystemType>(type),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(storage_partition), static_cast<storage::FileSystemType>(type),
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -470,10 +472,11 @@ void WebFileSystemImpl::move(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::Move,
- MakeTuple(GURL(src_path), GURL(dest_path),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(src_path), GURL(dest_path),
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -486,10 +489,11 @@ void WebFileSystemImpl::copy(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::Copy,
- MakeTuple(GURL(src_path), GURL(dest_path),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(src_path), GURL(dest_path),
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -501,10 +505,11 @@ void WebFileSystemImpl::remove(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::Remove,
- MakeTuple(GURL(path), false /* recursive */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path), false /* recursive */,
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -516,10 +521,11 @@ void WebFileSystemImpl::removeRecursively(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::Remove,
- MakeTuple(GURL(path), true /* recursive */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path), true /* recursive */,
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -531,13 +537,14 @@ void WebFileSystemImpl::readMetadata(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::ReadMetadata,
- MakeTuple(GURL(path),
- base::Bind(&ReadMetadataCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results)),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path),
+ base::Bind(&ReadMetadataCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results)),
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -550,10 +557,11 @@ void WebFileSystemImpl::createFile(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::CreateFile,
- MakeTuple(GURL(path), exclusive,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path), exclusive,
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -566,10 +574,11 @@ void WebFileSystemImpl::createDirectory(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::CreateDirectory,
- MakeTuple(GURL(path), exclusive, false /* recursive */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path), exclusive, false /* recursive */,
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -581,10 +590,11 @@ void WebFileSystemImpl::fileExists(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::Exists,
- MakeTuple(GURL(path), false /* directory */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path), false /* directory */,
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -596,10 +606,11 @@ void WebFileSystemImpl::directoryExists(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::Exists,
- MakeTuple(GURL(path), true /* directory */,
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path), true /* directory */,
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -611,13 +622,14 @@ int WebFileSystemImpl::readDirectory(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::ReadDirectory,
- MakeTuple(GURL(path),
- base::Bind(&ReadDirectoryCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results)),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path),
+ base::Bind(&ReadDirectoryCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results)),
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
return callbacks_id;
}
@@ -631,14 +643,15 @@ void WebFileSystemImpl::createFileWriter(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::ReadMetadata,
- MakeTuple(GURL(path),
- base::Bind(&CreateFileWriterCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results),
- main_thread_task_runner_, GURL(path), client),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path),
+ base::Bind(&CreateFileWriterCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results),
+ main_thread_task_runner_, GURL(path), client),
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -650,14 +663,15 @@ void WebFileSystemImpl::createSnapshotFileAndReadMetadata(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::CreateSnapshotFile,
- MakeTuple(GURL(path),
- base::Bind(&CreateSnapshotFileCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results),
- main_thread_task_runner_),
- base::Bind(&StatusCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- base::RetainedRef(waitable_results))),
+ std::make_tuple(
+ GURL(path),
+ base::Bind(&CreateSnapshotFileCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results),
+ main_thread_task_runner_),
+ base::Bind(&StatusCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
diff --git a/chromium/content/child/fileapi/webfilewriter_impl.cc b/chromium/content/child/fileapi/webfilewriter_impl.cc
index 8ec97332d18..a2f8d92f89d 100644
--- a/chromium/content/child/fileapi/webfilewriter_impl.cc
+++ b/chromium/content/child/fileapi/webfilewriter_impl.cc
@@ -36,8 +36,11 @@ class WebFileWriterImpl::WriterBridge
task_runner_(running_on_worker_ ? base::ThreadTaskRunnerHandle::Get()
: nullptr),
written_bytes_(0) {
- if (type == WebFileWriterImpl::TYPE_SYNC)
- waitable_event_.reset(new base::WaitableEvent(false, false));
+ if (type == WebFileWriterImpl::TYPE_SYNC) {
+ waitable_event_.reset(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED));
+ }
}
void Truncate(const GURL& path,
diff --git a/chromium/content/child/font_warmup_win.cc b/chromium/content/child/font_warmup_win.cc
index e3c07115ff0..2d3f2323d6c 100644
--- a/chromium/content/child/font_warmup_win.cc
+++ b/chromium/content/child/font_warmup_win.cc
@@ -24,7 +24,7 @@
#include "base/win/windows_version.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "skia/ext/fontmgr_default_win.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/ports/SkFontMgr.h"
#include "third_party/skia/include/ports/SkTypeface_win.h"
@@ -103,11 +103,11 @@ class FakeGdiObject : public base::RefCountedThreadSafe<FakeGdiObject> {
FakeGdiObject(uint32_t magic, void* handle)
: handle_(handle), magic_(magic) {}
- void set_typeface(const skia::RefPtr<SkTypeface>& typeface) {
- typeface_ = typeface;
+ void set_typeface(sk_sp<SkTypeface> typeface) {
+ typeface_ = std::move(typeface);
}
- skia::RefPtr<SkTypeface> typeface() { return typeface_; }
+ sk_sp<SkTypeface> typeface() { return typeface_; }
void* handle() { return handle_; }
uint32_t magic() { return magic_; }
@@ -117,7 +117,7 @@ class FakeGdiObject : public base::RefCountedThreadSafe<FakeGdiObject> {
void* handle_;
uint32_t magic_;
- skia::RefPtr<SkTypeface> typeface_;
+ sk_sp<SkTypeface> typeface_;
DISALLOW_COPY_AND_ASSIGN(FakeGdiObject);
};
@@ -193,7 +193,7 @@ base::LazyInstance<FakeGdiObjectFactory>::Leaky g_fake_gdi_object_factory =
const uint32_t kFakeDCMagic = 'fkdc';
const uint32_t kFakeFontMagic = 'fkft';
-skia::RefPtr<SkTypeface> GetTypefaceFromLOGFONT(const LOGFONTW* log_font) {
+sk_sp<SkTypeface> GetTypefaceFromLOGFONT(const LOGFONTW* log_font) {
CHECK(g_warmup_fontmgr);
int weight = log_font->lfWeight;
if (weight == FW_DONTCARE)
@@ -205,7 +205,7 @@ skia::RefPtr<SkTypeface> GetTypefaceFromLOGFONT(const LOGFONTW* log_font) {
std::string family_name = base::WideToUTF8(log_font->lfFaceName);
ppapi::ProxyAutoLock lock; // Needed for DirectWrite font proxy.
- return skia::AdoptRef(
+ return sk_sp<SkTypeface>(
g_warmup_fontmgr->matchFamilyStyle(family_name.c_str(), style));
}
@@ -219,13 +219,13 @@ HFONT WINAPI CreateFontIndirectWPatch(const LOGFONTW* log_font) {
if (!log_font)
return nullptr;
- skia::RefPtr<SkTypeface> typeface = GetTypefaceFromLOGFONT(log_font);
+ sk_sp<SkTypeface> typeface = GetTypefaceFromLOGFONT(log_font);
if (!typeface)
return nullptr;
scoped_refptr<FakeGdiObject> ret =
g_fake_gdi_object_factory.Get().Create(kFakeFontMagic);
- ret->set_typeface(typeface);
+ ret->set_typeface(std::move(typeface));
return static_cast<HFONT>(ret->handle());
}
@@ -252,7 +252,7 @@ int WINAPI EnumFontFamiliesExWPatch(HDC dc_handle,
if (!log_font || !enum_callback)
return 1;
- skia::RefPtr<SkTypeface> typeface = GetTypefaceFromLOGFONT(log_font);
+ sk_sp<SkTypeface> typeface = GetTypefaceFromLOGFONT(log_font);
if (!typeface)
return 1;
@@ -278,7 +278,7 @@ DWORD WINAPI GetFontDataPatch(HDC dc_handle,
if (!dc_obj)
return GDI_ERROR;
- skia::RefPtr<SkTypeface> typeface = dc_obj->typeface();
+ sk_sp<SkTypeface> typeface = dc_obj->typeface();
if (!typeface)
return GDI_ERROR;
@@ -312,10 +312,10 @@ HGDIOBJ WINAPI SelectObjectPatch(HDC dc_handle, HGDIOBJ object_handle) {
// Construct a new fake font object to handle the old font if there's one.
scoped_refptr<FakeGdiObject> new_font_obj;
- skia::RefPtr<SkTypeface> old_typeface = dc_obj->typeface();
+ sk_sp<SkTypeface> old_typeface = dc_obj->typeface();
if (old_typeface) {
new_font_obj = g_fake_gdi_object_factory.Get().Create(kFakeFontMagic);
- new_font_obj->set_typeface(old_typeface);
+ new_font_obj->set_typeface(std::move(old_typeface));
}
dc_obj->set_typeface(font_obj->typeface());
diff --git a/chromium/content/child/font_warmup_win_unittest.cc b/chromium/content/child/font_warmup_win_unittest.cc
index ef89549892d..d78748365f2 100644
--- a/chromium/content/child/font_warmup_win_unittest.cc
+++ b/chromium/content/child/font_warmup_win_unittest.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <windows.h>
#include <memory>
#include <vector>
@@ -14,7 +15,6 @@
#include "base/logging.h"
#include "base/sys_byteorder.h"
#include "base/win/windows_version.h"
-#include "skia/ext/refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkString.h"
#include "third_party/skia/include/core/SkTypeface.h"
diff --git a/chromium/content/child/indexed_db/OWNERS b/chromium/content/child/indexed_db/OWNERS
index 1f0a278156e..6d435ba10c4 100644
--- a/chromium/content/child/indexed_db/OWNERS
+++ b/chromium/content/child/indexed_db/OWNERS
@@ -2,16 +2,3 @@ dgrogan@chromium.org
michaeln@chromium.org
jsbell@chromium.org
cmumford@chromium.org
-
-# For security review of IPC message files.
-per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/child/mojo/mojo_application.cc b/chromium/content/child/mojo/mojo_application.cc
deleted file mode 100644
index 7aa45979ac8..00000000000
--- a/chromium/content/child/mojo/mojo_application.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/mojo/mojo_application.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "content/common/application_setup.mojom.h"
-#include "mojo/edk/embedder/embedder.h"
-
-namespace content {
-
-MojoApplication::MojoApplication() {
-}
-
-MojoApplication::~MojoApplication() {
-}
-
-void MojoApplication::InitWithToken(const std::string& token) {
- mojo::ScopedMessagePipeHandle handle =
- mojo::edk::CreateChildMessagePipe(token);
- DCHECK(handle.is_valid());
-
- mojom::ApplicationSetupPtr application_setup;
- application_setup.Bind(
- mojo::InterfacePtrInfo<mojom::ApplicationSetup>(std::move(handle), 0u));
-
- shell::mojom::InterfaceProviderPtr services;
- shell::mojom::InterfaceProviderPtr exposed_services;
- service_registry_.Bind(GetProxy(&exposed_services));
- application_setup->ExchangeInterfaceProviders(GetProxy(&services),
- std::move(exposed_services));
- service_registry_.BindRemoteServiceProvider(std::move(services));
-}
-
-} // namespace content
diff --git a/chromium/content/child/mojo/mojo_application.h b/chromium/content/child/mojo/mojo_application.h
deleted file mode 100644
index 68602c4fd36..00000000000
--- a/chromium/content/child/mojo/mojo_application.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_MOJO_MOJO_APPLICATION_H_
-#define CONTENT_CHILD_MOJO_MOJO_APPLICATION_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "content/common/mojo/service_registry_impl.h"
-
-namespace content {
-
-// MojoApplication represents the code needed to setup a child process as a
-// Mojo application. Instantiate MojoApplication and call InitWithToken() with
-// a token passed from the process host. It makes the ServiceRegistry interface
-// available.
-class MojoApplication {
- public:
- MojoApplication();
- virtual ~MojoApplication();
-
- // Initializes this MojoApplicaiton with a message pipe obtained using
- // |token|.
- void InitWithToken(const std::string& token);
-
- ServiceRegistry* service_registry() { return &service_registry_; }
-
- private:
- ServiceRegistryImpl service_registry_;
-
- DISALLOW_COPY_AND_ASSIGN(MojoApplication);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_MOJO_MOJO_APPLICATION_H_
diff --git a/chromium/content/child/notifications/notification_manager.cc b/chromium/content/child/notifications/notification_manager.cc
index e95e7a81e12..ed5642482ca 100644
--- a/chromium/content/child/notifications/notification_manager.cc
+++ b/chromium/content/child/notifications/notification_manager.cc
@@ -209,20 +209,6 @@ void NotificationManager::notifyDelegateDestroyed(
}
}
-blink::mojom::blink::PermissionStatus NotificationManager::checkPermission(
- const blink::WebSecurityOrigin& origin) {
- blink::mojom::PermissionStatus permission_status =
- blink::mojom::PermissionStatus::DENIED;
-
- // TODO(mkwst): This is potentially doing the wrong thing with unique
- // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
- // https://crbug.com/490074 for detail.
- thread_safe_sender_->Send(new PlatformNotificationHostMsg_CheckPermission(
- blink::WebStringToGURL(origin.toString()), &permission_status));
-
- return static_cast<blink::mojom::blink::PermissionStatus>(permission_status);
-}
-
bool NotificationManager::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(NotificationManager, message)
diff --git a/chromium/content/child/notifications/notification_manager.h b/chromium/content/child/notifications/notification_manager.h
index 88ad2787a72..2a71c314e60 100644
--- a/chromium/content/child/notifications/notification_manager.h
+++ b/chromium/content/child/notifications/notification_manager.h
@@ -61,8 +61,6 @@ class NotificationManager : public blink::WebNotificationManager,
int64_t persistent_notification_id) override;
void notifyDelegateDestroyed(
blink::WebNotificationDelegate* delegate) override;
- blink::mojom::blink::PermissionStatus checkPermission(
- const blink::WebSecurityOrigin& origin) override;
// Called by the NotificationDispatcher.
bool OnMessageReceived(const IPC::Message& message);
diff --git a/chromium/content/child/permissions/permission_dispatcher.cc b/chromium/content/child/permissions/permission_dispatcher.cc
index 3464648e4c1..c643649e3e2 100644
--- a/chromium/content/child/permissions/permission_dispatcher.cc
+++ b/chromium/content/child/permissions/permission_dispatcher.cc
@@ -7,11 +7,13 @@
#include <stddef.h>
#include <utility>
+#include "base/bind.h"
#include "base/callback.h"
#include "content/public/child/worker_thread.h"
-#include "content/public/common/service_registry.h"
+#include "services/shell/public/cpp/interface_provider.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/modules/permissions/WebPermissionObserver.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
using blink::WebPermissionObserver;
using blink::mojom::PermissionName;
@@ -87,8 +89,9 @@ bool PermissionDispatcher::IsObservable(blink::WebPermissionType type) {
type == blink::WebPermissionTypeBackgroundSync;
}
-PermissionDispatcher::PermissionDispatcher(ServiceRegistry* service_registry)
- : service_registry_(service_registry) {
+PermissionDispatcher::PermissionDispatcher(
+ shell::InterfaceProvider* remote_interfaces)
+ : remote_interfaces_(remote_interfaces) {
}
PermissionDispatcher::~PermissionDispatcher() {
@@ -229,8 +232,7 @@ void PermissionDispatcher::RunPermissionsCallbackOnWorkerThread(
blink::mojom::PermissionService*
PermissionDispatcher::GetPermissionServicePtr() {
if (!permission_service_.get()) {
- service_registry_->ConnectToRemoteService(
- mojo::GetProxy(&permission_service_));
+ remote_interfaces_->GetInterface(mojo::GetProxy(&permission_service_));
}
return permission_service_.get();
}
@@ -273,6 +275,7 @@ void PermissionDispatcher::RequestPermissionInternal(
GetPermissionServicePtr()->RequestPermission(
GetPermissionName(type),
origin,
+ blink::WebUserGestureIndicator::isProcessingUserGesture(),
base::Bind(&PermissionDispatcher::OnPermissionResponse,
base::Unretained(this),
worker_thread_id,
@@ -298,6 +301,7 @@ void PermissionDispatcher::RequestPermissionsInternal(
GetPermissionServicePtr()->RequestPermissions(
std::move(names), origin,
+ blink::WebUserGestureIndicator::isProcessingUserGesture(),
base::Bind(&PermissionDispatcher::OnRequestPermissionsResponse,
base::Unretained(this), worker_thread_id, callback_key));
}
@@ -347,7 +351,7 @@ void PermissionDispatcher::OnPermissionResponse(int worker_thread_id,
void PermissionDispatcher::OnRequestPermissionsResponse(
int worker_thread_id,
uintptr_t callback_key,
- const mojo::Array<PermissionStatus>& result) {
+ mojo::Array<PermissionStatus> result) {
std::unique_ptr<blink::WebPermissionsCallback> callback =
permissions_callbacks_.take_and_erase(callback_key);
std::unique_ptr<blink::WebVector<blink::WebPermissionStatus>> statuses(
diff --git a/chromium/content/child/permissions/permission_dispatcher.h b/chromium/content/child/permissions/permission_dispatcher.h
index e6409740631..b281468d264 100644
--- a/chromium/content/child/permissions/permission_dispatcher.h
+++ b/chromium/content/child/permissions/permission_dispatcher.h
@@ -15,9 +15,11 @@
#include "third_party/WebKit/public/platform/modules/permissions/WebPermissionClient.h"
#include "third_party/WebKit/public/platform/modules/permissions/permission.mojom.h"
-namespace content {
+namespace shell {
+class InterfaceProvider;
+}
-class ServiceRegistry;
+namespace content {
// The PermissionDispatcher is a layer between Blink and the Mojo
// PermissionService. It implements blink::WebPermissionClient. It is being used
@@ -31,9 +33,9 @@ class PermissionDispatcher : public blink::WebPermissionClient,
// static values that never changes.
static bool IsObservable(blink::WebPermissionType type);
- // The caller must guarantee that |service_registry| will have a lifetime
+ // The caller must guarantee that |interface_registry| will have a lifetime
// larger than this instance of PermissionDispatcher.
- explicit PermissionDispatcher(ServiceRegistry* service_registry);
+ explicit PermissionDispatcher(shell::InterfaceProvider* remote_interfaces);
~PermissionDispatcher() override;
// blink::WebPermissionClient implementation.
@@ -130,7 +132,7 @@ class PermissionDispatcher : public blink::WebPermissionClient,
void OnRequestPermissionsResponse(
int worker_thread_id,
uintptr_t callback_key,
- const mojo::Array<blink::mojom::PermissionStatus>& status);
+ mojo::Array<blink::mojom::PermissionStatus> status);
void OnPermissionChanged(blink::WebPermissionType type,
const std::string& origin,
blink::WebPermissionObserver* observer,
@@ -151,7 +153,7 @@ class PermissionDispatcher : public blink::WebPermissionClient,
// Pending callbacks for request() multiple permissions.
PermissionsCallbackMap permissions_callbacks_;
- ServiceRegistry* service_registry_;
+ shell::InterfaceProvider* remote_interfaces_;
blink::mojom::PermissionServicePtr permission_service_;
DISALLOW_COPY_AND_ASSIGN(PermissionDispatcher);
diff --git a/chromium/content/child/request_extra_data.cc b/chromium/content/child/request_extra_data.cc
index b26120bcabc..e71362b7576 100644
--- a/chromium/content/child/request_extra_data.cc
+++ b/chromium/content/child/request_extra_data.cc
@@ -24,8 +24,7 @@ RequestExtraData::RequestExtraData()
transferred_request_request_id_(-1),
service_worker_provider_id_(kInvalidServiceWorkerProviderId),
originated_from_service_worker_(false),
- lofi_state_(LOFI_UNSPECIFIED) {
-}
+ initiated_in_secure_context_(false) {}
RequestExtraData::~RequestExtraData() {
}
diff --git a/chromium/content/child/request_extra_data.h b/chromium/content/child/request_extra_data.h
index eb80fac5047..77c164655d9 100644
--- a/chromium/content/child/request_extra_data.h
+++ b/chromium/content/child/request_extra_data.h
@@ -98,12 +98,6 @@ class CONTENT_EXPORT RequestExtraData
void set_originated_from_service_worker(bool originated_from_service_worker) {
originated_from_service_worker_ = originated_from_service_worker;
}
- LoFiState lofi_state() const {
- return lofi_state_;
- }
- void set_lofi_state(LoFiState lofi_state) {
- lofi_state_ = lofi_state;
- }
// |custom_user_agent| is used to communicate an overriding custom user agent
// to |RenderViewImpl::willSendRequest()|; set to a null string to indicate no
// override and an empty string to indicate that there should be no user
@@ -132,6 +126,13 @@ class CONTENT_EXPORT RequestExtraData
stream_override_ = std::move(stream_override);
}
+ bool initiated_in_secure_context() const {
+ return initiated_in_secure_context_;
+ }
+ void set_initiated_in_secure_context(bool secure) {
+ initiated_in_secure_context_ = secure;
+ }
+
private:
blink::WebPageVisibilityState visibility_state_;
int render_frame_id_;
@@ -149,7 +150,7 @@ class CONTENT_EXPORT RequestExtraData
blink::WebString custom_user_agent_;
blink::WebString requested_with_;
std::unique_ptr<StreamOverrideParameters> stream_override_;
- LoFiState lofi_state_;
+ bool initiated_in_secure_context_;
DISALLOW_COPY_AND_ASSIGN(RequestExtraData);
};
diff --git a/chromium/content/child/request_info.cc b/chromium/content/child/request_info.cc
index 2af34cd5dc6..2d69b51d575 100644
--- a/chromium/content/child/request_info.cc
+++ b/chromium/content/child/request_info.cc
@@ -18,7 +18,7 @@ RequestInfo::RequestInfo()
routing_id(0),
download_to_file(false),
has_user_gesture(false),
- skip_service_worker(false),
+ skip_service_worker(SkipServiceWorker::NONE),
should_reset_appcache(false),
fetch_request_mode(FETCH_REQUEST_MODE_NO_CORS),
fetch_credentials_mode(FETCH_CREDENTIALS_MODE_OMIT),
@@ -28,7 +28,8 @@ RequestInfo::RequestInfo()
do_not_prompt_for_login(false),
report_raw_headers(false),
extra_data(NULL),
- loading_web_task_runner(nullptr) {}
+ loading_web_task_runner(nullptr),
+ lofi_state(LOFI_UNSPECIFIED) {}
RequestInfo::~RequestInfo() {}
diff --git a/chromium/content/child/request_info.h b/chromium/content/child/request_info.h
index a5e026f9709..f7d7339fed0 100644
--- a/chromium/content/child/request_info.h
+++ b/chromium/content/child/request_info.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "content/common/content_export.h"
+#include "content/common/navigation_params.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/referrer.h"
#include "content/public/common/request_context_frame_type.h"
@@ -88,8 +89,8 @@ struct CONTENT_EXPORT RequestInfo {
// True if the request was user initiated.
bool has_user_gesture;
- // True if the request should not be handled by the ServiceWorker.
- bool skip_service_worker;
+ // Indicates which types of ServiceWorkers should skip handling this request.
+ SkipServiceWorker skip_service_worker;
// True if corresponding AppCache group should be resetted.
bool should_reset_appcache;
@@ -128,6 +129,10 @@ struct CONTENT_EXPORT RequestInfo {
// the ResourceBody that has already been fetched by the browser process.
GURL resource_body_stream_url;
+ // Whether or not to request a LoFi version of the document or let the browser
+ // decide.
+ LoFiState lofi_state;
+
private:
DISALLOW_COPY_AND_ASSIGN(RequestInfo);
};
diff --git a/chromium/content/child/resource_dispatcher.cc b/chromium/content/child/resource_dispatcher.cc
index 05603a5140f..e5d0160faf0 100644
--- a/chromium/content/child/resource_dispatcher.cc
+++ b/chromium/content/child/resource_dispatcher.cc
@@ -543,7 +543,7 @@ void ResourceDispatcher::FlushDeferredMessages(int request_id) {
}
void ResourceDispatcher::StartSync(const RequestInfo& request_info,
- ResourceRequestBody* request_body,
+ ResourceRequestBodyImpl* request_body,
SyncLoadResponse* response) {
std::unique_ptr<ResourceRequest> request =
CreateRequest(request_info, request_body, NULL);
@@ -574,7 +574,7 @@ void ResourceDispatcher::StartSync(const RequestInfo& request_info,
}
int ResourceDispatcher::StartAsync(const RequestInfo& request_info,
- ResourceRequestBody* request_body,
+ ResourceRequestBodyImpl* request_body,
std::unique_ptr<RequestPeer> peer) {
GURL frame_origin;
std::unique_ptr<ResourceRequest> request =
@@ -735,7 +735,7 @@ void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) {
std::unique_ptr<ResourceRequest> ResourceDispatcher::CreateRequest(
const RequestInfo& request_info,
- ResourceRequestBody* request_body,
+ ResourceRequestBodyImpl* request_body,
GURL* frame_origin) {
std::unique_ptr<ResourceRequest> request(new ResourceRequest);
request->method = request_info.method;
@@ -764,6 +764,7 @@ std::unique_ptr<ResourceRequest> ResourceDispatcher::CreateRequest(
request->enable_upload_progress = request_info.enable_upload_progress;
request->do_not_prompt_for_login = request_info.do_not_prompt_for_login;
request->report_raw_headers = request_info.report_raw_headers;
+ request->lofi_state = request_info.lofi_state;
if ((request_info.referrer.policy == blink::WebReferrerPolicyDefault ||
request_info.referrer.policy ==
@@ -799,9 +800,10 @@ std::unique_ptr<ResourceRequest> ResourceDispatcher::CreateRequest(
extra_data->service_worker_provider_id();
request->originated_from_service_worker =
extra_data->originated_from_service_worker();
- request->lofi_state = extra_data->lofi_state();
request->request_body = request_body;
request->resource_body_stream_url = request_info.resource_body_stream_url;
+ request->initiated_in_secure_context =
+ extra_data->initiated_in_secure_context();
if (frame_origin)
*frame_origin = extra_data->frame_origin();
return request;
diff --git a/chromium/content/child/resource_dispatcher.h b/chromium/content/child/resource_dispatcher.h
index 17c80e41603..11062c6fe4b 100644
--- a/chromium/content/child/resource_dispatcher.h
+++ b/chromium/content/child/resource_dispatcher.h
@@ -35,7 +35,7 @@ struct RedirectInfo;
namespace content {
class RequestPeer;
class ResourceDispatcherDelegate;
-class ResourceRequestBody;
+class ResourceRequestBodyImpl;
class ResourceSchedulingFilter;
struct ResourceResponseInfo;
struct RequestInfo;
@@ -67,14 +67,14 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
// interrupt this method. Errors are reported via the status field of the
// response parameter.
void StartSync(const RequestInfo& request_info,
- ResourceRequestBody* request_body,
+ ResourceRequestBodyImpl* request_body,
SyncLoadResponse* response);
// Call this method to initiate the request. If this method succeeds, then
// the peer's methods will be called asynchronously to report various events.
// Returns the request id.
virtual int StartAsync(const RequestInfo& request_info,
- ResourceRequestBody* request_body,
+ ResourceRequestBodyImpl* request_body,
std::unique_ptr<RequestPeer> peer);
// Removes a request from the |pending_requests_| list, returning true if the
@@ -224,7 +224,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
std::unique_ptr<ResourceRequest> CreateRequest(
const RequestInfo& request_info,
- ResourceRequestBody* request_body,
+ ResourceRequestBodyImpl* request_body,
GURL* frame_origin);
IPC::Sender* message_sender_;
diff --git a/chromium/content/child/resource_dispatcher_unittest.cc b/chromium/content/child/resource_dispatcher_unittest.cc
index b250ca45455..07fbecfbb4d 100644
--- a/chromium/content/child/resource_dispatcher_unittest.cc
+++ b/chromium/content/child/resource_dispatcher_unittest.cc
@@ -9,6 +9,7 @@
#include <memory>
#include <string>
+#include <tuple>
#include <utility>
#include <vector>
@@ -174,60 +175,60 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
ADD_FAILURE() << "Expected ResourceHostMsg_RequestResource message";
return -1;
}
- ResourceRequest request = base::get<2>(params);
+ ResourceRequest request = std::get<2>(params);
EXPECT_EQ(kTestPageUrl, request.url.spec());
message_queue_.erase(message_queue_.begin());
- return base::get<1>(params);
+ return std::get<1>(params);
}
void ConsumeFollowRedirect(int expected_request_id) {
ASSERT_FALSE(message_queue_.empty());
- base::Tuple<int> args;
+ std::tuple<int> args;
ASSERT_EQ(ResourceHostMsg_FollowRedirect::ID, message_queue_[0].type());
ASSERT_TRUE(ResourceHostMsg_FollowRedirect::Read(
&message_queue_[0], &args));
- EXPECT_EQ(expected_request_id, base::get<0>(args));
+ EXPECT_EQ(expected_request_id, std::get<0>(args));
message_queue_.erase(message_queue_.begin());
}
void ConsumeDataReceived_ACK(int expected_request_id) {
ASSERT_FALSE(message_queue_.empty());
- base::Tuple<int> args;
+ std::tuple<int> args;
ASSERT_EQ(ResourceHostMsg_DataReceived_ACK::ID, message_queue_[0].type());
ASSERT_TRUE(ResourceHostMsg_DataReceived_ACK::Read(
&message_queue_[0], &args));
- EXPECT_EQ(expected_request_id, base::get<0>(args));
+ EXPECT_EQ(expected_request_id, std::get<0>(args));
message_queue_.erase(message_queue_.begin());
}
void ConsumeDataDownloaded_ACK(int expected_request_id) {
ASSERT_FALSE(message_queue_.empty());
- base::Tuple<int> args;
+ std::tuple<int> args;
ASSERT_EQ(ResourceHostMsg_DataDownloaded_ACK::ID, message_queue_[0].type());
ASSERT_TRUE(ResourceHostMsg_DataDownloaded_ACK::Read(
&message_queue_[0], &args));
- EXPECT_EQ(expected_request_id, base::get<0>(args));
+ EXPECT_EQ(expected_request_id, std::get<0>(args));
message_queue_.erase(message_queue_.begin());
}
void ConsumeReleaseDownloadedFile(int expected_request_id) {
ASSERT_FALSE(message_queue_.empty());
- base::Tuple<int> args;
+ std::tuple<int> args;
ASSERT_EQ(ResourceHostMsg_ReleaseDownloadedFile::ID,
message_queue_[0].type());
ASSERT_TRUE(ResourceHostMsg_ReleaseDownloadedFile::Read(
&message_queue_[0], &args));
- EXPECT_EQ(expected_request_id, base::get<0>(args));
+ EXPECT_EQ(expected_request_id, std::get<0>(args));
message_queue_.erase(message_queue_.begin());
}
void ConsumeCancelRequest(int expected_request_id) {
ASSERT_FALSE(message_queue_.empty());
- base::Tuple<int> args;
+ std::tuple<int> args;
ASSERT_EQ(ResourceHostMsg_CancelRequest::ID, message_queue_[0].type());
ASSERT_TRUE(ResourceHostMsg_CancelRequest::Read(
&message_queue_[0], &args));
- EXPECT_EQ(expected_request_id, base::get<0>(args));
+ EXPECT_EQ(expected_request_id, std::get<0>(args));
message_queue_.erase(message_queue_.begin());
}
@@ -316,7 +317,7 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
ResourceDispatcher* dispatcher() { return dispatcher_.get(); }
int StartAsync(const RequestInfo& request_info,
- ResourceRequestBody* request_body,
+ ResourceRequestBodyImpl* request_body,
TestRequestPeer::Context* peer_context) {
std::unique_ptr<TestRequestPeer> peer(
new TestRequestPeer(dispatcher(), peer_context));
diff --git a/chromium/content/child/runtime_features.cc b/chromium/content/child/runtime_features.cc
index 85d8abf2b04..60172bd4d31 100644
--- a/chromium/content/child/runtime_features.cc
+++ b/chromium/content/child/runtime_features.cc
@@ -114,6 +114,11 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
switches::kEnableGpuMemoryBufferCompositorResources) &&
!command_line.HasSwitch(switches::kDisable2dCanvasImageChromium) &&
!command_line.HasSwitch(switches::kDisableGpu);
+
+ if (enable_canvas_2d_image_chromium) {
+ enable_canvas_2d_image_chromium =
+ base::FeatureList::IsEnabled(features::kCanvas2DImageChromium);
+ }
#else
bool enable_canvas_2d_image_chromium = false;
#endif
@@ -126,10 +131,10 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
!command_line.HasSwitch(switches::kDisableWebGLImageChromium) &&
!command_line.HasSwitch(switches::kDisableGpu);
- // There are two bugs in WebGL image chromium.
- // https://bugs.chromium.org/p/chromium/issues/detail?id=581777#c37
- // TODO(erikchen): When those issues are fixed, reenable this feature.
- enable_web_gl_image_chromium = false;
+ if (enable_web_gl_image_chromium) {
+ enable_web_gl_image_chromium =
+ base::FeatureList::IsEnabled(features::kWebGLImageChromium);
+ }
#else
bool enable_web_gl_image_chromium =
command_line.HasSwitch(switches::kEnableWebGLImageChromium);
@@ -168,20 +173,44 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kEnableUnsafeES3APIs))
WebRuntimeFeatures::enableUnsafeES3APIs(true);
- if (command_line.HasSwitch(switches::kEnableWebVR)) {
+ if (command_line.HasSwitch(switches::kEnableWebVR))
WebRuntimeFeatures::enableWebVR(true);
- WebRuntimeFeatures::enableFeatureFromString(
- std::string("GeometryInterfaces"), true);
- }
if (command_line.HasSwitch(switches::kDisablePresentationAPI))
WebRuntimeFeatures::enablePresentationAPI(false);
- if (base::FeatureList::IsEnabled(features::kWebFontsInterventionV2)) {
- WebRuntimeFeatures::enableWebFontsInterventionV2(true);
- if (command_line.HasSwitch(switches::kEnableWebFontsInterventionTrigger))
- WebRuntimeFeatures::enableWebFontsInterventionTrigger(true);
+ if (base::FeatureList::IsEnabled(features::kWeakMemoryCache))
+ WebRuntimeFeatures::enableWeakMemoryCache(true);
+
+ if (base::FeatureList::IsEnabled(features::kDoNotUnlockSharedBuffer))
+ WebRuntimeFeatures::enableDoNotUnlockSharedBuffer(true);
+
+ const std::string webfonts_intervention_v2_group_name =
+ base::FieldTrialList::FindFullName("WebFontsInterventionV2");
+ const std::string webfonts_intervention_v2_about_flag =
+ command_line.GetSwitchValueASCII(switches::kEnableWebFontsInterventionV2);
+ if (!webfonts_intervention_v2_about_flag.empty()) {
+ WebRuntimeFeatures::enableWebFontsInterventionV2With2G(
+ webfonts_intervention_v2_about_flag.compare(
+ switches::kEnableWebFontsInterventionV2SwitchValueEnabledWith2G) ==
+ 0);
+ WebRuntimeFeatures::enableWebFontsInterventionV2WithSlow2G(
+ webfonts_intervention_v2_about_flag.compare(
+ switches::
+ kEnableWebFontsInterventionV2SwitchValueEnabledWithSlow2G) ==
+ 0);
+ } else {
+ WebRuntimeFeatures::enableWebFontsInterventionV2With2G(base::StartsWith(
+ webfonts_intervention_v2_group_name,
+ switches::kEnableWebFontsInterventionV2SwitchValueEnabledWith2G,
+ base::CompareCase::INSENSITIVE_ASCII));
+ WebRuntimeFeatures::enableWebFontsInterventionV2WithSlow2G(base::StartsWith(
+ webfonts_intervention_v2_group_name,
+ switches::kEnableWebFontsInterventionV2SwitchValueEnabledWithSlow2G,
+ base::CompareCase::INSENSITIVE_ASCII));
}
+ if (command_line.HasSwitch(switches::kEnableWebFontsInterventionTrigger))
+ WebRuntimeFeatures::enableWebFontsInterventionTrigger(true);
if (base::FeatureList::IsEnabled(features::kScrollAnchoring))
WebRuntimeFeatures::enableScrollAnchoring(true);
@@ -200,17 +229,27 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::enableMediaDocumentDownloadButton(
base::FeatureList::IsEnabled(features::kMediaDocumentDownloadButton));
- if (base::FeatureList::IsEnabled(features::kPointerEvents)) {
- WebRuntimeFeatures::enableFeatureFromString(
- std::string("PointerEvent"), true);
- }
+ if (base::FeatureList::IsEnabled(features::kPointerEvents))
+ WebRuntimeFeatures::enableFeatureFromString("PointerEvent", true);
+
+ WebRuntimeFeatures::enableFeatureFromString(
+ "FontCacheScaling",
+ base::FeatureList::IsEnabled(features::kFontCacheScaling));
if (!base::FeatureList::IsEnabled(features::kPaintOptimizations))
WebRuntimeFeatures::enableFeatureFromString("PaintOptimizations", false);
+ if (base::FeatureList::IsEnabled(features::kParseHTMLOnMainThread))
+ WebRuntimeFeatures::enableFeatureFromString("ParseHTMLOnMainThread", true);
+
WebRuntimeFeatures::enableRenderingPipelineThrottling(
base::FeatureList::IsEnabled(features::kRenderingPipelineThrottling));
+#if defined(OS_ANDROID)
+ WebRuntimeFeatures::enablePaymentRequest(
+ base::FeatureList::IsEnabled(features::kWebPayments));
+#endif
+
// Enable explicitly enabled features, and then disable explicitly disabled
// ones.
if (command_line.HasSwitch(switches::kEnableBlinkFeatures)) {
diff --git a/chromium/content/child/scoped_web_callbacks.h b/chromium/content/child/scoped_web_callbacks.h
index fac339163d6..43a5ef3db59 100644
--- a/chromium/content/child/scoped_web_callbacks.h
+++ b/chromium/content/child/scoped_web_callbacks.h
@@ -9,8 +9,8 @@
#include <utility>
#include "base/callback.h"
+#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/move.h"
#include "third_party/WebKit/public/platform/WebCallbacks.h"
// A ScopedWebCallbacks is a move-only scoper which helps manage the lifetime of
@@ -67,8 +67,6 @@
// our desired default behavior before deleting the WebCallbacks.
template <typename CallbacksType>
class ScopedWebCallbacks {
- MOVE_ONLY_TYPE_FOR_CPP_03(ScopedWebCallbacks);
-
public:
using DestructionCallback =
base::Callback<void(std::unique_ptr<CallbacksType> callbacks)>;
@@ -98,6 +96,8 @@ class ScopedWebCallbacks {
private:
std::unique_ptr<CallbacksType> callbacks_;
DestructionCallback destruction_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedWebCallbacks);
};
template <typename CallbacksType>
diff --git a/chromium/content/child/service_worker/service_worker_network_provider.cc b/chromium/content/child/service_worker/service_worker_network_provider.cc
index 5c883a0154d..2f9be43dd5c 100644
--- a/chromium/content/child/service_worker/service_worker_network_provider.cc
+++ b/chromium/content/child/service_worker/service_worker_network_provider.cc
@@ -7,7 +7,6 @@
#include "base/atomic_sequence_num.h"
#include "content/child/child_thread_impl.h"
#include "content/child/service_worker/service_worker_provider_context.h"
-#include "content/common/navigation_params.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/browser_side_navigation_policy.h"
@@ -58,34 +57,18 @@ ServiceWorkerNetworkProvider* ServiceWorkerNetworkProvider::FromDocumentState(
std::unique_ptr<ServiceWorkerNetworkProvider>
ServiceWorkerNetworkProvider::CreateForNavigation(
int route_id,
- const RequestNavigationParams& request_params,
blink::WebLocalFrame* frame,
bool content_initiated) {
- bool browser_side_navigation = IsBrowserSideNavigationEnabled();
- bool should_create_provider_for_window = false;
- int service_worker_provider_id = kInvalidServiceWorkerProviderId;
- std::unique_ptr<ServiceWorkerNetworkProvider> network_provider;
-
// Determine if a ServiceWorkerNetworkProvider should be created and properly
// initialized for the navigation. A default ServiceWorkerNetworkProvider
// will always be created since it is expected in a certain number of places,
// however it will have an invalid id.
- // PlzNavigate: |service_worker_provider_id| can be sent by the browser, if
- // it already created the SeviceWorkerProviderHost.
- if (browser_side_navigation && !content_initiated) {
- should_create_provider_for_window =
- request_params.should_create_service_worker;
- service_worker_provider_id = request_params.service_worker_provider_id;
- DCHECK(ServiceWorkerUtils::IsBrowserAssignedProviderId(
- service_worker_provider_id) ||
- service_worker_provider_id == kInvalidServiceWorkerProviderId);
- } else {
- should_create_provider_for_window =
- ((frame->effectiveSandboxFlags() & blink::WebSandboxFlags::Origin) !=
- blink::WebSandboxFlags::Origin);
- }
+ bool should_create_provider_for_window =
+ ((frame->effectiveSandboxFlags() & blink::WebSandboxFlags::Origin) !=
+ blink::WebSandboxFlags::Origin);
// Now create the ServiceWorkerNetworkProvider (with invalid id if needed).
+ std::unique_ptr<ServiceWorkerNetworkProvider> network_provider;
if (should_create_provider_for_window) {
// Ideally Document::isSecureContext would be called here, but the document
// is not created yet, and due to redirects the URL may change. So pass
@@ -94,20 +77,10 @@ ServiceWorkerNetworkProvider::CreateForNavigation(
// control the document.
const bool is_parent_frame_secure = IsFrameSecure(frame->parent());
- if (service_worker_provider_id == kInvalidServiceWorkerProviderId) {
- network_provider = std::unique_ptr<ServiceWorkerNetworkProvider>(
- new ServiceWorkerNetworkProvider(route_id,
- SERVICE_WORKER_PROVIDER_FOR_WINDOW,
- is_parent_frame_secure));
- } else {
- CHECK(browser_side_navigation);
- DCHECK(ServiceWorkerUtils::IsBrowserAssignedProviderId(
- service_worker_provider_id));
- network_provider = std::unique_ptr<ServiceWorkerNetworkProvider>(
- new ServiceWorkerNetworkProvider(
- route_id, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
- service_worker_provider_id, is_parent_frame_secure));
- }
+ network_provider = std::unique_ptr<ServiceWorkerNetworkProvider>(
+ new ServiceWorkerNetworkProvider(route_id,
+ SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ is_parent_frame_secure));
} else {
network_provider = std::unique_ptr<ServiceWorkerNetworkProvider>(
new ServiceWorkerNetworkProvider());
@@ -118,11 +91,9 @@ ServiceWorkerNetworkProvider::CreateForNavigation(
ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
int route_id,
ServiceWorkerProviderType provider_type,
- int browser_provider_id,
bool is_parent_frame_secure)
- : provider_id_(browser_provider_id) {
- if (provider_id_ == kInvalidServiceWorkerProviderId)
- return;
+ : provider_id_(GetNextProviderId()) {
+ DCHECK(provider_id_ != kInvalidServiceWorkerProviderId);
if (!ChildThreadImpl::current())
return; // May be null in some tests.
context_ = new ServiceWorkerProviderContext(
@@ -132,15 +103,6 @@ ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
provider_id_, route_id, provider_type, is_parent_frame_secure));
}
-ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
- int route_id,
- ServiceWorkerProviderType provider_type,
- bool is_parent_frame_secure)
- : ServiceWorkerNetworkProvider(route_id,
- provider_type,
- GetNextProviderId(),
- is_parent_frame_secure) {}
-
ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider()
: provider_id_(kInvalidServiceWorkerProviderId) {}
@@ -154,12 +116,13 @@ ServiceWorkerNetworkProvider::~ServiceWorkerNetworkProvider() {
}
void ServiceWorkerNetworkProvider::SetServiceWorkerVersionId(
- int64_t version_id) {
+ int64_t version_id,
+ int embedded_worker_id) {
DCHECK_NE(kInvalidServiceWorkerProviderId, provider_id_);
if (!ChildThreadImpl::current())
return; // May be null in some tests.
- ChildThreadImpl::current()->Send(
- new ServiceWorkerHostMsg_SetVersionId(provider_id_, version_id));
+ ChildThreadImpl::current()->Send(new ServiceWorkerHostMsg_SetVersionId(
+ provider_id_, version_id, embedded_worker_id));
}
bool ServiceWorkerNetworkProvider::IsControlledByServiceWorker() const {
diff --git a/chromium/content/child/service_worker/service_worker_network_provider.h b/chromium/content/child/service_worker/service_worker_network_provider.h
index 1d09950af42..0afa5c685fa 100644
--- a/chromium/content/child/service_worker/service_worker_network_provider.h
+++ b/chromium/content/child/service_worker/service_worker_network_provider.h
@@ -24,7 +24,6 @@ class WebLocalFrame;
namespace content {
class ServiceWorkerProviderContext;
-struct RequestNavigationParams;
// A unique provider_id is generated for each instance.
// Instantiated prior to the main resource load being started and remains
@@ -49,16 +48,9 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider
static std::unique_ptr<ServiceWorkerNetworkProvider> CreateForNavigation(
int route_id,
- const RequestNavigationParams& request_params,
blink::WebLocalFrame* frame,
bool content_initiated);
- // PlzNavigate
- // The |browser_provider_id| is initialized by the browser for navigations.
- ServiceWorkerNetworkProvider(int route_id,
- ServiceWorkerProviderType type,
- int browser_provider_id,
- bool is_parent_frame_secure);
ServiceWorkerNetworkProvider(int route_id,
ServiceWorkerProviderType type,
bool is_parent_frame_secure);
@@ -71,7 +63,7 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider
// This method is called for a provider that's associated with a
// running service worker script. The version_id indicates which
// ServiceWorkerVersion should be used.
- void SetServiceWorkerVersionId(int64_t version_id);
+ void SetServiceWorkerVersionId(int64_t version_id, int embedded_worker_id);
bool IsControlledByServiceWorker() const;
diff --git a/chromium/content/child/shared_memory_data_consumer_handle_unittest.cc b/chromium/content/child/shared_memory_data_consumer_handle_unittest.cc
index 1fd31078ac8..a832ee29f21 100644
--- a/chromium/content/child/shared_memory_data_consumer_handle_unittest.cc
+++ b/chromium/content/child/shared_memory_data_consumer_handle_unittest.cc
@@ -20,6 +20,7 @@
#include "base/run_loop.h"
#include "base/task_runner.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/public/child/fixed_received_data.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -206,8 +207,8 @@ class SharedMemoryDataConsumerHandleTest
void RunPostedTasks() {
base::RunLoop run_loop;
- base::MessageLoop::current()->task_runner()->PostTask(FROM_HERE,
- run_loop.QuitClosure());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
run_loop.Run();
}
diff --git a/chromium/content/child/shared_memory_received_data_factory_unittest.cc b/chromium/content/child/shared_memory_received_data_factory_unittest.cc
index 05b6bed7ee8..ce0b890c818 100644
--- a/chromium/content/child/shared_memory_received_data_factory_unittest.cc
+++ b/chromium/content/child/shared_memory_received_data_factory_unittest.cc
@@ -5,8 +5,8 @@
#include "content/child/shared_memory_received_data_factory.h"
#include <stddef.h>
+#include <tuple>
-#include "base/tuple.h"
#include "content/common/resource_messages.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
@@ -31,9 +31,9 @@ class MockSender : public IPC::Sender {
bool Send(IPC::Message* message) override {
bool result = false;
if (message->type() == ResourceHostMsg_DataReceived_ACK::ID) {
- base::Tuple<int> args;
+ std::tuple<int> args;
ResourceHostMsg_DataReceived_ACK::Read(message, &args);
- result = SendAck(base::get<0>(args));
+ result = SendAck(std::get<0>(args));
} else {
result = SendOtherwise(message);
}
diff --git a/chromium/content/child/site_isolation_stats_gatherer_browsertest.cc b/chromium/content/child/site_isolation_stats_gatherer_browsertest.cc
index d37c97ad568..852ddabe045 100644
--- a/chromium/content/child/site_isolation_stats_gatherer_browsertest.cc
+++ b/chromium/content/child/site_isolation_stats_gatherer_browsertest.cc
@@ -150,8 +150,8 @@ IN_PROC_BROWSER_TEST_F(SiteIsolationStatsGathererBrowserTest,
bool was_blocked;
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- base::StringPrintf("sendRequest(\"%s\");", resource), &was_blocked));
+ shell(), base::StringPrintf("sendRequest(\"%s\");", resource),
+ &was_blocked));
ASSERT_FALSE(was_blocked);
InspectHistograms(histograms, true, resource);
@@ -174,8 +174,8 @@ IN_PROC_BROWSER_TEST_F(SiteIsolationStatsGathererBrowserTest,
bool was_blocked;
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- base::StringPrintf("sendRequest(\"%s\");", resource), &was_blocked));
+ shell(), base::StringPrintf("sendRequest(\"%s\");", resource),
+ &was_blocked));
ASSERT_FALSE(was_blocked);
InspectHistograms(histograms, false, resource);
diff --git a/chromium/content/child/v8_value_converter_impl.cc b/chromium/content/child/v8_value_converter_impl.cc
index 799d505ecd5..89378a8cb9d 100644
--- a/chromium/content/child/v8_value_converter_impl.cc
+++ b/chromium/content/child/v8_value_converter_impl.cc
@@ -10,10 +10,12 @@
#include <cmath>
#include <memory>
#include <string>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "third_party/WebKit/public/web/WebArrayBuffer.h"
#include "third_party/WebKit/public/web/WebArrayBufferConverter.h"
@@ -26,7 +28,7 @@ namespace content {
bool V8ValueConverter::Strategy::FromV8Object(
v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const {
return false;
@@ -34,24 +36,27 @@ bool V8ValueConverter::Strategy::FromV8Object(
bool V8ValueConverter::Strategy::FromV8Array(
v8::Local<v8::Array> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const {
return false;
}
-bool V8ValueConverter::Strategy::FromV8ArrayBuffer(v8::Local<v8::Object> value,
- base::Value** out,
- v8::Isolate* isolate) const {
+bool V8ValueConverter::Strategy::FromV8ArrayBuffer(
+ v8::Local<v8::Object> value,
+ std::unique_ptr<base::Value>* out,
+ v8::Isolate* isolate) const {
return false;
}
-bool V8ValueConverter::Strategy::FromV8Number(v8::Local<v8::Number> value,
- base::Value** out) const {
+bool V8ValueConverter::Strategy::FromV8Number(
+ v8::Local<v8::Number> value,
+ std::unique_ptr<base::Value>* out) const {
return false;
}
-bool V8ValueConverter::Strategy::FromV8Undefined(base::Value** out) const {
+bool V8ValueConverter::Strategy::FromV8Undefined(
+ std::unique_ptr<base::Value>* out) const {
return false;
}
@@ -212,7 +217,7 @@ v8::Local<v8::Value> V8ValueConverterImpl::ToV8Value(
ToV8ValueImpl(context->GetIsolate(), context->Global(), value));
}
-base::Value* V8ValueConverterImpl::FromV8Value(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Value(
v8::Local<v8::Value> val,
v8::Local<v8::Context> context) const {
v8::Context::Scope context_scope(context);
@@ -341,7 +346,7 @@ v8::Local<v8::Value> V8ValueConverterImpl::ToArrayBuffer(
&buffer, creation_context, isolate);
}
-base::Value* V8ValueConverterImpl::FromV8ValueImpl(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8ValueImpl(
FromV8ValueState* state,
v8::Local<v8::Value> val,
v8::Isolate* isolate) const {
@@ -349,43 +354,46 @@ base::Value* V8ValueConverterImpl::FromV8ValueImpl(
FromV8ValueState::Level state_level(state);
if (state->HasReachedMaxRecursionDepth())
- return NULL;
+ return nullptr;
if (val->IsNull())
- return base::Value::CreateNullValue().release();
+ return base::Value::CreateNullValue();
if (val->IsBoolean())
- return new base::FundamentalValue(val->ToBoolean(isolate)->Value());
+ return base::MakeUnique<base::FundamentalValue>(
+ val->ToBoolean(isolate)->Value());
if (val->IsNumber() && strategy_) {
- base::Value* out = NULL;
+ std::unique_ptr<base::Value> out;
if (strategy_->FromV8Number(val.As<v8::Number>(), &out))
return out;
}
if (val->IsInt32())
- return new base::FundamentalValue(val->ToInt32(isolate)->Value());
+ return base::MakeUnique<base::FundamentalValue>(
+ val->ToInt32(isolate)->Value());
if (val->IsNumber()) {
double val_as_double = val.As<v8::Number>()->Value();
if (!std::isfinite(val_as_double))
- return NULL;
- return new base::FundamentalValue(val_as_double);
+ return nullptr;
+ return base::MakeUnique<base::FundamentalValue>(val_as_double);
}
if (val->IsString()) {
v8::String::Utf8Value utf8(val);
- return new base::StringValue(std::string(*utf8, utf8.length()));
+ return base::MakeUnique<base::StringValue>(
+ std::string(*utf8, utf8.length()));
}
if (val->IsUndefined()) {
if (strategy_) {
- base::Value* out = NULL;
+ std::unique_ptr<base::Value> out;
if (strategy_->FromV8Undefined(&out))
return out;
}
// JSON.stringify ignores undefined.
- return NULL;
+ return nullptr;
}
if (val->IsDate()) {
@@ -394,14 +402,14 @@ base::Value* V8ValueConverterImpl::FromV8ValueImpl(
// consistent within this class.
return FromV8Object(val->ToObject(isolate), state, isolate);
v8::Date* date = v8::Date::Cast(*val);
- return new base::FundamentalValue(date->ValueOf() / 1000.0);
+ return base::MakeUnique<base::FundamentalValue>(date->ValueOf() / 1000.0);
}
if (val->IsRegExp()) {
if (!reg_exp_allowed_)
// JSON.stringify converts to an object.
return FromV8Object(val.As<v8::Object>(), state, isolate);
- return new base::StringValue(*v8::String::Utf8Value(val));
+ return base::MakeUnique<base::StringValue>(*v8::String::Utf8Value(val));
}
// v8::Value doesn't have a ToArray() method for some reason.
@@ -411,7 +419,7 @@ base::Value* V8ValueConverterImpl::FromV8ValueImpl(
if (val->IsFunction()) {
if (!function_allowed_)
// JSON.stringify refuses to convert function(){}.
- return NULL;
+ return nullptr;
return FromV8Object(val.As<v8::Object>(), state, isolate);
}
@@ -422,16 +430,16 @@ base::Value* V8ValueConverterImpl::FromV8ValueImpl(
return FromV8Object(val.As<v8::Object>(), state, isolate);
LOG(ERROR) << "Unexpected v8 value type encountered.";
- return NULL;
+ return nullptr;
}
-base::Value* V8ValueConverterImpl::FromV8Array(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Array(
v8::Local<v8::Array> val,
FromV8ValueState* state,
v8::Isolate* isolate) const {
ScopedUniquenessGuard uniqueness_guard(state, val);
if (!uniqueness_guard.is_valid())
- return base::Value::CreateNullValue().release();
+ return base::Value::CreateNullValue();
std::unique_ptr<v8::Context::Scope> scope;
// If val was created in a different context than our current one, change to
@@ -447,12 +455,12 @@ base::Value* V8ValueConverterImpl::FromV8Array(
base::Bind(&V8ValueConverterImpl::FromV8ValueImpl,
base::Unretained(this),
base::Unretained(state));
- base::Value* out = NULL;
+ std::unique_ptr<base::Value> out;
if (strategy_->FromV8Array(val, &out, isolate, callback))
return out;
}
- base::ListValue* result = new base::ListValue();
+ std::unique_ptr<base::ListValue> result(new base::ListValue());
// Only fields with integer keys are carried over to the ListValue.
for (uint32_t i = 0; i < val->Length(); ++i) {
@@ -468,22 +476,23 @@ base::Value* V8ValueConverterImpl::FromV8Array(
continue;
}
- base::Value* child = FromV8ValueImpl(state, child_v8, isolate);
+ std::unique_ptr<base::Value> child =
+ FromV8ValueImpl(state, child_v8, isolate);
if (child)
- result->Append(child);
+ result->Append(std::move(child));
else
// JSON.stringify puts null in places where values don't serialize, for
// example undefined and functions. Emulate that behavior.
result->Append(base::Value::CreateNullValue());
}
- return result;
+ return std::move(result);
}
-base::Value* V8ValueConverterImpl::FromV8ArrayBuffer(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8ArrayBuffer(
v8::Local<v8::Object> val,
v8::Isolate* isolate) const {
if (strategy_) {
- base::Value* out = NULL;
+ std::unique_ptr<base::Value> out;
if (strategy_->FromV8ArrayBuffer(val, &out, isolate))
return out;
}
@@ -508,16 +517,16 @@ base::Value* V8ValueConverterImpl::FromV8ArrayBuffer(
if (data)
return base::BinaryValue::CreateWithCopiedBuffer(data, length);
else
- return NULL;
+ return nullptr;
}
-base::Value* V8ValueConverterImpl::FromV8Object(
+std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Object(
v8::Local<v8::Object> val,
FromV8ValueState* state,
v8::Isolate* isolate) const {
ScopedUniquenessGuard uniqueness_guard(state, val);
if (!uniqueness_guard.is_valid())
- return base::Value::CreateNullValue().release();
+ return base::Value::CreateNullValue();
std::unique_ptr<v8::Context::Scope> scope;
// If val was created in a different context than our current one, change to
@@ -533,7 +542,7 @@ base::Value* V8ValueConverterImpl::FromV8Object(
base::Bind(&V8ValueConverterImpl::FromV8ValueImpl,
base::Unretained(this),
base::Unretained(state));
- base::Value* out = NULL;
+ std::unique_ptr<base::Value> out;
if (strategy_->FromV8Object(val, &out, isolate, callback))
return out;
}
@@ -552,7 +561,7 @@ base::Value* V8ValueConverterImpl::FromV8Object(
// ANOTHER NOTE: returning an empty dictionary here to minimise surprise.
// See also http://crbug.com/330559.
if (val->InternalFieldCount())
- return new base::DictionaryValue();
+ return base::MakeUnique<base::DictionaryValue>();
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
v8::Local<v8::Array> property_names(val->GetOwnPropertyNames());
@@ -579,8 +588,8 @@ base::Value* V8ValueConverterImpl::FromV8Object(
child_v8 = v8::Null(isolate);
}
- std::unique_ptr<base::Value> child(
- FromV8ValueImpl(state, child_v8, isolate));
+ std::unique_ptr<base::Value> child =
+ FromV8ValueImpl(state, child_v8, isolate);
if (!child)
// JSON.stringify skips properties whose values don't serialize, for
// example undefined and functions. Emulate that behavior.
@@ -610,10 +619,10 @@ base::Value* V8ValueConverterImpl::FromV8Object(
continue;
result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()),
- child.release());
+ std::move(child));
}
- return result.release();
+ return std::move(result);
}
} // namespace content
diff --git a/chromium/content/child/v8_value_converter_impl.h b/chromium/content/child/v8_value_converter_impl.h
index fd23c47a7e2..4b4c00afe40 100644
--- a/chromium/content/child/v8_value_converter_impl.h
+++ b/chromium/content/child/v8_value_converter_impl.h
@@ -34,8 +34,9 @@ class CONTENT_EXPORT V8ValueConverterImpl : public V8ValueConverter {
v8::Local<v8::Value> ToV8Value(
const base::Value* value,
v8::Local<v8::Context> context) const override;
- base::Value* FromV8Value(v8::Local<v8::Value> value,
- v8::Local<v8::Context> context) const override;
+ std::unique_ptr<base::Value> FromV8Value(
+ v8::Local<v8::Value> value,
+ v8::Local<v8::Context> context) const override;
private:
friend class ScopedAvoidIdentityHashForTesting;
@@ -57,21 +58,21 @@ class CONTENT_EXPORT V8ValueConverterImpl : public V8ValueConverter {
v8::Local<v8::Object> creation_context,
const base::BinaryValue* value) const;
- base::Value* FromV8ValueImpl(FromV8ValueState* state,
- v8::Local<v8::Value> value,
- v8::Isolate* isolate) const;
- base::Value* FromV8Array(v8::Local<v8::Array> array,
- FromV8ValueState* state,
- v8::Isolate* isolate) const;
+ std::unique_ptr<base::Value> FromV8ValueImpl(FromV8ValueState* state,
+ v8::Local<v8::Value> value,
+ v8::Isolate* isolate) const;
+ std::unique_ptr<base::Value> FromV8Array(v8::Local<v8::Array> array,
+ FromV8ValueState* state,
+ v8::Isolate* isolate) const;
// This will convert objects of type ArrayBuffer or any of the
// ArrayBufferView subclasses.
- base::Value* FromV8ArrayBuffer(v8::Local<v8::Object> val,
- v8::Isolate* isolate) const;
+ std::unique_ptr<base::Value> FromV8ArrayBuffer(v8::Local<v8::Object> val,
+ v8::Isolate* isolate) const;
- base::Value* FromV8Object(v8::Local<v8::Object> object,
- FromV8ValueState* state,
- v8::Isolate* isolate) const;
+ std::unique_ptr<base::Value> FromV8Object(v8::Local<v8::Object> object,
+ FromV8ValueState* state,
+ v8::Isolate* isolate) const;
// If true, we will convert Date JavaScript objects to doubles.
bool date_allowed_;
diff --git a/chromium/content/child/v8_value_converter_impl_unittest.cc b/chromium/content/child/v8_value_converter_impl_unittest.cc
index 82e23d4866b..78b377a3a6d 100644
--- a/chromium/content/child/v8_value_converter_impl_unittest.cc
+++ b/chromium/content/child/v8_value_converter_impl_unittest.cc
@@ -11,6 +11,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/test/values_test_util.h"
#include "base/values.h"
@@ -180,8 +181,7 @@ class V8ValueConverterImplTest : public testing::Test {
v8::Local<v8::Object> object(v8::Object::New(isolate_));
object->Set(v8::String::NewFromUtf8(isolate_, "test"), val);
std::unique_ptr<base::DictionaryValue> dictionary(
- static_cast<base::DictionaryValue*>(
- converter.FromV8Value(object, context)));
+ base::DictionaryValue::From(converter.FromV8Value(object, context)));
ASSERT_TRUE(dictionary.get());
if (expected_value) {
@@ -196,7 +196,7 @@ class V8ValueConverterImplTest : public testing::Test {
v8::Local<v8::Array> array(v8::Array::New(isolate_));
array->Set(0, val);
std::unique_ptr<base::ListValue> list(
- static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+ base::ListValue::From(converter.FromV8Value(array, context)));
ASSERT_TRUE(list.get());
if (expected_value) {
base::Value* temp = NULL;
@@ -329,8 +329,7 @@ TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
// Converting from v8 value should replace the foo property with null.
V8ValueConverterImpl converter;
std::unique_ptr<base::DictionaryValue> converted(
- static_cast<base::DictionaryValue*>(
- converter.FromV8Value(object, context)));
+ base::DictionaryValue::From(converter.FromV8Value(object, context)));
EXPECT_TRUE(converted.get());
// http://code.google.com/p/v8/issues/detail?id=1342
// EXPECT_EQ(2u, converted->size());
@@ -374,7 +373,7 @@ TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
// Converting from v8 value should replace the first item with null.
V8ValueConverterImpl converter;
std::unique_ptr<base::ListValue> converted(
- static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+ base::ListValue::From(converter.FromV8Value(array, context)));
ASSERT_TRUE(converted.get());
// http://code.google.com/p/v8/issues/detail?id=1342
EXPECT_EQ(2u, converted->GetSize());
@@ -442,8 +441,7 @@ TEST_F(V8ValueConverterImplTest, Prototype) {
V8ValueConverterImpl converter;
std::unique_ptr<base::DictionaryValue> result(
- static_cast<base::DictionaryValue*>(
- converter.FromV8Value(object, context)));
+ base::DictionaryValue::From(converter.FromV8Value(object, context)));
ASSERT_TRUE(result.get());
EXPECT_EQ(0u, result->size());
}
@@ -570,7 +568,7 @@ TEST_F(V8ValueConverterImplTest, ArrayPrototypeSetter) {
// Try again, using an array without the index.
base::ListValue one_item_list;
- one_item_list.Append(new base::FundamentalValue(123456));
+ one_item_list.AppendInteger(123456);
v8::Local<v8::Array> converted2 =
converter.ToV8Value(&one_item_list, context).As<v8::Array>();
EXPECT_FALSE(converted2.IsEmpty());
@@ -609,8 +607,7 @@ TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
converter.SetStripNullFromObjects(true);
std::unique_ptr<base::DictionaryValue> result(
- static_cast<base::DictionaryValue*>(
- converter.FromV8Value(object, context)));
+ base::DictionaryValue::From(converter.FromV8Value(object, context)));
ASSERT_TRUE(result.get());
EXPECT_EQ(0u, result->size());
}
@@ -630,8 +627,7 @@ TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
object->Set(v8::String::NewFromUtf8(isolate_, "obj"), object);
std::unique_ptr<base::DictionaryValue> object_result(
- static_cast<base::DictionaryValue*>(
- converter.FromV8Value(object, context)));
+ base::DictionaryValue::From(converter.FromV8Value(object, context)));
ASSERT_TRUE(object_result.get());
EXPECT_EQ(2u, object_result->size());
EXPECT_TRUE(IsNull(object_result.get(), "obj"));
@@ -642,7 +638,7 @@ TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
array->Set(1, array);
std::unique_ptr<base::ListValue> list_result(
- static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+ base::ListValue::From(converter.FromV8Value(array, context)));
ASSERT_TRUE(list_result.get());
EXPECT_EQ(2u, list_result->GetSize());
EXPECT_TRUE(IsNull(list_result.get(), 1));
@@ -709,7 +705,7 @@ TEST_F(V8ValueConverterImplTest, ArrayGetters) {
V8ValueConverterImpl converter;
std::unique_ptr<base::ListValue> result(
- static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+ base::ListValue::From(converter.FromV8Value(array, context)));
ASSERT_TRUE(result.get());
EXPECT_EQ(2u, result->GetSize());
}
@@ -873,8 +869,7 @@ TEST_F(V8ValueConverterImplTest, ReuseObjects) {
// The actual result.
std::unique_ptr<base::DictionaryValue> result(
- static_cast<base::DictionaryValue*>(
- converter.FromV8Value(object, context)));
+ base::DictionaryValue::From(converter.FromV8Value(object, context)));
ASSERT_TRUE(result.get());
EXPECT_EQ(2u, result->size());
@@ -906,7 +901,7 @@ TEST_F(V8ValueConverterImplTest, ReuseObjects) {
// The actual result.
std::unique_ptr<base::ListValue> list_result(
- static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
+ base::ListValue::From(converter.FromV8Value(array, context)));
ASSERT_TRUE(list_result.get());
ASSERT_EQ(2u, list_result->GetSize());
for (size_t i = 0; i < list_result->GetSize(); ++i) {
@@ -963,39 +958,39 @@ class V8ValueConverterOverridingStrategyForTesting
V8ValueConverterOverridingStrategyForTesting()
: reference_value_(NewReferenceValue()) {}
bool FromV8Object(v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const override {
*out = NewReferenceValue();
return true;
}
bool FromV8Array(v8::Local<v8::Array> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const override {
*out = NewReferenceValue();
return true;
}
bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate) const override {
*out = NewReferenceValue();
return true;
}
bool FromV8Number(v8::Local<v8::Number> value,
- base::Value** out) const override {
+ std::unique_ptr<base::Value>* out) const override {
*out = NewReferenceValue();
return true;
}
- bool FromV8Undefined(base::Value** out) const override {
+ bool FromV8Undefined(std::unique_ptr<base::Value>* out) const override {
*out = NewReferenceValue();
return true;
}
base::Value* reference_value() const { return reference_value_.get(); }
private:
- static base::Value* NewReferenceValue() {
- return new base::StringValue("strategy");
+ static std::unique_ptr<base::Value> NewReferenceValue() {
+ return base::MakeUnique<base::StringValue>("strategy");
}
std::unique_ptr<base::Value> reference_value_;
};
@@ -1058,27 +1053,29 @@ class V8ValueConverterBypassStrategyForTesting
: public V8ValueConverter::Strategy {
public:
bool FromV8Object(v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const override {
return false;
}
bool FromV8Array(v8::Local<v8::Array> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const override {
return false;
}
bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate) const override {
return false;
}
bool FromV8Number(v8::Local<v8::Number> value,
- base::Value** out) const override {
+ std::unique_ptr<base::Value>* out) const override {
+ return false;
+ }
+ bool FromV8Undefined(std::unique_ptr<base::Value>* out) const override {
return false;
}
- bool FromV8Undefined(base::Value** out) const override { return false; }
};
// Verify that having a strategy that fallbacks to default behaviour
diff --git a/chromium/content/child/web_database_observer_impl.cc b/chromium/content/child/web_database_observer_impl.cc
index 368e0a56fc2..bddc9e1f18a 100644
--- a/chromium/content/child/web_database_observer_impl.cc
+++ b/chromium/content/child/web_database_observer_impl.cc
@@ -81,27 +81,26 @@ void WebDatabaseObserverImpl::databaseOpened(
const WebString& database_name,
const WebString& database_display_name,
unsigned long estimated_size) {
- const std::string origin_identifier = GetIdentifierFromOrigin(origin);
- open_connections_->AddOpenConnection(origin_identifier, database_name);
+ open_connections_->AddOpenConnection(GetIdentifierFromOrigin(origin),
+ database_name);
sender_->Send(new DatabaseHostMsg_Opened(
- origin_identifier, database_name, database_display_name, estimated_size));
+ origin, database_name, database_display_name, estimated_size));
}
void WebDatabaseObserverImpl::databaseModified(const WebSecurityOrigin& origin,
const WebString& database_name) {
- sender_->Send(new DatabaseHostMsg_Modified(GetIdentifierFromOrigin(origin),
- database_name));
+ sender_->Send(new DatabaseHostMsg_Modified(origin, database_name));
}
void WebDatabaseObserverImpl::databaseClosed(const WebSecurityOrigin& origin,
const WebString& database_name) {
DCHECK(!main_thread_task_runner_->RunsTasksOnCurrentThread());
- const std::string origin_identifier = GetIdentifierFromOrigin(origin);
main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(base::IgnoreResult(&IPC::SyncMessageFilter::Send), sender_,
- new DatabaseHostMsg_Closed(origin_identifier, database_name)));
- open_connections_->RemoveOpenConnection(origin_identifier, database_name);
+ new DatabaseHostMsg_Closed(origin, database_name)));
+ open_connections_->RemoveOpenConnection(GetIdentifierFromOrigin(origin),
+ database_name);
}
void WebDatabaseObserverImpl::reportOpenDatabaseResult(
@@ -191,8 +190,8 @@ void WebDatabaseObserverImpl::HandleSqliteError(const WebSecurityOrigin& origin,
// a unnecessary ipc traffic, this method can get called at a fairly
// high frequency (per-sqlstatement).
if (error == SQLITE_CORRUPT || error == SQLITE_NOTADB) {
- sender_->Send(new DatabaseHostMsg_HandleSqliteError(
- GetIdentifierFromOrigin(origin), database_name, error));
+ sender_->Send(
+ new DatabaseHostMsg_HandleSqliteError(origin, database_name, error));
}
}
diff --git a/chromium/content/child/web_url_loader_impl.cc b/chromium/content/child/web_url_loader_impl.cc
index cf47c4fedca..b729ae7908c 100644
--- a/chromium/content/child/web_url_loader_impl.cc
+++ b/chromium/content/child/web_url_loader_impl.cc
@@ -17,6 +17,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -32,7 +33,7 @@
#include "content/child/web_url_request_util.h"
#include "content/child/weburlresponse_extradata_impl.h"
#include "content/common/resource_messages.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/ssl_status_serialization.h"
#include "content/public/child/fixed_received_data.h"
@@ -43,7 +44,7 @@
#include "net/base/filename_util.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.h"
-#include "net/cert/sct_status_flags.h"
+#include "net/cert/ct_sct_to_string.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/ssl/ssl_cipher_suite_names.h"
@@ -187,8 +188,28 @@ int GetInfoFromDataURL(const GURL& url,
return net::OK;
}
+// Convert a net::SignedCertificateTimestampAndStatus object to a
+// blink::WebURLResponse::SignedCertificateTimestamp object.
+blink::WebURLResponse::SignedCertificateTimestamp NetSCTToBlinkSCT(
+ const net::SignedCertificateTimestampAndStatus& sct_and_status) {
+ return blink::WebURLResponse::SignedCertificateTimestamp(
+ WebString::fromUTF8(net::ct::StatusToString(sct_and_status.status)),
+ WebString::fromUTF8(net::ct::OriginToString(sct_and_status.sct->origin)),
+ WebString::fromUTF8(sct_and_status.sct->log_description),
+ WebString::fromUTF8(base::HexEncode(sct_and_status.sct->log_id.c_str(),
+ sct_and_status.sct->log_id.length())),
+ sct_and_status.sct->timestamp.ToJavaTime(),
+ WebString::fromUTF8(net::ct::HashAlgorithmToString(
+ sct_and_status.sct->signature.hash_algorithm)),
+ WebString::fromUTF8(net::ct::SignatureAlgorithmToString(
+ sct_and_status.sct->signature.signature_algorithm)),
+ WebString::fromUTF8(
+ base::HexEncode(sct_and_status.sct->signature.signature_data.c_str(),
+ sct_and_status.sct->signature.signature_data.length())));
+}
+
void SetSecurityStyleAndDetails(const GURL& url,
- const std::string& security_info,
+ const ResourceResponseInfo& info,
WebURLResponse* response,
bool report_security_info) {
if (!report_security_info) {
@@ -202,6 +223,7 @@ void SetSecurityStyleAndDetails(const GURL& url,
// There are cases where an HTTPS request can come in without security
// info attached (such as a redirect response).
+ const std::string& security_info = info.security_info;
if (security_info.empty()) {
response->setSecurityStyle(WebURLResponse::SecurityStyleUnknown);
return;
@@ -259,10 +281,16 @@ void SetSecurityStyleAndDetails(const GURL& url,
size_t num_invalid_scts = ssl_status.num_invalid_scts;
size_t num_valid_scts = ssl_status.num_valid_scts;
+ blink::WebURLResponse::SignedCertificateTimestampList sct_list(
+ info.signed_certificate_timestamps.size());
+
+ for (size_t i = 0; i < sct_list.size(); ++i)
+ sct_list[i] = NetSCTToBlinkSCT(info.signed_certificate_timestamps[i]);
+
blink::WebURLResponse::WebSecurityDetails webSecurityDetails(
WebString::fromUTF8(protocol), WebString::fromUTF8(key_exchange),
- WebString::fromUTF8(cipher), WebString::fromUTF8(mac),
- ssl_status.cert_id, num_unknown_scts, num_invalid_scts, num_valid_scts);
+ WebString::fromUTF8(cipher), WebString::fromUTF8(mac), ssl_status.cert_id,
+ num_unknown_scts, num_invalid_scts, num_valid_scts, sct_list);
response->setSecurityDetails(webSecurityDetails);
}
@@ -436,12 +464,6 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
SyncLoadResponse* sync_load_response) {
DCHECK(request_id_ == -1);
request_ = request; // Save the request.
- if (request.getExtraData()) {
- RequestExtraData* extra_data =
- static_cast<RequestExtraData*>(request.getExtraData());
- stream_override_ = extra_data->TakeStreamOverrideOwnership();
- }
-
GURL url = request.url();
if (CanHandleDataURLRequestLocally()) {
@@ -461,6 +483,13 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
return;
}
+ if (request.getExtraData()) {
+ RequestExtraData* extra_data =
+ static_cast<RequestExtraData*>(request.getExtraData());
+ stream_override_ = extra_data->TakeStreamOverrideOwnership();
+ }
+
+
// PlzNavigate: outside of tests, the only navigation requests going through
// the WebURLLoader are the ones created by CommitNavigation. Several browser
// tests load HTML directly through a data url which will be handled by the
@@ -505,7 +534,8 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
request_info.routing_id = request.requestorID();
request_info.download_to_file = request.downloadToFile();
request_info.has_user_gesture = request.hasUserGesture();
- request_info.skip_service_worker = request.skipServiceWorker();
+ request_info.skip_service_worker =
+ GetSkipServiceWorkerForWebURLRequest(request);
request_info.should_reset_appcache = request.shouldResetAppCache();
request_info.fetch_request_mode =
GetFetchRequestModeForWebURLRequest(request);
@@ -520,8 +550,9 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
request_info.extra_data = request.getExtraData();
request_info.report_raw_headers = request.reportRawHeaders();
request_info.loading_web_task_runner.reset(web_task_runner_->clone());
+ request_info.lofi_state = static_cast<LoFiState>(request.getLoFiState());
- scoped_refptr<ResourceRequestBody> request_body =
+ scoped_refptr<ResourceRequestBodyImpl> request_body =
GetRequestBodyForWebURLRequest(request).get();
// PlzNavigate: during navigation, the renderer should request a stream which
@@ -579,9 +610,12 @@ bool WebURLLoaderImpl::Context::OnReceivedRedirect(
WebURLRequest new_request;
new_request.initialize();
- PopulateURLRequestForRedirect(request_, redirect_info, referrer_policy_,
- !info.was_fetched_via_service_worker,
- &new_request);
+ PopulateURLRequestForRedirect(
+ request_, redirect_info, referrer_policy_,
+ info.was_fetched_via_service_worker
+ ? blink::WebURLRequest::SkipServiceWorker::None
+ : blink::WebURLRequest::SkipServiceWorker::All,
+ &new_request);
client_->willFollowRedirect(loader_, new_request, response);
request_ = new_request;
@@ -955,9 +989,15 @@ void WebURLLoaderImpl::PopulateURLResponse(const GURL& url,
info.is_in_cache_storage
? blink::WebString::fromUTF8(info.cache_storage_cache_name)
: blink::WebString());
+ blink::WebVector<blink::WebString> cors_exposed_header_names(
+ info.cors_exposed_header_names.size());
+ std::transform(
+ info.cors_exposed_header_names.begin(),
+ info.cors_exposed_header_names.end(), cors_exposed_header_names.begin(),
+ [](const std::string& h) { return blink::WebString::fromLatin1(h); });
+ response->setCorsExposedHeaderNames(cors_exposed_header_names);
- SetSecurityStyleAndDetails(url, info.security_info, response,
- report_security_info);
+ SetSecurityStyleAndDetails(url, info, response, report_security_info);
WebURLResponseExtraDataImpl* extra_data =
new WebURLResponseExtraDataImpl(info.npn_negotiated_protocol);
@@ -1064,7 +1104,7 @@ void WebURLLoaderImpl::PopulateURLRequestForRedirect(
const blink::WebURLRequest& request,
const net::RedirectInfo& redirect_info,
blink::WebReferrerPolicy referrer_policy,
- bool skip_service_worker,
+ blink::WebURLRequest::SkipServiceWorker skip_service_worker,
blink::WebURLRequest* new_request) {
// TODO(darin): We lack sufficient information to construct the actual
// request that resulted from the redirect.
@@ -1082,6 +1122,7 @@ void WebURLLoaderImpl::PopulateURLRequestForRedirect(
new_request->setHTTPReferrer(WebString::fromUTF8(redirect_info.new_referrer),
referrer_policy);
+ new_request->setPriority(request.getPriority());
std::string old_method = request.httpMethod().utf8();
new_request->setHTTPMethod(WebString::fromUTF8(redirect_info.new_method));
diff --git a/chromium/content/child/web_url_loader_impl.h b/chromium/content/child/web_url_loader_impl.h
index d1f4f81064f..53fbe1d6b5c 100644
--- a/chromium/content/child/web_url_loader_impl.h
+++ b/chromium/content/child/web_url_loader_impl.h
@@ -50,7 +50,7 @@ class CONTENT_EXPORT WebURLLoaderImpl
const blink::WebURLRequest& request,
const net::RedirectInfo& redirect_info,
blink::WebReferrerPolicy referrer_policy,
- bool skip_service_worker,
+ blink::WebURLRequest::SkipServiceWorker skip_service_worker,
blink::WebURLRequest* new_request);
// WebURLLoader methods:
diff --git a/chromium/content/child/web_url_loader_impl_unittest.cc b/chromium/content/child/web_url_loader_impl_unittest.cc
index ac54c49a11b..5284b1de537 100644
--- a/chromium/content/child/web_url_loader_impl_unittest.cc
+++ b/chromium/content/child/web_url_loader_impl_unittest.cc
@@ -68,7 +68,7 @@ class TestResourceDispatcher : public ResourceDispatcher {
// TestDispatcher implementation:
int StartAsync(const RequestInfo& request_info,
- ResourceRequestBody* request_body,
+ ResourceRequestBodyImpl* request_body,
std::unique_ptr<RequestPeer> peer) override {
EXPECT_FALSE(peer_);
peer_ = std::move(peer);
@@ -118,6 +118,7 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
delete_on_fail_(false),
did_receive_redirect_(false),
did_receive_response_(false),
+ check_redirect_request_priority_(false),
did_finish_(false) {}
~TestWebURLLoaderClient() override {}
@@ -129,6 +130,10 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
const blink::WebURLResponse& redirectResponse) override {
EXPECT_TRUE(loader_);
EXPECT_EQ(loader_.get(), loader);
+
+ if (check_redirect_request_priority_)
+ EXPECT_EQ(redirect_request_priority, newRequest.getPriority());
+
// No test currently simulates mutiple redirects.
EXPECT_FALSE(did_receive_redirect_);
did_receive_redirect_ = true;
@@ -222,6 +227,10 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
void set_delete_on_receive_data() { delete_on_receive_data_ = true; }
void set_delete_on_finish() { delete_on_finish_ = true; }
void set_delete_on_fail() { delete_on_fail_ = true; }
+ void set_redirect_request_priority(blink::WebURLRequest::Priority priority) {
+ check_redirect_request_priority_ = true;
+ redirect_request_priority = priority;
+ }
bool did_receive_redirect() const { return did_receive_redirect_; }
bool did_receive_response() const { return did_receive_response_; }
@@ -241,6 +250,8 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
bool did_receive_redirect_;
bool did_receive_response_;
+ bool check_redirect_request_priority_;
+ blink::WebURLRequest::Priority redirect_request_priority;
std::string received_data_;
bool did_finish_;
blink::WebURLError error_;
@@ -271,6 +282,16 @@ class WebURLLoaderImplTest : public testing::Test {
ASSERT_TRUE(peer());
}
+ void DoStartAsyncRequestWithPriority(
+ blink::WebURLRequest::Priority priority) {
+ blink::WebURLRequest request;
+ request.initialize();
+ request.setPriority(priority);
+ request.setURL(GURL(kTestURL));
+ client()->loader()->loadAsynchronously(request, client());
+ ASSERT_TRUE(peer());
+ }
+
void DoReceiveRedirect() {
EXPECT_FALSE(client()->did_receive_redirect());
net::RedirectInfo redirect_info;
@@ -364,6 +385,19 @@ TEST_F(WebURLLoaderImplTest, Redirect) {
EXPECT_EQ(kTestData, client()->received_data());
}
+TEST_F(WebURLLoaderImplTest, RedirectCorrectPriority) {
+ DoStartAsyncRequestWithPriority(
+ blink::WebURLRequest::Priority::PriorityVeryHigh);
+ client()->set_redirect_request_priority(
+ blink::WebURLRequest::Priority::PriorityVeryHigh);
+ DoReceiveRedirect();
+ DoReceiveResponse();
+ DoReceiveData();
+ DoCompleteRequest();
+ EXPECT_FALSE(dispatcher()->canceled());
+ EXPECT_EQ(kTestData, client()->received_data());
+}
+
TEST_F(WebURLLoaderImplTest, Failure) {
DoStartAsyncRequest();
DoReceiveResponse();
diff --git a/chromium/content/child/web_url_request_util.cc b/chromium/content/child/web_url_request_util.cc
index 5f14fbb4d9a..e23e5b7bea1 100644
--- a/chromium/content/child/web_url_request_util.cc
+++ b/chromium/content/child/web_url_request_util.cc
@@ -15,6 +15,7 @@
#include "net/base/net_errors.h"
#include "third_party/WebKit/public/platform/FilePathConversion.h"
#include "third_party/WebKit/public/platform/WebCachePolicy.h"
+#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -22,6 +23,7 @@
#include "third_party/WebKit/public/platform/WebURLRequest.h"
using blink::WebCachePolicy;
+using blink::WebData;
using blink::WebHTTPBody;
using blink::WebString;
using blink::WebURLRequest;
@@ -217,9 +219,48 @@ int GetLoadFlagsForWebURLRequest(const blink::WebURLRequest& request) {
return load_flags;
}
-scoped_refptr<ResourceRequestBody> GetRequestBodyForWebURLRequest(
+WebHTTPBody GetWebHTTPBodyForRequestBody(
+ const scoped_refptr<ResourceRequestBodyImpl>& input) {
+ WebHTTPBody http_body;
+ http_body.initialize();
+ http_body.setIdentifier(input->identifier());
+ for (const auto& element : *input->elements()) {
+ switch (element.type()) {
+ case ResourceRequestBodyImpl::Element::TYPE_BYTES:
+ http_body.appendData(WebData(element.bytes(), element.length()));
+ break;
+ case ResourceRequestBodyImpl::Element::TYPE_FILE:
+ http_body.appendFileRange(
+ element.path().AsUTF16Unsafe(), element.offset(),
+ (element.length() != std::numeric_limits<uint64_t>::max())
+ ? element.length()
+ : -1,
+ element.expected_modification_time().ToDoubleT());
+ break;
+ case ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM:
+ http_body.appendFileSystemURLRange(
+ element.filesystem_url(), element.offset(),
+ (element.length() != std::numeric_limits<uint64_t>::max())
+ ? element.length()
+ : -1,
+ element.expected_modification_time().ToDoubleT());
+ break;
+ case ResourceRequestBodyImpl::Element::TYPE_BLOB:
+ http_body.appendBlob(WebString::fromUTF8(element.blob_uuid()));
+ break;
+ case ResourceRequestBodyImpl::Element::TYPE_BYTES_DESCRIPTION:
+ case ResourceRequestBodyImpl::Element::TYPE_DISK_CACHE_ENTRY:
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ return http_body;
+}
+
+scoped_refptr<ResourceRequestBodyImpl> GetRequestBodyForWebURLRequest(
const blink::WebURLRequest& request) {
- scoped_refptr<ResourceRequestBody> request_body;
+ scoped_refptr<ResourceRequestBodyImpl> request_body;
if (request.httpBody().isNull()) {
return request_body;
@@ -229,8 +270,13 @@ scoped_refptr<ResourceRequestBody> GetRequestBodyForWebURLRequest(
// GET and HEAD requests shouldn't have http bodies.
DCHECK(method != "GET" && method != "HEAD");
- const WebHTTPBody& httpBody = request.httpBody();
- request_body = new ResourceRequestBody();
+ return GetRequestBodyForWebHTTPBody(request.httpBody());
+}
+
+scoped_refptr<ResourceRequestBodyImpl> GetRequestBodyForWebHTTPBody(
+ const blink::WebHTTPBody& httpBody) {
+ scoped_refptr<ResourceRequestBodyImpl> request_body =
+ new ResourceRequestBodyImpl();
size_t i = 0;
WebHTTPBody::Element element;
while (httpBody.elementAt(i++, element)) {
@@ -272,7 +318,7 @@ scoped_refptr<ResourceRequestBody> GetRequestBodyForWebURLRequest(
NOTREACHED();
}
}
- request_body->set_identifier(request.httpBody().identifier());
+ request_body->set_identifier(httpBody.identifier());
return request_body;
}
@@ -410,6 +456,18 @@ RequestContextType GetRequestContextTypeForWebURLRequest(
return static_cast<RequestContextType>(request.getRequestContext());
}
+STATIC_ASSERT_ENUM(SkipServiceWorker::NONE,
+ WebURLRequest::SkipServiceWorker::None);
+STATIC_ASSERT_ENUM(SkipServiceWorker::CONTROLLING,
+ WebURLRequest::SkipServiceWorker::Controlling);
+STATIC_ASSERT_ENUM(SkipServiceWorker::ALL,
+ WebURLRequest::SkipServiceWorker::All);
+
+SkipServiceWorker GetSkipServiceWorkerForWebURLRequest(
+ const blink::WebURLRequest& request) {
+ return static_cast<SkipServiceWorker>(request.skipServiceWorker());
+}
+
blink::WebURLError CreateWebURLError(const blink::WebURL& unreachable_url,
bool stale_copy_in_cache,
int reason) {
diff --git a/chromium/content/child/web_url_request_util.h b/chromium/content/child/web_url_request_util.h
index 4a1da0cf0fc..6763af8b9db 100644
--- a/chromium/content/child/web_url_request_util.h
+++ b/chromium/content/child/web_url_request_util.h
@@ -8,13 +8,14 @@
#include <string>
#include "content/common/content_export.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/request_context_frame_type.h"
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
namespace blink {
+class WebHTTPBody;
class WebURL;
class WebURLRequest;
struct WebURLError;
@@ -29,10 +30,18 @@ std::string GetWebURLRequestHeaders(const blink::WebURLRequest& request);
int GetLoadFlagsForWebURLRequest(const blink::WebURLRequest& request);
+// Takes a ResourceRequestBodyImpl and converts into WebHTTPBody.
+blink::WebHTTPBody GetWebHTTPBodyForRequestBody(
+ const scoped_refptr<ResourceRequestBodyImpl>& input);
+
+// Takes a WebHTTPBody and converts into a ResourceRequestBodyImpl.
+scoped_refptr<ResourceRequestBodyImpl> GetRequestBodyForWebHTTPBody(
+ const blink::WebHTTPBody& httpBody);
+
// Takes a WebURLRequest and sets the appropriate information
-// in a ResourceRequestBody structure. Returns an empty scoped_refptr
+// in a ResourceRequestBodyImpl structure. Returns an empty scoped_refptr
// if the request body is not present.
-scoped_refptr<ResourceRequestBody> GetRequestBodyForWebURLRequest(
+scoped_refptr<ResourceRequestBodyImpl> GetRequestBodyForWebURLRequest(
const blink::WebURLRequest& request);
// Helper functions to convert enums from the blink type to the content
@@ -47,6 +56,8 @@ RequestContextFrameType GetRequestContextFrameTypeForWebURLRequest(
const blink::WebURLRequest& request);
RequestContextType GetRequestContextTypeForWebURLRequest(
const blink::WebURLRequest& request);
+SkipServiceWorker GetSkipServiceWorkerForWebURLRequest(
+ const blink::WebURLRequest& request);
// Generates a WebURLError based on |reason|.
blink::WebURLError CreateWebURLError(const blink::WebURL& unreachable_url,
diff --git a/chromium/content/child/websocket_bridge.cc b/chromium/content/child/websocket_bridge.cc
index 7cfff1ad50a..bd94b425874 100644
--- a/chromium/content/child/websocket_bridge.cc
+++ b/chromium/content/child/websocket_bridge.cc
@@ -206,6 +206,8 @@ void WebSocketBridge::DidStartClosingHandshake() {
void WebSocketBridge::connect(const WebURL& url,
const WebVector<WebString>& protocols,
const WebSecurityOrigin& origin,
+ const WebURL& first_party_for_cookies,
+ const WebString& user_agent_override,
WebSocketHandleClient* client) {
DCHECK_EQ(kInvalidChannelId, channel_id_);
WebSocketDispatcher* dispatcher =
@@ -221,8 +223,17 @@ void WebSocketBridge::connect(const WebURL& url,
<< base::JoinString(protocols_to_pass, ", ") << "), "
<< origin.toString().utf8() << ")";
+ WebSocketHostMsg_AddChannelRequest_Params params;
+ params.socket_url = url;
+ params.requested_protocols = protocols_to_pass;
+ params.origin = origin;
+ params.first_party_for_cookies = first_party_for_cookies;
+ params.user_agent_override = user_agent_override.latin1();
+ params.render_frame_id = render_frame_id_;
+
+ // Headers (ie: User-Agent) are ISO Latin 1.
ChildThreadImpl::current()->Send(new WebSocketHostMsg_AddChannelRequest(
- channel_id_, url, protocols_to_pass, origin, render_frame_id_));
+ channel_id_, params));
}
void WebSocketBridge::send(bool fin,
diff --git a/chromium/content/child/websocket_bridge.h b/chromium/content/child/websocket_bridge.h
index ab5e3dca019..d8ccc2bab4a 100644
--- a/chromium/content/child/websocket_bridge.h
+++ b/chromium/content/child/websocket_bridge.h
@@ -34,6 +34,8 @@ class WebSocketBridge : public blink::WebSocketHandle {
void connect(const blink::WebURL& url,
const blink::WebVector<blink::WebString>& protocols,
const blink::WebSecurityOrigin& origin,
+ const blink::WebURL& first_party_for_cookies,
+ const blink::WebString& user_agent_override,
blink::WebSocketHandleClient* client) override;
void send(bool fin,
WebSocketHandle::MessageType type,
diff --git a/chromium/content/child/websocket_dispatcher.cc b/chromium/content/child/websocket_dispatcher.cc
index 9fc3370bb65..13535eb51af 100644
--- a/chromium/content/child/websocket_dispatcher.cc
+++ b/chromium/content/child/websocket_dispatcher.cc
@@ -15,10 +15,28 @@
namespace content {
-WebSocketDispatcher::WebSocketDispatcher() : channel_id_max_(0) {}
+WebSocketDispatcher::WebSocketDispatcher()
+ : channel_id_max_(0),
+ weak_ptr_factory_(this) {}
WebSocketDispatcher::~WebSocketDispatcher() {}
+bool WebSocketDispatcher::CanHandleMessage(const IPC::Message& msg) {
+ switch (msg.type()) {
+ case WebSocketMsg_AddChannelResponse::ID:
+ case WebSocketMsg_NotifyStartOpeningHandshake::ID:
+ case WebSocketMsg_NotifyFinishOpeningHandshake::ID:
+ case WebSocketMsg_NotifyFailure::ID:
+ case WebSocketMsg_SendFrame::ID:
+ case WebSocketMsg_FlowControl::ID:
+ case WebSocketMsg_DropChannel::ID:
+ case WebSocketMsg_NotifyClosing::ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
int WebSocketDispatcher::AddBridge(WebSocketBridge* bridge) {
++channel_id_max_;
bridges_.insert(std::make_pair(channel_id_max_, bridge));
@@ -35,20 +53,8 @@ void WebSocketDispatcher::RemoveBridge(int channel_id) {
}
bool WebSocketDispatcher::OnMessageReceived(const IPC::Message& msg) {
- switch (msg.type()) {
- case WebSocketMsg_AddChannelResponse::ID:
- case WebSocketMsg_NotifyStartOpeningHandshake::ID:
- case WebSocketMsg_NotifyFinishOpeningHandshake::ID:
- case WebSocketMsg_NotifyFailure::ID:
- case WebSocketMsg_SendFrame::ID:
- case WebSocketMsg_FlowControl::ID:
- case WebSocketMsg_DropChannel::ID:
- case WebSocketMsg_NotifyClosing::ID:
- break;
- default:
- return false;
- }
-
+ if (!CanHandleMessage(msg))
+ return false;
WebSocketBridge* bridge = GetBridge(msg.routing_id(), msg.type());
if (!bridge)
return true;
diff --git a/chromium/content/child/websocket_dispatcher.h b/chromium/content/child/websocket_dispatcher.h
index e40053de41c..bd2fd50d6de 100644
--- a/chromium/content/child/websocket_dispatcher.h
+++ b/chromium/content/child/websocket_dispatcher.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "ipc/ipc_listener.h"
namespace content {
@@ -27,6 +28,8 @@ class WebSocketDispatcher : public IPC::Listener {
WebSocketDispatcher();
~WebSocketDispatcher() override;
+ static bool CanHandleMessage(const IPC::Message& msg);
+
// Returns a unique channel id
int AddBridge(WebSocketBridge* bridge);
void RemoveBridge(int channel_id);
@@ -34,11 +37,16 @@ class WebSocketDispatcher : public IPC::Listener {
// IPC::Listener implementation.
bool OnMessageReceived(const IPC::Message& msg) override;
+ base::WeakPtr<WebSocketDispatcher> GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
private:
WebSocketBridge* GetBridge(int channel_id, uint32_t type);
std::map<int, WebSocketBridge*> bridges_;
int channel_id_max_;
+ base::WeakPtrFactory<WebSocketDispatcher> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(WebSocketDispatcher);
};
diff --git a/chromium/content/child/websocket_message_filter.cc b/chromium/content/child/websocket_message_filter.cc
new file mode 100644
index 00000000000..b2e54c08f96
--- /dev/null
+++ b/chromium/content/child/websocket_message_filter.cc
@@ -0,0 +1,36 @@
+// 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/child/websocket_message_filter.h"
+
+#include "base/bind.h"
+#include "base/single_thread_task_runner.h"
+#include "content/child/websocket_dispatcher.h"
+#include "ipc/ipc_message.h"
+
+namespace content {
+
+WebSocketMessageFilter::WebSocketMessageFilter(
+ WebSocketDispatcher* websocket_dispatcher)
+ : websocket_dispatcher_(websocket_dispatcher->GetWeakPtr()) {}
+
+WebSocketMessageFilter::~WebSocketMessageFilter() {}
+
+bool WebSocketMessageFilter::OnMessageReceived(const IPC::Message& message) {
+ if (!WebSocketDispatcher::CanHandleMessage(message))
+ return false;
+ loading_task_runner_->PostTask(FROM_HERE, base::Bind(
+ &WebSocketMessageFilter::OnMessageReceivedOnMainThread,
+ this, message));
+ return true;
+}
+
+void WebSocketMessageFilter::OnMessageReceivedOnMainThread(
+ const IPC::Message& message) {
+ if (!websocket_dispatcher_.get())
+ return;
+ websocket_dispatcher_->OnMessageReceived(message);
+}
+
+} // namespace content
diff --git a/chromium/content/child/websocket_message_filter.h b/chromium/content/child/websocket_message_filter.h
new file mode 100644
index 00000000000..00efbb213ac
--- /dev/null
+++ b/chromium/content/child/websocket_message_filter.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_CHILD_WEBSOCKET_MESSAGE_FILTER_H_
+#define CONTENT_CHILD_WEBSOCKET_MESSAGE_FILTER_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "ipc/message_filter.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace content {
+
+class WebSocketDispatcher;
+
+// Delegates IPC messages to a WebSocketDispatcher on the loading task queue
+// instead of the default task queue.
+class WebSocketMessageFilter : public IPC::MessageFilter {
+ public:
+ explicit WebSocketMessageFilter(WebSocketDispatcher* websocket_dispatcher);
+
+ // IPC::MessageFilter implementation.
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ void SetLoadingTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner) {
+ loading_task_runner_ = loading_task_runner;
+ }
+
+ private:
+ ~WebSocketMessageFilter() override;
+ void OnMessageReceivedOnMainThread(const IPC::Message& message);
+
+ scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
+
+ // This actual object is owned by a ChildThreadImpl and is derefed only on the
+ // main thread.
+ base::WeakPtr<WebSocketDispatcher> websocket_dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBSOCKET_MESSAGE_FILTER_H_
diff --git a/chromium/content/common/BUILD.gn b/chromium/content/common/BUILD.gn
index b4005ba3f2f..d829dc56500 100644
--- a/chromium/content/common/BUILD.gn
+++ b/chromium/content/common/BUILD.gn
@@ -7,6 +7,7 @@ import("//build/config/ui.gni")
import("//content/common/common.gni")
import("//media/media_options.gni")
import("//mojo/public/tools/bindings/mojom.gni")
+import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
if (is_mac) {
import("//build/config/mac/mac_sdk.gni")
}
@@ -44,6 +45,8 @@ source_set("common") {
"//components/mus/public/interfaces",
"//components/tracing",
"//components/tracing:startup_tracing",
+ "//content:resources",
+ "//content/app/resources",
"//device/bluetooth",
"//gpu",
"//gpu/command_buffer/client:gles2_c_lib",
@@ -56,16 +59,15 @@ source_set("common") {
"//gpu/ipc/common",
"//gpu/skia_bindings",
"//ipc",
- "//ipc/mojo",
"//media",
"//media:shared_memory_support",
"//media/base/ipc",
+ "//media/capture",
"//media/gpu/ipc/client",
"//media/gpu/ipc/common",
"//media/midi",
"//mojo/common:common_base",
"//mojo/edk/system",
- "//mojo/platform_handle:platform_handle_impl",
"//net",
"//sandbox",
"//services/shell",
@@ -82,6 +84,7 @@ source_set("common") {
"//ui/accessibility",
"//ui/base",
"//ui/base/ime",
+ "//ui/display",
"//ui/events/ipc",
"//ui/gfx",
"//ui/gfx/geometry",
@@ -157,12 +160,14 @@ source_set("common") {
}
if (enable_plugins) {
- deps += [ "//ppapi/shared_impl" ]
+ deps += [
+ "//ppapi/proxy",
+ "//ppapi/shared_impl",
+ ]
} else {
sources -= [
"pepper_file_util.cc",
"pepper_file_util.h",
- "pepper_messages.h",
"pepper_plugin_list.cc",
"pepper_plugin_list.h",
"pepper_renderer_instance_data.cc",
@@ -202,6 +207,18 @@ source_set("common") {
]
}
}
+
+ if (is_mac) {
+ deps += [ "//media/gpu" ]
+ }
+
+ if (enable_ipc_fuzzer) {
+ configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_config" ]
+ sources += [
+ "external_ipc_dumper.cc",
+ "external_ipc_dumper.h",
+ ]
+ }
}
# See comment at the top of //content/BUILD.gn for how this works.
@@ -222,11 +239,10 @@ mojom("mojo_bindings") {
visibility = [ "//content/*" ]
sources = [
- "application_setup.mojom",
+ "frame.mojom",
"image_downloader/image_downloader.mojom",
"leveldb_wrapper.mojom",
"process_control.mojom",
- "render_frame_setup.mojom",
"render_widget_window_tree_client_factory.mojom",
"service_worker/embedded_worker_setup.mojom",
"storage_partition_service.mojom",
@@ -240,7 +256,8 @@ mojom("mojo_bindings") {
"//services/shell/public/interfaces",
"//skia/public/interfaces",
"//third_party/WebKit/public:mojo_bindings",
- "//ui/mojo/geometry:interfaces",
+ "//ui/gfx/geometry/mojo",
+ "//url/mojo:url_mojom_gurl",
"//url/mojo:url_mojom_origin",
]
}
diff --git a/chromium/content/common/DEPS b/chromium/content/common/DEPS
index 01e10486c1d..ad4b6f0228a 100644
--- a/chromium/content/common/DEPS
+++ b/chromium/content/common/DEPS
@@ -15,6 +15,7 @@ include_rules = [
"+third_party/WebKit/public/platform/WebGamepads.h",
"+third_party/WebKit/public/platform/WebHTTPBody.h",
"+third_party/WebKit/public/platform/WebHistoryScrollRestorationType.h",
+ "+third_party/WebKit/public/platform/WebInsecureRequestPolicy.h",
"+third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h",
"+third_party/WebKit/public/platform/WebPageVisibilityState.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
@@ -48,6 +49,7 @@ include_rules = [
"+third_party/WebKit/public/web/WebDragStatus.h",
"+third_party/WebKit/public/web/WebFindOptions.h",
"+third_party/WebKit/public/web/WebFrameOwnerProperties.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",
diff --git a/chromium/content/common/OWNERS b/chromium/content/common/OWNERS
index 872aef9cf76..77241690419 100644
--- a/chromium/content/common/OWNERS
+++ b/chromium/content/common/OWNERS
@@ -17,70 +17,20 @@ per-file pepper*=bauerb@chromium.org
per-file plugin*=ananta@chromium.org
per-file plugin*=bauerb@chromium.org
-# Changes to IPC messages require a security review to avoid introducing
-# new sandbox escapes.
-per-file *_message*.h=set noparent
-per-file *_message*.h=dcheng@chromium.org
-per-file *_message*.h=inferno@chromium.org
-per-file *_message*.h=jln@chromium.org
-per-file *_message*.h=jschuh@chromium.org
-per-file *_message*.h=kenrb@chromium.org
-per-file *_message*.h=mkwst@chromium.org
-per-file *_message*.h=nasko@chromium.org
-per-file *_message*.h=palmer@chromium.org
-per-file *_message*.h=tsepez@chromium.org
-per-file *_message*.h=wfh@chromium.org
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
per-file *_messages.cc=set noparent
-per-file *_messages.cc=dcheng@chromium.org
-per-file *_messages.cc=inferno@chromium.org
-per-file *_messages.cc=jln@chromium.org
-per-file *_messages.cc=jschuh@chromium.org
-per-file *_messages.cc=kenrb@chromium.org
-per-file *_messages.cc=mkwst@chromium.org
-per-file *_messages.cc=nasko@chromium.org
-per-file *_messages.cc=palmer@chromium.org
-per-file *_messages.cc=tsepez@chromium.org
-per-file *_messages.cc=wfh@chromium.org
+per-file *_messages.cc=file://ipc/SECURITY_OWNERS
-per-file *param_traits*.h=set noparent
-per-file *param_traits*.h=dcheng@chromium.org
-per-file *param_traits*.h=inferno@chromium.org
-per-file *param_traits*.h=jln@chromium.org
-per-file *param_traits*.h=jschuh@chromium.org
-per-file *param_traits*.h=kenrb@chromium.org
-per-file *param_traits*.h=mkwst@chromium.org
-per-file *param_traits*.h=nasko@chromium.org
-per-file *param_traits*.h=palmer@chromium.org
-per-file *param_traits*.h=tsepez@chromium.org
-per-file *param_traits*.h=wfh@chromium.org
+per-file *_param_traits*.*=set noparent
+per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
per-file *font_config_ipc_linux*=set noparent
-per-file *font_config_ipc_linux*=dcheng@chromium.org
-per-file *font_config_ipc_linux*=inferno@chromium.org
-per-file *font_config_ipc_linux*=jln@chromium.org
-per-file *font_config_ipc_linux*=jschuh@chromium.org
-per-file *font_config_ipc_linux*=kenrb@chromium.org
-per-file *font_config_ipc_linux*=mkwst@chromium.org
-per-file *font_config_ipc_linux*=nasko@chromium.org
-per-file *font_config_ipc_linux*=palmer@chromium.org
-per-file *font_config_ipc_linux*=tsepez@chromium.org
-per-file *font_config_ipc_linux*=wfh@chromium.org
+per-file *font_config_ipc_linux*=file://ipc/SECURITY_OWNERS
-# Changes to Mojo interfaces require a security review to avoid
-# introducing new sandbox escapes.
per-file *.mojom=set noparent
-per-file *.mojom=dcheng@chromium.org
-per-file *.mojom=inferno@chromium.org
-per-file *.mojom=jln@chromium.org
-per-file *.mojom=jschuh@chromium.org
-per-file *.mojom=kenrb@chromium.org
-per-file *.mojom=mkwst@chromium.org
-per-file *.mojom=nasko@chromium.org
-per-file *.mojom=palmer@chromium.org
-per-file *.mojom=tsepez@chromium.org
-per-file *.mojom=wfh@chromium.org
-
+per-file *.mojom=file://ipc/SECURITY_OWNERS
# Accessibility
per-file accessibility_node_data.*=dmazzoni@chromium.org
diff --git a/chromium/content/common/all_messages.h b/chromium/content/common/all_messages.h
index 106af5aaa50..6e9f289dce4 100644
--- a/chromium/content/common/all_messages.h
+++ b/chromium/content/common/all_messages.h
@@ -4,7 +4,7 @@
// Multiply-included file, hence no include guard.
// Inclusion of all message files present in content. Keep this file
-// up-to-date when adding a new value to the IPCMessageStart enum in
+// up to date when adding a new value to the IPCMessageStart enum in
// ipc/ipc_message_start.h to ensure the corresponding message file is
// included here.
#include "content/common/content_message_generator.h"
diff --git a/chromium/content/common/android/OWNERS b/chromium/content/common/android/OWNERS
index dcf1b07f36f..9e94ab23248 100644
--- a/chromium/content/common/android/OWNERS
+++ b/chromium/content/common/android/OWNERS
@@ -1,40 +1,11 @@
tedchoc@chromium.org
yfriedman@chromium.org
-# Changes to IPC messages require a security review to avoid introducing
-# new sandbox escapes.
-per-file *_message*.h=set noparent
-per-file *_message*.h=dcheng@chromium.org
-per-file *_message*.h=inferno@chromium.org
-per-file *_message*.h=jln@chromium.org
-per-file *_message*.h=jschuh@chromium.org
-per-file *_message*.h=kenrb@chromium.org
-per-file *_message*.h=mkwst@chromium.org
-per-file *_message*.h=nasko@chromium.org
-per-file *_message*.h=palmer@chromium.org
-per-file *_message*.h=tsepez@chromium.org
-per-file *_message*.h=wfh@chromium.org
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
per-file *_messages.cc=set noparent
-per-file *_messages.cc=dcheng@chromium.org
-per-file *_messages.cc=inferno@chromium.org
-per-file *_messages.cc=jln@chromium.org
-per-file *_messages.cc=jschuh@chromium.org
-per-file *_messages.cc=kenrb@chromium.org
-per-file *_messages.cc=mkwst@chromium.org
-per-file *_messages.cc=nasko@chromium.org
-per-file *_messages.cc=palmer@chromium.org
-per-file *_messages.cc=tsepez@chromium.org
-per-file *_messages.cc=wfh@chromium.org
+per-file *_messages.cc=file://ipc/SECURITY_OWNERS
-per-file *_param_traits.*=set noparent
-per-file *_param_traits.*=dcheng@chromium.org
-per-file *_param_traits.*=inferno@chromium.org
-per-file *_param_traits.*=jln@chromium.org
-per-file *_param_traits.*=jschuh@chromium.org
-per-file *_param_traits.*=kenrb@chromium.org
-per-file *_param_traits.*=mkwst@chromium.org
-per-file *_param_traits.*=nasko@chromium.org
-per-file *_param_traits.*=palmer@chromium.org
-per-file *_param_traits.*=tsepez@chromium.org
-per-file *_param_traits.*=wfh@chromium.org
+per-file *_param_traits*.*=set noparent
+per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/android/gin_java_bridge_value.cc b/chromium/content/common/android/gin_java_bridge_value.cc
index c06ac84ead2..6a7423055fc 100644
--- a/chromium/content/common/android/gin_java_bridge_value.cc
+++ b/chromium/content/common/android/gin_java_bridge_value.cc
@@ -4,8 +4,6 @@
#include "content/common/android/gin_java_bridge_value.h"
-#include "base/memory/ptr_util.h"
-
namespace content {
namespace {
@@ -30,7 +28,7 @@ struct Header : public base::Pickle::Header {
// static
std::unique_ptr<base::BinaryValue> GinJavaBridgeValue::CreateUndefinedValue() {
GinJavaBridgeValue gin_value(TYPE_UNDEFINED);
- return base::WrapUnique(gin_value.SerializeToBinaryValue());
+ return gin_value.SerializeToBinaryValue();
}
// static
@@ -38,7 +36,7 @@ std::unique_ptr<base::BinaryValue> GinJavaBridgeValue::CreateNonFiniteValue(
float in_value) {
GinJavaBridgeValue gin_value(TYPE_NONFINITE);
gin_value.pickle_.WriteFloat(in_value);
- return base::WrapUnique(gin_value.SerializeToBinaryValue());
+ return gin_value.SerializeToBinaryValue();
}
// static
@@ -52,7 +50,7 @@ std::unique_ptr<base::BinaryValue> GinJavaBridgeValue::CreateObjectIDValue(
int32_t in_value) {
GinJavaBridgeValue gin_value(TYPE_OBJECT_ID);
gin_value.pickle_.WriteInt(in_value);
- return base::WrapUnique(gin_value.SerializeToBinaryValue());
+ return gin_value.SerializeToBinaryValue();
}
// static
@@ -122,7 +120,8 @@ GinJavaBridgeValue::GinJavaBridgeValue(const base::BinaryValue* value)
DCHECK(ContainsGinJavaBridgeValue(value));
}
-base::BinaryValue* GinJavaBridgeValue::SerializeToBinaryValue() {
+std::unique_ptr<base::BinaryValue>
+GinJavaBridgeValue::SerializeToBinaryValue() {
return base::BinaryValue::CreateWithCopiedBuffer(
reinterpret_cast<const char*>(pickle_.data()), pickle_.size());
}
diff --git a/chromium/content/common/android/gin_java_bridge_value.h b/chromium/content/common/android/gin_java_bridge_value.h
index b5090c3ea17..1cd92d8b767 100644
--- a/chromium/content/common/android/gin_java_bridge_value.h
+++ b/chromium/content/common/android/gin_java_bridge_value.h
@@ -58,7 +58,7 @@ class GinJavaBridgeValue {
private:
explicit GinJavaBridgeValue(Type type);
explicit GinJavaBridgeValue(const base::BinaryValue* value);
- base::BinaryValue* SerializeToBinaryValue();
+ std::unique_ptr<base::BinaryValue> SerializeToBinaryValue();
base::Pickle pickle_;
diff --git a/chromium/content/common/android/resource_request_body_android.cc b/chromium/content/common/android/resource_request_body_android.cc
new file mode 100644
index 00000000000..3f91c9a1d36
--- /dev/null
+++ b/chromium/content/common/android/resource_request_body_android.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/common/android/resource_request_body_android.h"
+
+#include <jni.h>
+
+#include <string>
+
+#include "base/android/jni_array.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/page_state_serialization.h"
+#include "content/public/common/resource_request_body.h"
+#include "jni/ResourceRequestBody_jni.h"
+
+namespace content {
+
+namespace {
+
+base::android::ScopedJavaLocalRef<jbyteArray>
+ConvertResourceRequestBodyToJavaArray(JNIEnv* env,
+ const ResourceRequestBodyImpl& body) {
+ std::string encoded = EncodeResourceRequestBody(body);
+ return base::android::ToJavaByteArray(
+ env, reinterpret_cast<const uint8_t*>(encoded.data()), encoded.size());
+}
+
+} // namespace
+
+bool RegisterResourceRequestBody(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+base::android::ScopedJavaLocalRef<jbyteArray>
+CreateResourceRequestBodyFromBytes(
+ JNIEnv* env,
+ const JavaParamRef<jclass>& clazz,
+ const JavaParamRef<jbyteArray>& j_post_data) {
+ base::android::ScopedJavaLocalRef<jbyteArray> result;
+ if (!j_post_data)
+ return result;
+
+ std::vector<uint8_t> post_data;
+ base::android::JavaByteArrayToByteVector(env, j_post_data, &post_data);
+ scoped_refptr<ResourceRequestBody> body =
+ ResourceRequestBody::CreateFromBytes(
+ reinterpret_cast<const char*>(post_data.data()), post_data.size());
+
+ return ConvertResourceRequestBodyToJavaArray(
+ env, static_cast<const ResourceRequestBodyImpl&>(*body));
+}
+
+base::android::ScopedJavaLocalRef<jobject>
+ConvertResourceRequestBodyToJavaObject(
+ JNIEnv* env,
+ const scoped_refptr<ResourceRequestBodyImpl>& body) {
+ if (!body)
+ return base::android::ScopedJavaLocalRef<jobject>();
+
+ // TODO(lukasza): Avoid repeatedly copying the bytes.
+ // See also https://goo.gl/ITiLGI.
+ base::android::ScopedJavaLocalRef<jbyteArray> j_encoded =
+ ConvertResourceRequestBodyToJavaArray(env, *body);
+
+ return Java_ResourceRequestBody_createFromEncodedNativeForm(env,
+ j_encoded.obj());
+}
+
+scoped_refptr<ResourceRequestBodyImpl> ExtractResourceRequestBodyFromJavaObject(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_body) {
+ if (!j_body)
+ return nullptr;
+
+ base::android::ScopedJavaLocalRef<jbyteArray> j_encoded =
+ Java_ResourceRequestBody_getEncodedNativeForm(env, j_body.obj());
+ if (j_encoded.is_null())
+ return nullptr;
+
+ std::vector<uint8_t> encoded;
+ base::android::JavaByteArrayToByteVector(env, j_encoded.obj(), &encoded);
+
+ return DecodeResourceRequestBody(
+ reinterpret_cast<const char*>(encoded.data()), encoded.size());
+}
+
+} // namespace content
diff --git a/chromium/content/common/android/resource_request_body_android.h b/chromium/content/common/android/resource_request_body_android.h
new file mode 100644
index 00000000000..70373ebff2a
--- /dev/null
+++ b/chromium/content/common/android/resource_request_body_android.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_ANDROID_RESOURCE_REQUEST_BODY_JNI_H_
+#define CONTENT_BROWSER_ANDROID_RESOURCE_REQUEST_BODY_JNI_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/ref_counted.h"
+
+namespace content {
+
+class ResourceRequestBodyImpl;
+
+bool RegisterResourceRequestBody(JNIEnv* env);
+
+// Returns an instance of org.chromium.content_public.common.ResourceRequestBody
+// that contains serialized representation of the |native_object|.
+base::android::ScopedJavaLocalRef<jobject>
+ConvertResourceRequestBodyToJavaObject(
+ JNIEnv* env,
+ const scoped_refptr<ResourceRequestBodyImpl>& native_object);
+
+// Reconstructs the native C++ content::ResourceRequestBody object based on
+// org.chromium.content_public.common.ResourceRequestBody (|java_object|) passed
+// in as an argument.
+scoped_refptr<ResourceRequestBodyImpl> ExtractResourceRequestBodyFromJavaObject(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& java_object);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_RESOURCE_REQUEST_BODY_JNI_H_
diff --git a/chromium/content/common/android/sync_compositor_messages.cc b/chromium/content/common/android/sync_compositor_messages.cc
index 7a2e4c1d230..f9be4b274ff 100644
--- a/chromium/content/common/android/sync_compositor_messages.cc
+++ b/chromium/content/common/android/sync_compositor_messages.cc
@@ -6,11 +6,6 @@
namespace content {
-SyncCompositorCommonBrowserParams::SyncCompositorCommonBrowserParams()
- : begin_frame_source_paused(false) {}
-
-SyncCompositorCommonBrowserParams::~SyncCompositorCommonBrowserParams() {}
-
SyncCompositorDemandDrawHwParams::SyncCompositorDemandDrawHwParams() {}
SyncCompositorDemandDrawHwParams::SyncCompositorDemandDrawHwParams(
@@ -43,7 +38,6 @@ SyncCompositorCommonRendererParams::SyncCompositorCommonRendererParams()
max_page_scale_factor(0.f),
need_animate_scroll(false),
need_invalidate_count(0u),
- need_begin_frame(false),
did_activate_pending_tree_count(0u) {}
SyncCompositorCommonRendererParams::~SyncCompositorCommonRendererParams() {}
diff --git a/chromium/content/common/android/sync_compositor_messages.h b/chromium/content/common/android/sync_compositor_messages.h
index 0f7bf23cd5d..62eafb7200e 100644
--- a/chromium/content/common/android/sync_compositor_messages.h
+++ b/chromium/content/common/android/sync_compositor_messages.h
@@ -22,13 +22,6 @@
namespace content {
-struct SyncCompositorCommonBrowserParams {
- SyncCompositorCommonBrowserParams();
- ~SyncCompositorCommonBrowserParams();
-
- bool begin_frame_source_paused;
-};
-
struct SyncCompositorDemandDrawHwParams {
SyncCompositorDemandDrawHwParams();
SyncCompositorDemandDrawHwParams(
@@ -77,7 +70,6 @@ struct SyncCompositorCommonRendererParams {
float max_page_scale_factor;
bool need_animate_scroll;
uint32_t need_invalidate_count;
- bool need_begin_frame;
uint32_t did_activate_pending_tree_count;
};
@@ -91,10 +83,6 @@ struct SyncCompositorCommonRendererParams {
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START SyncCompositorMsgStart
-IPC_STRUCT_TRAITS_BEGIN(content::SyncCompositorCommonBrowserParams)
- IPC_STRUCT_TRAITS_MEMBER(begin_frame_source_paused)
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_TRAITS_BEGIN(content::SyncCompositorDemandDrawHwParams)
IPC_STRUCT_TRAITS_MEMBER(surface_size)
IPC_STRUCT_TRAITS_MEMBER(transform)
@@ -125,7 +113,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::SyncCompositorCommonRendererParams)
IPC_STRUCT_TRAITS_MEMBER(max_page_scale_factor)
IPC_STRUCT_TRAITS_MEMBER(need_animate_scroll)
IPC_STRUCT_TRAITS_MEMBER(need_invalidate_count)
- IPC_STRUCT_TRAITS_MEMBER(need_begin_frame)
IPC_STRUCT_TRAITS_MEMBER(did_activate_pending_tree_count)
IPC_STRUCT_TRAITS_END()
@@ -133,48 +120,32 @@ IPC_STRUCT_TRAITS_END()
// Synchronous IPCs are allowed here to the renderer compositor thread. See
// design doc https://goo.gl/Tn81FW and crbug.com/526842 for details.
-IPC_SYNC_MESSAGE_ROUTED2_2(SyncCompositorMsg_HandleInputEvent,
- content::SyncCompositorCommonBrowserParams,
- IPC::WebInputEventPointer,
- content::SyncCompositorCommonRendererParams,
- content::InputEventAckState)
-
-IPC_SYNC_MESSAGE_ROUTED2_1(SyncCompositorMsg_BeginFrame,
- content::SyncCompositorCommonBrowserParams,
- cc::BeginFrameArgs,
+IPC_SYNC_MESSAGE_ROUTED0_1(SyncCompositorMsg_SynchronizeRendererState,
content::SyncCompositorCommonRendererParams)
-IPC_MESSAGE_ROUTED2(SyncCompositorMsg_ComputeScroll,
- content::SyncCompositorCommonBrowserParams,
+IPC_MESSAGE_ROUTED1(SyncCompositorMsg_ComputeScroll,
base::TimeTicks);
-IPC_SYNC_MESSAGE_ROUTED2_3(SyncCompositorMsg_DemandDrawHw,
- content::SyncCompositorCommonBrowserParams,
+IPC_SYNC_MESSAGE_ROUTED1_3(SyncCompositorMsg_DemandDrawHw,
content::SyncCompositorDemandDrawHwParams,
content::SyncCompositorCommonRendererParams,
uint32_t /* output_surface_id */,
cc::CompositorFrame)
-IPC_SYNC_MESSAGE_ROUTED2_2(SyncCompositorMsg_SetSharedMemory,
- content::SyncCompositorCommonBrowserParams,
+IPC_SYNC_MESSAGE_ROUTED1_2(SyncCompositorMsg_SetSharedMemory,
content::SyncCompositorSetSharedMemoryParams,
bool /* success */,
content::SyncCompositorCommonRendererParams);
IPC_MESSAGE_ROUTED0(SyncCompositorMsg_ZeroSharedMemory);
-IPC_SYNC_MESSAGE_ROUTED2_3(SyncCompositorMsg_DemandDrawSw,
- content::SyncCompositorCommonBrowserParams,
+IPC_SYNC_MESSAGE_ROUTED1_3(SyncCompositorMsg_DemandDrawSw,
content::SyncCompositorDemandDrawSwParams,
bool /* result */,
content::SyncCompositorCommonRendererParams,
cc::CompositorFrame)
-IPC_MESSAGE_ROUTED1(SyncCompositorMsg_UpdateState,
- content::SyncCompositorCommonBrowserParams)
-
-IPC_SYNC_MESSAGE_ROUTED3_1(SyncCompositorMsg_ZoomBy,
- content::SyncCompositorCommonBrowserParams,
+IPC_SYNC_MESSAGE_ROUTED2_1(SyncCompositorMsg_ZoomBy,
float /* delta */,
gfx::Point /* anchor */,
content::SyncCompositorCommonRendererParams)
@@ -195,7 +166,3 @@ IPC_MESSAGE_ROUTED0(SyncCompositorHostMsg_OutputSurfaceCreated);
IPC_MESSAGE_ROUTED1(SyncCompositorHostMsg_UpdateState,
content::SyncCompositorCommonRendererParams)
-
-IPC_MESSAGE_ROUTED2(SyncCompositorHostMsg_OverScroll,
- content::SyncCompositorCommonRendererParams,
- content::DidOverscrollParams)
diff --git a/chromium/content/common/application_setup.mojom b/chromium/content/common/application_setup.mojom
deleted file mode 100644
index 1a6b6985f78..00000000000
--- a/chromium/content/common/application_setup.mojom
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module content.mojom;
-
-import "services/shell/public/interfaces/interface_provider.mojom";
-
-interface ApplicationSetup {
- ExchangeInterfaceProviders(
- shell.mojom.InterfaceProvider& remote_interfaces,
- shell.mojom.InterfaceProvider local_interfaces);
-};
diff --git a/chromium/content/common/ax_content_node_data.cc b/chromium/content/common/ax_content_node_data.cc
index e71cd101efd..7dec9c68199 100644
--- a/chromium/content/common/ax_content_node_data.cc
+++ b/chromium/content/common/ax_content_node_data.cc
@@ -35,6 +35,10 @@ AXContentNodeData::AXContentNodeData() {
AXContentNodeData::AXContentNodeData(const AXContentNodeData& other) = default;
+AXContentNodeData::AXContentNodeData(const AXNodeData& other)
+ : AXNodeData(other) {
+}
+
AXContentNodeData::~AXContentNodeData() {
}
diff --git a/chromium/content/common/ax_content_node_data.h b/chromium/content/common/ax_content_node_data.h
index 93ab7191942..ae68d4f2a73 100644
--- a/chromium/content/common/ax_content_node_data.h
+++ b/chromium/content/common/ax_content_node_data.h
@@ -28,6 +28,7 @@ enum AXContentIntAttribute {
// content-layer-specific AX attributes.
struct CONTENT_EXPORT AXContentNodeData : public ui::AXNodeData {
AXContentNodeData();
+ AXContentNodeData(const AXNodeData& other);
AXContentNodeData(const AXContentNodeData& other);
~AXContentNodeData() override;
diff --git a/chromium/content/common/bluetooth/DEPS b/chromium/content/common/bluetooth/DEPS
deleted file mode 100644
index 2c5a329542a..00000000000
--- a/chromium/content/common/bluetooth/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+device/bluetooth",
-]
-
diff --git a/chromium/content/common/bluetooth/OWNERS b/chromium/content/common/bluetooth/OWNERS
deleted file mode 100644
index 8fb320057d8..00000000000
--- a/chromium/content/common/bluetooth/OWNERS
+++ /dev/null
@@ -1,16 +0,0 @@
-jyasskin@chromium.org
-ortuno@chromium.org
-scheib@chromium.org
-
-# For security review of IPC message files.
-per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/common/bluetooth/PRESUBMIT.py b/chromium/content/common/bluetooth/PRESUBMIT.py
deleted file mode 100644
index 3f9babedbd6..00000000000
--- a/chromium/content/common/bluetooth/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +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.
-
-"""Presubmit script.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
- results = []
- results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
- return results
diff --git a/chromium/content/common/bluetooth/bluetooth_device.cc b/chromium/content/common/bluetooth/bluetooth_device.cc
deleted file mode 100644
index 4b07d329f4d..00000000000
--- a/chromium/content/common/bluetooth/bluetooth_device.cc
+++ /dev/null
@@ -1,37 +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/common/bluetooth/bluetooth_device.h"
-
-#include "base/strings/string_util.h"
-
-namespace content {
-
-BluetoothDevice::BluetoothDevice()
- : id(""),
- name(base::string16()),
- uuids() {}
-
-BluetoothDevice::BluetoothDevice(
- const std::string& id,
- const base::string16& name,
- const std::vector<std::string>& uuids)
- : id(id),
- name(name),
- uuids(uuids) {}
-
-BluetoothDevice::~BluetoothDevice() {
-}
-
-// static
-std::vector<std::string> BluetoothDevice::UUIDsFromBluetoothUUIDs(
- const device::BluetoothDevice::UUIDList& uuid_list) {
- std::vector<std::string> uuids;
- uuids.reserve(uuid_list.size());
- for (const auto& it : uuid_list)
- uuids.push_back(it.canonical_value());
- return uuids;
-}
-
-} // namespace content
diff --git a/chromium/content/common/bluetooth/bluetooth_device.h b/chromium/content/common/bluetooth/bluetooth_device.h
deleted file mode 100644
index 5d731a96d1f..00000000000
--- a/chromium/content/common/bluetooth/bluetooth_device.h
+++ /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.
-
-#ifndef CONTENT_COMMON_BLUETOOTH_BLUETOOTH_DEVICE_H_
-#define CONTENT_COMMON_BLUETOOTH_BLUETOOTH_DEVICE_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/strings/string16.h"
-#include "content/common/content_export.h"
-#include "device/bluetooth/bluetooth_device.h"
-
-namespace content {
-
-// Data sent over IPC representing a Bluetooth device, corresponding to
-// blink::WebBluetoothDevice.
-struct CONTENT_EXPORT BluetoothDevice {
- BluetoothDevice();
- BluetoothDevice(const std::string& id,
- const base::string16& name,
- const std::vector<std::string>& uuids);
- ~BluetoothDevice();
-
- static std::vector<std::string> UUIDsFromBluetoothUUIDs(
- const device::BluetoothDevice::UUIDList& uuid_list);
-
- std::string id;
- base::string16 name;
- std::vector<std::string> uuids; // 128bit UUIDs with dashes. 36 chars.
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_BLUETOOTH_BLUETOOTH_DEVICE_H_
diff --git a/chromium/content/common/bluetooth/bluetooth_messages.h b/chromium/content/common/bluetooth/bluetooth_messages.h
deleted file mode 100644
index a51ebf1854f..00000000000
--- a/chromium/content/common/bluetooth/bluetooth_messages.h
+++ /dev/null
@@ -1,128 +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.
-
-// Messages for Web Bluetooth API.
-// Multiply-included message file, hence no include guard.
-
-// Web Bluetooth Security
-// The security mechanisms of Bluetooth are described in the specification:
-// https://webbluetoothchrome.github.io/web-bluetooth
-//
-// Exerpts:
-//
-// From: Security and privacy considerations
-// http://webbluetoothchrome.github.io/web-bluetooth/#security-and-privacy-considerations
-// """
-// When a website requests access to devices using requestDevice, it gets the
-// ability to access all GATT services mentioned in the call. The UA must inform
-// the user what capabilities these services give the website before asking
-// which devices to entrust to it. If any services in the list aren't known to
-// the UA, the UA must assume they give the site complete control over the
-// device and inform the user of this risk. The UA must also allow the user to
-// inspect what sites have access to what devices and revoke these pairings.
-//
-// The UA must not allow the user to pair entire classes of devices with a
-// website. It is possible to construct a class of devices for which each
-// individual device sends the same Bluetooth-level identifying information. UAs
-// are not required to attempt to detect this sort of forgery and may let a user
-// pair this pseudo-device with a website.
-//
-// To help ensure that only the entity the user approved for access actually has
-// access, this specification requires that only authenticated environments can
-// access Bluetooth devices (requestDevice).
-// """
-//
-// From: Per-origin Bluetooth device properties:
-// """
-// For each origin, the UA must maintain an allowed devices map, whose keys are
-// the Bluetooth devices the origin is allowed to access, and whose values are
-// pairs of a DOMString device id and an allowed services list consisting of
-// UUIDs for GATT Primary Services the origin is allowed to access on the
-// device.
-//
-// The UA may remove devices from the allowed devices map at any time based on
-// signals from the user. This needs a definition involving removing
-// BluetoothDevice instances from device instance maps and clearing out their
-// [[representedDevice]] fields. For example, if the user chooses not to
-// remember access, the UA might remove a device when the tab that was granted
-// access to it is closed. Or the UA might provide a revocation UI that allows
-// the user to explicitly remove a device even while a tab is actively using
-// that device. If a device is removed from this list while a Promise is pending
-// to do something with the device, it must be treated the same as if the device
-// moved out of Bluetooth range.
-// """
-//
-// From: Device Discovery: requestDevice
-// http://webbluetoothchrome.github.io/web-bluetooth/#device-discovery
-// """
-// Even if scanResult is empty, display a prompt to the user requesting that the
-// user select a device from it. The UA should show the user the human-readable
-// name of each device. If this name is not available because the UA's Bluetooth
-// system doesn't support privacy-enabled scans, the UA should allow the user to
-// indicate interest and then perform a privacy-disabled scan to retrieve the
-// name.
-//
-// The UA may allow the user to select a nearby device that does not match
-// filters.
-//
-// Wait for the user to have selected a device or cancelled the prompt.
-//
-// If the user cancels the prompt, reject promise with a NotFoundError and abort
-// these steps.
-//
-// Add device to the origin's allowed devices map. with the union of the service
-// UUIDs from filters and options.optionalServices as allowed services.
-//
-// Get the BluetoothDevice representing device and resolve promise with the
-// result.
-// """
-
-#include "ipc/ipc_message_macros.h"
-
-#include <stdint.h>
-
-#include "content/common/bluetooth/bluetooth_device.h"
-#include "content/common/bluetooth/bluetooth_scan_filter.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
-
-#define IPC_MESSAGE_START BluetoothMsgStart
-
-IPC_STRUCT_TRAITS_BEGIN(content::BluetoothDevice)
- IPC_STRUCT_TRAITS_MEMBER(id)
- IPC_STRUCT_TRAITS_MEMBER(name)
- IPC_STRUCT_TRAITS_MEMBER(uuids)
-IPC_STRUCT_TRAITS_END()
-
-IPC_ENUM_TRAITS_MAX_VALUE(blink::WebBluetoothError,
- blink::WebBluetoothError::ENUM_MAX_VALUE)
-
-IPC_STRUCT_TRAITS_BEGIN(content::BluetoothScanFilter)
-IPC_STRUCT_TRAITS_MEMBER(services)
-IPC_STRUCT_TRAITS_MEMBER(name)
-IPC_STRUCT_TRAITS_MEMBER(namePrefix)
-IPC_STRUCT_TRAITS_END()
-
-// Messages sent from the browser to the renderer.
-
-// Informs the renderer that the device request |request_id| succeeded.
-IPC_MESSAGE_CONTROL3(BluetoothMsg_RequestDeviceSuccess,
- int /* thread_id */,
- int /* request_id */,
- content::BluetoothDevice /* device */)
-
-// Informs the renderer that the device request |request_id| failed.
-IPC_MESSAGE_CONTROL3(BluetoothMsg_RequestDeviceError,
- int /* thread_id */,
- int /* request_id */,
- blink::WebBluetoothError /* result */)
-
-// Messages sent from the renderer to the browser.
-
-// Requests a bluetooth device from the browser.
-IPC_MESSAGE_CONTROL5(BluetoothHostMsg_RequestDevice,
- int /* thread_id */,
- int /* request_id */,
- int /* frame_routing_id */,
- std::vector<content::BluetoothScanFilter>,
- std::vector<device::BluetoothUUID> /* optional_services */)
diff --git a/chromium/content/common/bluetooth/bluetooth_scan_filter.cc b/chromium/content/common/bluetooth/bluetooth_scan_filter.cc
deleted file mode 100644
index 2c5a7cb87a9..00000000000
--- a/chromium/content/common/bluetooth/bluetooth_scan_filter.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/bluetooth/bluetooth_scan_filter.h"
-
-namespace content {
-
-BluetoothScanFilter::BluetoothScanFilter() : services() {
-}
-
-BluetoothScanFilter::BluetoothScanFilter(const BluetoothScanFilter& other) =
- default;
-
-BluetoothScanFilter::~BluetoothScanFilter() {
-}
-
-} // namespace content
diff --git a/chromium/content/common/bluetooth/bluetooth_scan_filter.h b/chromium/content/common/bluetooth/bluetooth_scan_filter.h
deleted file mode 100644
index 6c0bb3374e1..00000000000
--- a/chromium/content/common/bluetooth/bluetooth_scan_filter.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_BLUETOOTH_BLUETOOTH_SCAN_FILTER_H_
-#define CONTENT_COMMON_BLUETOOTH_BLUETOOTH_SCAN_FILTER_H_
-
-#include <string>
-#include <vector>
-
-#include "content/common/content_export.h"
-#include "device/bluetooth/bluetooth_uuid.h"
-
-namespace content {
-
-// Data sent over IPC representing a filter on Bluetooth scans, corresponding to
-// blink::WebBluetoothScanFilter.
-struct CONTENT_EXPORT BluetoothScanFilter {
- BluetoothScanFilter();
- BluetoothScanFilter(const BluetoothScanFilter& other);
- ~BluetoothScanFilter();
-
- std::vector<device::BluetoothUUID> services;
- std::string name;
- std::string namePrefix;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_BLUETOOTH_BLUETOOTH_DEVICE_H_
diff --git a/chromium/content/common/browser_plugin/OWNERS b/chromium/content/common/browser_plugin/OWNERS
index 1e6d75dcf89..eecf034561f 100644
--- a/chromium/content/common/browser_plugin/OWNERS
+++ b/chromium/content/common/browser_plugin/OWNERS
@@ -2,15 +2,5 @@ fsamuel@chromium.org
lazyboy@chromium.org
wjmaclean@chromium.org
-# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/browser_plugin/browser_plugin_messages.h b/chromium/content/common/browser_plugin/browser_plugin_messages.h
index 69907befc27..4161dafa06c 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_messages.h
+++ b/chromium/content/common/browser_plugin/browser_plugin_messages.h
@@ -20,7 +20,6 @@
#include "third_party/WebKit/public/platform/WebFocusType.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebDragStatus.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
diff --git a/chromium/content/common/cache_storage/OWNERS b/chromium/content/common/cache_storage/OWNERS
index 80517c24dba..0aa3aee8256 100644
--- a/chromium/content/common/cache_storage/OWNERS
+++ b/chromium/content/common/cache_storage/OWNERS
@@ -3,16 +3,5 @@ nhiroki@chromium.org
jkarlin@chromium.org
jsbell@chromium.org
-# Changes to IPC messages require a security review to avoid introducing
-# new sandbox escapes.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/child_process_host_impl.cc b/chromium/content/common/child_process_host_impl.cc
index 1aa93b52987..1dc475da372 100644
--- a/chromium/content/common/child_process_host_impl.cc
+++ b/chromium/content/common/child_process_host_impl.cc
@@ -29,8 +29,10 @@
#include "ipc/attachment_broker.h"
#include "ipc/attachment_broker_privileged.h"
#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_mojo.h"
#include "ipc/ipc_logging.h"
#include "ipc/message_filter.h"
+#include "mojo/edk/embedder/embedder.h"
#if defined(OS_LINUX)
#include "base/linux_util.h"
@@ -130,9 +132,31 @@ void ChildProcessHostImpl::ForceShutdown() {
Send(new ChildProcessMsg_Shutdown());
}
+std::string ChildProcessHostImpl::CreateChannelMojo(
+ const std::string& child_token) {
+ DCHECK(channel_id_.empty());
+ channel_id_ = mojo::edk::GenerateRandomToken();
+ mojo::ScopedMessagePipeHandle host_handle =
+ mojo::edk::CreateParentMessagePipe(channel_id_, child_token);
+ channel_ = IPC::ChannelMojo::Create(std::move(host_handle),
+ IPC::Channel::MODE_SERVER, this);
+ if (!channel_ || !InitChannel())
+ return std::string();
+
+ return channel_id_;
+}
+
std::string ChildProcessHostImpl::CreateChannel() {
+ DCHECK(channel_id_.empty());
channel_id_ = IPC::Channel::GenerateVerifiedChannelID(std::string());
channel_ = IPC::Channel::CreateServer(channel_id_, this);
+ if (!channel_ || !InitChannel())
+ return std::string();
+
+ return channel_id_;
+}
+
+bool ChildProcessHostImpl::InitChannel() {
#if USE_ATTACHMENT_BROKER
IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel(
channel_.get(), base::MessageLoopForIO::current()->task_runner());
@@ -142,7 +166,7 @@ std::string ChildProcessHostImpl::CreateChannel() {
IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel(
channel_.get());
#endif
- return std::string();
+ return false;
}
for (size_t i = 0; i < filters_.size(); ++i)
@@ -156,7 +180,7 @@ std::string ChildProcessHostImpl::CreateChannel() {
opening_channel_ = true;
- return channel_id_;
+ return true;
}
bool ChildProcessHostImpl::IsChannelOpening() {
diff --git a/chromium/content/common/child_process_host_impl.h b/chromium/content/common/child_process_host_impl.h
index 18875c94e67..686a7737319 100644
--- a/chromium/content/common/child_process_host_impl.h
+++ b/chromium/content/common/child_process_host_impl.h
@@ -79,6 +79,7 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
bool Send(IPC::Message* message) override;
void ForceShutdown() override;
std::string CreateChannel() override;
+ std::string CreateChannelMojo(const std::string& child_token) override;
bool IsChannelOpening() override;
void AddFilter(IPC::MessageFilter* filter) override;
#if defined(OS_POSIX)
@@ -109,6 +110,10 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
void OnDeletedGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
const gpu::SyncToken& sync_token);
+ // Initializes the IPC channel and returns true on success. |channel_| must be
+ // non-null.
+ bool InitChannel();
+
ChildProcessHostDelegate* delegate_;
base::Process peer_process_;
bool opening_channel_; // True while we're waiting the channel to be opened.
diff --git a/chromium/content/common/content_message_generator.h b/chromium/content/common/content_message_generator.h
index 5de191ce4fd..c9ed8ceda99 100644
--- a/chromium/content/common/content_message_generator.h
+++ b/chromium/content/common/content_message_generator.h
@@ -9,7 +9,6 @@
#include "build/build_config.h"
#include "content/common/accessibility_messages.h"
#include "content/common/appcache_messages.h"
-#include "content/common/bluetooth/bluetooth_messages.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/cache_storage/cache_storage_messages.h"
#include "content/common/clipboard_messages.h"
@@ -43,9 +42,7 @@
#include "content/common/media/webrtc_identity_messages.h"
#include "content/common/memory_messages.h"
#include "content/common/message_port_messages.h"
-#include "content/common/mime_registry_messages.h"
#include "content/common/page_messages.h"
-#include "content/common/pepper_messages.h"
#include "content/common/platform_notification_messages.h"
#include "content/common/power_monitor_messages.h"
#include "content/common/push_messaging_messages.h"
diff --git a/chromium/content/common/content_switches_internal.cc b/chromium/content/common/content_switches_internal.cc
index e3949845e3e..d4716f96def 100644
--- a/chromium/content/common/content_switches_internal.cc
+++ b/chromium/content/common/content_switches_internal.cc
@@ -7,6 +7,7 @@
#include <string>
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "build/build_config.h"
#include "content/public/common/content_switches.h"
@@ -19,9 +20,17 @@ namespace content {
namespace {
+#if defined(OS_WIN)
+const base::Feature kUseZoomForDsfEnabledByDefault {
+ "use-zoom-for-dsf enabled by default", base::FEATURE_ENABLED_BY_DEFAULT
+};
+#endif
+
bool IsUseZoomForDSFEnabledByDefault() {
#if defined(OS_CHROMEOS)
return true;
+#elif defined(OS_WIN)
+ return base::FeatureList::IsEnabled(kUseZoomForDsfEnabledByDefault);
#else
return false;
#endif
@@ -81,4 +90,24 @@ bool IsUseZoomForDSFEnabled() {
return enabled;
}
+ProgressBarCompletion GetProgressBarCompletionPolicy() {
+#if defined(OS_ANDROID)
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ std::string progress_bar_completion =
+ command_line.GetSwitchValueASCII(switches::kProgressBarCompletion);
+ if (progress_bar_completion == "loadEvent")
+ return ProgressBarCompletion::LOAD_EVENT;
+ if (progress_bar_completion == "resourcesBeforeDOMContentLoaded")
+ return ProgressBarCompletion::RESOURCES_BEFORE_DCL;
+ if (progress_bar_completion == "domContentLoaded")
+ return ProgressBarCompletion::DOM_CONTENT_LOADED;
+ if (progress_bar_completion ==
+ "resourcesBeforeDOMContentLoadedAndSameOriginIframes") {
+ return ProgressBarCompletion::RESOURCES_BEFORE_DCL_AND_SAME_ORIGIN_IFRAMES;
+ }
+#endif
+ return ProgressBarCompletion::LOAD_EVENT;
+}
+
} // namespace content
diff --git a/chromium/content/common/content_switches_internal.h b/chromium/content/common/content_switches_internal.h
index aacd9426e58..f1ddb19d4dc 100644
--- a/chromium/content/common/content_switches_internal.h
+++ b/chromium/content/common/content_switches_internal.h
@@ -18,6 +18,8 @@ bool IsWin32kRendererLockdownEnabled();
#endif
V8CacheOptions GetV8CacheOptions();
+ProgressBarCompletion GetProgressBarCompletionPolicy();
+
CONTENT_EXPORT bool IsUseZoomForDSFEnabled();
} // namespace content
diff --git a/chromium/content/common/database_messages.h b/chromium/content/common/database_messages.h
index 0e5c1f9c454..fa0ea266d57 100644
--- a/chromium/content/common/database_messages.h
+++ b/chromium/content/common/database_messages.h
@@ -9,6 +9,7 @@
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
#include "ipc/ipc_platform_file.h"
+#include "url/origin.h"
#define IPC_MESSAGE_START DatabaseMsgStart
@@ -16,22 +17,22 @@
// Notifies the child process of the new database size
IPC_MESSAGE_CONTROL3(DatabaseMsg_UpdateSize,
- std::string /* the origin */,
+ url::Origin /* the origin */,
base::string16 /* the database name */,
int64_t /* the new database size */)
// Notifies the child process of the new space available
IPC_MESSAGE_CONTROL2(DatabaseMsg_UpdateSpaceAvailable,
- std::string /* the origin */,
+ url::Origin /* the origin */,
int64_t /* space available to origin */)
// Notifies the child process to reset it's cached value for the origin.
IPC_MESSAGE_CONTROL1(DatabaseMsg_ResetSpaceAvailable,
- std::string /* the origin */)
+ url::Origin /* the origin */)
// Asks the child process to close a database immediately
IPC_MESSAGE_CONTROL2(DatabaseMsg_CloseImmediately,
- std::string /* the origin */,
+ url::Origin /* the origin */,
base::string16 /* the database name */)
// Database messages sent from the renderer to the browser.
@@ -60,7 +61,7 @@ IPC_SYNC_MESSAGE_CONTROL1_1(DatabaseHostMsg_GetFileSize,
// Asks the browser process for the amount of space available to an origin
IPC_SYNC_MESSAGE_CONTROL1_1(DatabaseHostMsg_GetSpaceAvailable,
- std::string /* origin identifier */,
+ url::Origin /* origin */,
int64_t /* remaining space available */)
// Asks the browser set the size of a DB file
@@ -71,23 +72,23 @@ IPC_SYNC_MESSAGE_CONTROL2_1(DatabaseHostMsg_SetFileSize,
// Notifies the browser process that a new database has been opened
IPC_MESSAGE_CONTROL4(DatabaseHostMsg_Opened,
- std::string /* origin identifier */,
+ url::Origin /* origin */,
base::string16 /* database name */,
base::string16 /* database description */,
int64_t /* estimated size */)
// Notifies the browser process that a database might have been modified
IPC_MESSAGE_CONTROL2(DatabaseHostMsg_Modified,
- std::string /* origin identifier */,
+ url::Origin /* origin */,
base::string16 /* database name */)
// Notifies the browser process that a database is about to close
IPC_MESSAGE_CONTROL2(DatabaseHostMsg_Closed,
- std::string /* origin identifier */,
+ url::Origin /* origin */,
base::string16 /* database name */)
// Sent when a sqlite error indicates the database is corrupt.
IPC_MESSAGE_CONTROL3(DatabaseHostMsg_HandleSqliteError,
- std::string /* origin identifier */,
+ url::Origin /* origin */,
base::string16 /* database name */,
- int /* error */)
+ int /* error */)
diff --git a/chromium/content/common/discardable_shared_memory_heap_unittest.cc b/chromium/content/common/discardable_shared_memory_heap_unittest.cc
index 6e4aac4197f..f391ff3d2ee 100644
--- a/chromium/content/common/discardable_shared_memory_heap_unittest.cc
+++ b/chromium/content/common/discardable_shared_memory_heap_unittest.cc
@@ -319,7 +319,8 @@ TEST(DiscardableSharedMemoryHeapTest, CreateMemoryAllocatorDumpTest) {
// Check if allocator dump is created when span exists.
std::unique_ptr<base::trace_event::ProcessMemoryDump> pmd(
- new base::trace_event::ProcessMemoryDump(nullptr));
+ new base::trace_event::ProcessMemoryDump(
+ nullptr, {base::trace_event::MemoryDumpLevelOfDetail::DETAILED}));
EXPECT_TRUE(heap.CreateMemoryAllocatorDump(span.get(), "discardable/test1",
pmd.get()));
diff --git a/chromium/content/common/dom_storage/OWNERS b/chromium/content/common/dom_storage/OWNERS
index 043f130dc03..924fa74bece 100644
--- a/chromium/content/common/dom_storage/OWNERS
+++ b/chromium/content/common/dom_storage/OWNERS
@@ -1,16 +1,5 @@
marja@chromium.org
michaeln@chromium.org
-# Changes to IPC messages require a security review to avoid introducing
-# new sandbox escapes.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/dom_storage/dom_storage_types.h b/chromium/content/common/dom_storage/dom_storage_types.h
index 4650f9bf4a3..e913aa80f95 100644
--- a/chromium/content/common/dom_storage/dom_storage_types.h
+++ b/chromium/content/common/dom_storage/dom_storage_types.h
@@ -35,9 +35,6 @@ const int64_t kLocalStorageNamespaceId = 0;
const int64_t kInvalidSessionStorageNamespaceId = kLocalStorageNamespaceId;
-// Start purging memory if the number of in-memory areas exceeds this.
-const int64_t kMaxInMemoryStorageAreas = 100;
-
} // namespace content
#endif // CONTENT_COMMON_DOM_STORAGE_DOM_STORAGE_TYPES_H_
diff --git a/chromium/content/common/drag_messages.h b/chromium/content/common/drag_messages.h
index c3e8e7ddfc2..0164368d9fe 100644
--- a/chromium/content/common/drag_messages.h
+++ b/chromium/content/common/drag_messages.h
@@ -5,6 +5,8 @@
// IPC messages for drag and drop.
// Multiply-included message file, hence no include guard.
+#include <vector>
+
#include "content/common/drag_event_source_info.h"
#include "content/public/common/drop_data.h"
#include "ipc/ipc_message_macros.h"
@@ -18,7 +20,7 @@
// Messages sent from the browser to the renderer.
IPC_MESSAGE_ROUTED5(DragMsg_TargetDragEnter,
- content::DropData /* drop_data */,
+ std::vector<content::DropData::Metadata> /* drop_data */,
gfx::Point /* client_pt */,
gfx::Point /* screen_pt */,
blink::WebDragOperationsMask /* ops_allowed */,
@@ -32,7 +34,8 @@ IPC_MESSAGE_ROUTED4(DragMsg_TargetDragOver,
IPC_MESSAGE_ROUTED0(DragMsg_TargetDragLeave)
-IPC_MESSAGE_ROUTED3(DragMsg_TargetDrop,
+IPC_MESSAGE_ROUTED4(DragMsg_TargetDrop,
+ content::DropData /* drop_data */,
gfx::Point /* client_pt */,
gfx::Point /* screen_pt */,
int /* key_modifiers */)
diff --git a/chromium/content/common/drag_traits.h b/chromium/content/common/drag_traits.h
index 0f22b5aef13..927881585f2 100644
--- a/chromium/content/common/drag_traits.h
+++ b/chromium/content/common/drag_traits.h
@@ -14,6 +14,8 @@
IPC_ENUM_TRAITS(blink::WebDragOperation) // Bitmask.
IPC_ENUM_TRAITS_MAX_VALUE(ui::DragDropTypes::DragEventSource,
ui::DragDropTypes::DRAG_EVENT_SOURCE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::DropData::Kind,
+ content::DropData::Kind::LAST)
IPC_STRUCT_TRAITS_BEGIN(ui::FileInfo)
IPC_STRUCT_TRAITS_MEMBER(path)
@@ -42,6 +44,13 @@ IPC_STRUCT_TRAITS_BEGIN(content::DropData::FileSystemFileInfo)
IPC_STRUCT_TRAITS_MEMBER(size)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::DropData::Metadata)
+ IPC_STRUCT_TRAITS_MEMBER(kind)
+ IPC_STRUCT_TRAITS_MEMBER(mime_type)
+ IPC_STRUCT_TRAITS_MEMBER(filename)
+ IPC_STRUCT_TRAITS_MEMBER(file_system_url)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::DragEventSourceInfo)
IPC_STRUCT_TRAITS_MEMBER(event_location)
IPC_STRUCT_TRAITS_MEMBER(event_source)
diff --git a/chromium/content/common/dwrite_text_analysis_source_win.cc b/chromium/content/common/dwrite_text_analysis_source_win.cc
deleted file mode 100644
index 19c6c54f599..00000000000
--- a/chromium/content/common/dwrite_text_analysis_source_win.cc
+++ /dev/null
@@ -1,82 +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/common/dwrite_text_analysis_source_win.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-TextAnalysisSource::TextAnalysisSource() = default;
-TextAnalysisSource::~TextAnalysisSource() = default;
-
-HRESULT TextAnalysisSource::GetLocaleName(UINT32 text_position,
- UINT32* text_length,
- const WCHAR** locale_name) {
- if (text_position >= text_.length() || !text_length || !locale_name)
- return E_INVALIDARG;
- *text_length = text_.length() - text_position;
- *locale_name = locale_name_.c_str();
- return S_OK;
-}
-
-HRESULT TextAnalysisSource::GetNumberSubstitution(
- UINT32 text_position,
- UINT32* text_length,
- IDWriteNumberSubstitution** number_substitution) {
- if (text_position >= text_.length() || !text_length || !number_substitution)
- return E_INVALIDARG;
- *text_length = text_.length() - text_position;
- number_substitution_.CopyTo(number_substitution);
- return S_OK;
-}
-
-DWRITE_READING_DIRECTION TextAnalysisSource::GetParagraphReadingDirection() {
- return reading_direction_;
-}
-
-HRESULT TextAnalysisSource::GetTextAtPosition(UINT32 text_position,
- const WCHAR** text_string,
- UINT32* text_length) {
- if (!text_length || !text_string)
- return E_INVALIDARG;
- if (text_position >= text_.length()) {
- *text_string = nullptr;
- *text_length = 0;
- return S_OK;
- }
- *text_string = text_.c_str() + text_position;
- *text_length = text_.length() - text_position;
- return S_OK;
-}
-
-HRESULT TextAnalysisSource::GetTextBeforePosition(UINT32 text_position,
- const WCHAR** text_string,
- UINT32* text_length) {
- if (!text_length || !text_string)
- return E_INVALIDARG;
- if (text_position < 1 || text_position > text_.length()) {
- *text_string = nullptr;
- *text_length = 0;
- return S_OK;
- }
- *text_string = text_.c_str();
- *text_length = text_position;
- return S_OK;
-}
-
-HRESULT TextAnalysisSource::RuntimeClassInitialize(
- const base::string16& text,
- const base::string16& locale_name,
- IDWriteNumberSubstitution* number_substitution,
- DWRITE_READING_DIRECTION reading_direction) {
- DCHECK(number_substitution);
- text_ = text;
- locale_name_ = locale_name;
- number_substitution_ = number_substitution;
- reading_direction_ = reading_direction;
- return S_OK;
-}
-
-} // namespace content
diff --git a/chromium/content/common/dwrite_text_analysis_source_win.h b/chromium/content/common/dwrite_text_analysis_source_win.h
deleted file mode 100644
index 2999e43af77..00000000000
--- a/chromium/content/common/dwrite_text_analysis_source_win.h
+++ /dev/null
@@ -1,64 +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_COMMON_DWRITE_TEXT_ANALYSIS_SOURCE_WIN_H_
-#define CONTENT_COMMON_DWRITE_TEXT_ANALYSIS_SOURCE_WIN_H_
-
-#include <dwrite.h>
-#include <wrl.h>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// Implements an IDWriteTextAnalysisSource, describing a single pre-defined
-// chunk of text with a uniform locale, reading direction, and number
-// substitution.
-class CONTENT_EXPORT TextAnalysisSource
- : public Microsoft::WRL::RuntimeClass<
- Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
- IDWriteTextAnalysisSource> {
- public:
- TextAnalysisSource();
-
- // IDWriteTextAnalysisSource:
- HRESULT STDMETHODCALLTYPE GetLocaleName(UINT32 text_position,
- UINT32* text_length,
- const WCHAR** locale_name) override;
- HRESULT STDMETHODCALLTYPE GetNumberSubstitution(
- UINT32 text_position,
- UINT32* text_length,
- IDWriteNumberSubstitution** number_substitution) override;
- DWRITE_READING_DIRECTION STDMETHODCALLTYPE
- GetParagraphReadingDirection() override;
- HRESULT STDMETHODCALLTYPE GetTextAtPosition(UINT32 text_position,
- const WCHAR** text_string,
- UINT32* text_length) override;
- HRESULT STDMETHODCALLTYPE GetTextBeforePosition(UINT32 text_position,
- const WCHAR** text_string,
- UINT32* text_length) override;
-
- HRESULT STDMETHODCALLTYPE
- RuntimeClassInitialize(const base::string16& text,
- const base::string16& locale_name,
- IDWriteNumberSubstitution* number_substitution,
- DWRITE_READING_DIRECTION reading_direction);
-
- protected:
- ~TextAnalysisSource() override;
-
- private:
- base::string16 text_;
- base::string16 locale_name_;
- Microsoft::WRL::ComPtr<IDWriteNumberSubstitution> number_substitution_;
- DWRITE_READING_DIRECTION reading_direction_;
-
- DISALLOW_ASSIGN(TextAnalysisSource);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_DWRITE_TEXT_ANALYSIS_SOURCE_WIN_H_
diff --git a/chromium/content/common/external_ipc_dumper.cc b/chromium/content/common/external_ipc_dumper.cc
new file mode 100644
index 00000000000..907ebfd9c52
--- /dev/null
+++ b/chromium/content/common/external_ipc_dumper.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 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 "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/native_library.h"
+#include "base/path_service.h"
+#include "build/build_config.h"
+#include "content/common/external_ipc_dumper.h"
+
+namespace {
+
+typedef IPC::ChannelProxy::OutgoingMessageFilter* (*GetFilterFunction)();
+typedef void (*SetDumpDirectoryFunction)(const base::FilePath&);
+
+const char kFilterEntryName[] = "GetFilter";
+const char kSetDumpDirectoryEntryName[] = "SetDumpDirectory";
+
+#if defined(OS_WIN)
+#define IPC_MESSAGE_DUMP_MODULE FILE_PATH_LITERAL("ipc_message_dump.dll")
+#else
+#define IPC_MESSAGE_DUMP_MODULE FILE_PATH_LITERAL("libipc_message_dump.so")
+#endif
+
+} // namespace
+
+namespace content {
+
+IPC::ChannelProxy::OutgoingMessageFilter* LoadExternalIPCDumper(
+ const base::FilePath& dump_directory) {
+ base::FilePath module_path;
+ if (!PathService::Get(base::DIR_MODULE, &module_path)) {
+ LOG(ERROR) << "Unable to get message dump module directory.";
+ return NULL;
+ }
+
+ base::FilePath library_path = module_path.Append(IPC_MESSAGE_DUMP_MODULE);
+ base::NativeLibraryLoadError load_error;
+ base::NativeLibrary library =
+ base::LoadNativeLibrary(library_path, &load_error);
+
+ if (!library) {
+ LOG(ERROR) << load_error.ToString();
+ return NULL;
+ }
+
+ SetDumpDirectoryFunction set_directory_entry_point =
+ reinterpret_cast<SetDumpDirectoryFunction>(
+ base::GetFunctionPointerFromNativeLibrary(
+ library, kSetDumpDirectoryEntryName));
+ if (!set_directory_entry_point) {
+ LOG(ERROR) << kSetDumpDirectoryEntryName
+ << " not exported by message dump module.";
+ return NULL;
+ }
+ set_directory_entry_point(dump_directory);
+
+ GetFilterFunction filter_entry_point = reinterpret_cast<GetFilterFunction>(
+ base::GetFunctionPointerFromNativeLibrary(library, kFilterEntryName));
+ if (!filter_entry_point) {
+ LOG(ERROR) << kFilterEntryName << " not exported by message dump module.";
+ return NULL;
+ }
+
+ return filter_entry_point();
+}
+
+} // namespace content
diff --git a/chromium/content/common/external_ipc_dumper.h b/chromium/content/common/external_ipc_dumper.h
new file mode 100644
index 00000000000..809761d4820
--- /dev/null
+++ b/chromium/content/common/external_ipc_dumper.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_EXTERNAL_IPC_DUMPER_H_
+#define CONTENT_COMMON_EXTERNAL_IPC_DUMPER_H_
+
+#include "ipc/ipc_channel_proxy.h"
+
+namespace content {
+
+IPC::ChannelProxy::OutgoingMessageFilter* LoadExternalIPCDumper(
+ const base::FilePath& dump_directory);
+
+} // namespace content
+
+#endif // CONTENT_COMMON_EXTERNAL_IPC_DUMPER_H_
diff --git a/chromium/content/common/fileapi/OWNERS b/chromium/content/common/fileapi/OWNERS
index 4d4319a2c31..f848bb15a13 100644
--- a/chromium/content/common/fileapi/OWNERS
+++ b/chromium/content/common/fileapi/OWNERS
@@ -3,15 +3,5 @@ jianli@chromium.org
tzik@chromium.org
nhiroki@chromium.org
-# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/font_config_ipc_linux.cc b/chromium/content/common/font_config_ipc_linux.cc
index fff2fb95c89..0c65468b75d 100644
--- a/chromium/content/common/font_config_ipc_linux.cc
+++ b/chromium/content/common/font_config_ipc_linux.cc
@@ -15,6 +15,7 @@
#include <functional>
#include <memory>
+#include <utility>
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
@@ -23,9 +24,9 @@
#include "base/posix/unix_domain_socket_linux.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
-#include "skia/ext/refptr.h"
#include "skia/ext/skia_utils_base.h"
#include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
@@ -123,13 +124,13 @@ SkMemoryStream* FontConfigIPC::mapFileDescriptorToStream(int fd) {
mapped_font_file->Initialize(base::File(fd));
DCHECK(mapped_font_file->IsValid());
- auto data = skia::AdoptRef(
- SkData::NewWithProc(mapped_font_file->data(), mapped_font_file->length(),
- &DestroyMemoryMappedFile, mapped_font_file.get()));
+ sk_sp<SkData> data =
+ SkData::MakeWithProc(mapped_font_file->data(), mapped_font_file->length(),
+ &DestroyMemoryMappedFile, mapped_font_file.get());
if (!data)
return nullptr;
ignore_result(mapped_font_file.release()); // Ownership transferred to SkDataB
- return new SkMemoryStream(data.get());
+ return new SkMemoryStream(std::move(data));
}
SkStreamAsset* FontConfigIPC::openStream(const FontIdentity& identity) {
@@ -158,21 +159,21 @@ SkStreamAsset* FontConfigIPC::openStream(const FontIdentity& identity) {
return mapFileDescriptorToStream(result_fd);
}
-SkTypeface* FontConfigIPC::createTypeface(
+sk_sp<SkTypeface> FontConfigIPC::makeTypeface(
const SkFontConfigInterface::FontIdentity& identity) {
base::AutoLock lock(lock_);
auto mapped_typefaces_it = mapped_typefaces_.Get(identity);
if (mapped_typefaces_it != mapped_typefaces_.end())
- return SkSafeRef(mapped_typefaces_it->second.get());
+ return mapped_typefaces_it->second;
SkStreamAsset* typeface_stream = openStream(identity);
if (!typeface_stream)
return nullptr;
- skia::RefPtr<SkTypeface> typeface_from_stream = skia::AdoptRef(
- SkTypeface::CreateFromStream(typeface_stream, identity.fTTCIndex));
+ sk_sp<SkTypeface> typeface_from_stream(
+ SkTypeface::MakeFromStream(typeface_stream, identity.fTTCIndex));
auto mapped_typefaces_insert_it =
- mapped_typefaces_.Put(identity, typeface_from_stream);
- return SkSafeRef(mapped_typefaces_insert_it->second.get());
+ mapped_typefaces_.Put(identity, std::move(typeface_from_stream));
+ return mapped_typefaces_insert_it->second;
}
} // namespace content
diff --git a/chromium/content/common/font_config_ipc_linux.h b/chromium/content/common/font_config_ipc_linux.h
index 59a4b0f4338..258c2002083 100644
--- a/chromium/content/common/font_config_ipc_linux.h
+++ b/chromium/content/common/font_config_ipc_linux.h
@@ -9,7 +9,7 @@
#include "base/containers/mru_cache.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
-#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
@@ -41,7 +41,7 @@ class FontConfigIPC : public SkFontConfigInterface {
// Returns a new SkTypeface instance or a ref'ed one from the cache. The
// caller should adopt the pointer.
- SkTypeface* createTypeface(const FontIdentity& identity) override
+ sk_sp<SkTypeface> makeTypeface(const FontIdentity& identity) override
WARN_UNUSED_RESULT;
enum Method {
@@ -71,7 +71,7 @@ class FontConfigIPC : public SkFontConfigInterface {
// frequency of ttc indices is very low, and style is not used by clients of
// this API, this seems okay.
base::HashingMRUCache<FontIdentity,
- skia::RefPtr<SkTypeface>,
+ sk_sp<SkTypeface>,
SkFontConfigInterfaceFontIdentityHash>
mapped_typefaces_;
diff --git a/chromium/content/common/font_list_pango.cc b/chromium/content/common/font_list_pango.cc
index d64c9033a0c..f7d82fc5a22 100644
--- a/chromium/content/common/font_list_pango.cc
+++ b/chromium/content/common/font_list_pango.cc
@@ -9,6 +9,7 @@
#include <set>
#include <string>
+#include <utility>
#include "base/values.h"
@@ -30,11 +31,11 @@ std::unique_ptr<base::ListValue> GetFontList_SlowBlocking() {
for (std::set<std::string>::const_iterator iter = sorted_families.begin();
iter != sorted_families.end(); ++iter) {
- base::ListValue* font_item = new base::ListValue();
- font_item->Append(new base::StringValue(*iter));
- font_item->Append(new base::StringValue(*iter)); // localized name.
+ std::unique_ptr<base::ListValue> font_item(new base::ListValue());
+ font_item->AppendString(*iter);
+ font_item->AppendString(*iter); // localized name.
// TODO(yusukes): Support localized family names.
- font_list->Append(font_item);
+ font_list->Append(std::move(font_item));
}
return font_list;
diff --git a/chromium/content/common/frame.mojom b/chromium/content/common/frame.mojom
new file mode 100644
index 00000000000..9ec96441b37
--- /dev/null
+++ b/chromium/content/common/frame.mojom
@@ -0,0 +1,23 @@
+// 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.
+
+module content.mojom;
+
+import "services/shell/public/interfaces/interface_provider.mojom";
+
+// Implemented by the frame provider (e.g. renderer processes).
+interface Frame {
+ GetInterfaceProvider(shell.mojom.InterfaceProvider& interfaces);
+};
+
+// Implemented by the frame server (i.e. the browser process).
+interface FrameHost {
+ GetInterfaceProvider(shell.mojom.InterfaceProvider& interfaces);
+};
+
+// Implemented by a service that provides implementations of the Frame
+// interface. (e.g. renderer processes).
+interface FrameFactory {
+ CreateFrame(int32 frame_routing_id, Frame& frame, FrameHost host);
+};
diff --git a/chromium/content/common/frame_messages.h b/chromium/content/common/frame_messages.h
index a518fd476f7..2e53dc5d387 100644
--- a/chromium/content/common/frame_messages.h
+++ b/chromium/content/common/frame_messages.h
@@ -23,15 +23,15 @@
#include "content/common/frame_replication_state.h"
#include "content/common/navigation_gesture.h"
#include "content/common/navigation_params.h"
-#include "content/common/resource_request_body.h"
#include "content/common/savable_subframe.h"
#include "content/public/common/color_suggestion.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/console_message_level.h"
#include "content/public/common/context_menu_params.h"
+#include "content/public/common/file_chooser_file_info.h"
+#include "content/public/common/file_chooser_params.h"
#include "content/public/common/frame_navigate_params.h"
#include "content/public/common/javascript_message_type.h"
-#include "content/public/common/mhtml_generation_params.h"
#include "content/public/common/page_importance_signals.h"
#include "content/public/common/page_state.h"
#include "content/public/common/resource_response.h"
@@ -41,8 +41,10 @@
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
#include "third_party/WebKit/public/platform/WebFocusType.h"
+#include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
+#include "third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h"
#include "third_party/WebKit/public/web/WebTreeScopeType.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -100,6 +102,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(ui::MenuSourceType, ui::MENU_SOURCE_TYPE_LAST)
IPC_ENUM_TRAITS_MIN_MAX_VALUE(content::LoFiState,
content::LOFI_UNSPECIFIED,
content::LOFI_ON)
+IPC_ENUM_TRAITS_MAX_VALUE(content::FileChooserParams::Mode,
+ content::FileChooserParams::Save)
IPC_STRUCT_TRAITS_BEGIN(blink::WebFindOptions)
IPC_STRUCT_TRAITS_MEMBER(forward)
@@ -163,6 +167,7 @@ IPC_STRUCT_TRAITS_BEGIN(blink::WebFrameOwnerProperties)
IPC_STRUCT_TRAITS_MEMBER(scrollingMode)
IPC_STRUCT_TRAITS_MEMBER(marginWidth)
IPC_STRUCT_TRAITS_MEMBER(marginHeight)
+ IPC_STRUCT_TRAITS_MEMBER(allowFullscreen)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::TransitionElement)
@@ -289,9 +294,8 @@ IPC_STRUCT_BEGIN_WITH_PARENT(FrameHostMsg_DidCommitProvisionalLoad_Params,
// Timestamp at which the UI action that triggered the navigation originated.
IPC_STRUCT_MEMBER(base::TimeTicks, ui_timestamp)
- // True if the document for the load is enforcing strict mixed content
- // checking.
- IPC_STRUCT_MEMBER(bool, should_enforce_strict_mixed_content_checking)
+ // The insecure request policy the document for the load is enforcing.
+ IPC_STRUCT_MEMBER(blink::WebInsecureRequestPolicy, insecure_request_policy)
// True if the document for the load is a unique origin that should be
// considered potentially trustworthy.
@@ -340,6 +344,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(lofi_state)
IPC_STRUCT_TRAITS_MEMBER(navigation_start)
IPC_STRUCT_TRAITS_MEMBER(method)
+ IPC_STRUCT_TRAITS_MEMBER(post_data)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::BeginNavigationParams)
@@ -352,7 +357,6 @@ IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::StartNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(extra_headers)
- IPC_STRUCT_TRAITS_MEMBER(browser_initiated_post_data)
#if defined(OS_ANDROID)
IPC_STRUCT_TRAITS_MEMBER(has_user_gesture)
#endif
@@ -377,7 +381,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::RequestNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(is_view_source)
IPC_STRUCT_TRAITS_MEMBER(should_clear_history_list)
IPC_STRUCT_TRAITS_MEMBER(should_create_service_worker)
- IPC_STRUCT_TRAITS_MEMBER(service_worker_provider_id)
#if defined(OS_ANDROID)
IPC_STRUCT_TRAITS_MEMBER(data_url_as_string)
#endif
@@ -390,7 +393,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::FrameReplicationState)
IPC_STRUCT_TRAITS_MEMBER(unique_name)
IPC_STRUCT_TRAITS_MEMBER(accumulated_csp_headers)
IPC_STRUCT_TRAITS_MEMBER(scope)
- IPC_STRUCT_TRAITS_MEMBER(should_enforce_strict_mixed_content_checking)
+ IPC_STRUCT_TRAITS_MEMBER(insecure_request_policy)
IPC_STRUCT_TRAITS_MEMBER(has_potentially_trustworthy_unique_origin)
IPC_STRUCT_TRAITS_END()
@@ -448,6 +451,9 @@ IPC_STRUCT_END()
// the browser process should look for an existing history item for the frame.
IPC_STRUCT_BEGIN(FrameHostMsg_OpenURL_Params)
IPC_STRUCT_MEMBER(GURL, url)
+ IPC_STRUCT_MEMBER(bool, uses_post)
+ IPC_STRUCT_MEMBER(scoped_refptr<content::ResourceRequestBodyImpl>,
+ resource_request_body)
IPC_STRUCT_MEMBER(content::Referrer, referrer)
IPC_STRUCT_MEMBER(WindowOpenDisposition, disposition)
IPC_STRUCT_MEMBER(bool, should_replace_current_entry)
@@ -503,7 +509,7 @@ IPC_STRUCT_BEGIN(FrameMsg_SerializeAsMHTML_Params)
// intended for sharing.
IPC_STRUCT_MEMBER(bool, mhtml_binary_encoding)
- IPC_STRUCT_MEMBER(content::MHTMLCacheControlPolicy,
+ IPC_STRUCT_MEMBER(blink::WebFrameSerializerCacheControlPolicy,
mhtml_cache_control_policy)
// Frame to content-id map.
@@ -553,7 +559,28 @@ IPC_STRUCT_TRAITS_BEGIN(content::ContentSecurityPolicyHeader)
IPC_STRUCT_TRAITS_MEMBER(source)
IPC_STRUCT_TRAITS_END()
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+IPC_STRUCT_TRAITS_BEGIN(content::FileChooserFileInfo)
+ IPC_STRUCT_TRAITS_MEMBER(file_path)
+ IPC_STRUCT_TRAITS_MEMBER(display_name)
+ IPC_STRUCT_TRAITS_MEMBER(file_system_url)
+ IPC_STRUCT_TRAITS_MEMBER(modification_time)
+ IPC_STRUCT_TRAITS_MEMBER(length)
+ IPC_STRUCT_TRAITS_MEMBER(is_directory)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::FileChooserParams)
+ IPC_STRUCT_TRAITS_MEMBER(mode)
+ IPC_STRUCT_TRAITS_MEMBER(title)
+ IPC_STRUCT_TRAITS_MEMBER(default_file_name)
+ IPC_STRUCT_TRAITS_MEMBER(accept_types)
+ IPC_STRUCT_TRAITS_MEMBER(need_local_path)
+#if defined(OS_ANDROID)
+ IPC_STRUCT_TRAITS_MEMBER(capture)
+#endif
+ IPC_STRUCT_TRAITS_MEMBER(requestor)
+IPC_STRUCT_TRAITS_END()
+
+#if defined(USE_EXTERNAL_POPUP_MENU)
// This message is used for supporting popup menus on Mac OS X and Android using
// native controls. See the FrameHostMsg_ShowPopup message.
IPC_STRUCT_BEGIN(FrameHostMsg_ShowPopup_Params)
@@ -655,7 +682,7 @@ IPC_MESSAGE_ROUTED3(FrameMsg_Navigate,
// Instructs the renderer to invoke the frame's beforeunload event handler.
// Expects the result to be returned via FrameHostMsg_BeforeUnload_ACK.
-IPC_MESSAGE_ROUTED0(FrameMsg_BeforeUnload)
+IPC_MESSAGE_ROUTED1(FrameMsg_BeforeUnload, bool /* is_reload */)
// Instructs the frame to swap out for a cross-site transition, including
// running the unload event handler and creating a RenderFrameProxy with the
@@ -784,11 +811,10 @@ IPC_MESSAGE_ROUTED1(FrameMsg_AddContentSecurityPolicy,
// Resets ContentSecurityPolicy in a frame proxy / in RemoteSecurityContext.
IPC_MESSAGE_ROUTED0(FrameMsg_ResetContentSecurityPolicy)
-// Update a proxy's replicated enforcement of strict mixed content
-// checking. Used when the frame's mixed content setting is changed in
-// another process.
-IPC_MESSAGE_ROUTED1(FrameMsg_EnforceStrictMixedContentChecking,
- bool /* should enforce */)
+// Update a proxy's replicated enforcement of insecure request policy.
+// Used when the frame's policy is changed in another process.
+IPC_MESSAGE_ROUTED1(FrameMsg_EnforceInsecureRequestPolicy,
+ blink::WebInsecureRequestPolicy)
// Update a proxy's replicated origin. Used when the frame is navigated to a
// new origin.
@@ -800,6 +826,12 @@ IPC_MESSAGE_ROUTED2(FrameMsg_DidUpdateOrigin,
// support cross-process focused frame changes.
IPC_MESSAGE_ROUTED0(FrameMsg_SetFocusedFrame)
+// Sent to a frame proxy when its real frame is preparing to enter fullscreen
+// in another process. Actually entering fullscreen will be done separately as
+// part of ViewMsg_Resize, once the browser process has resized the tab for
+// fullscreen.
+IPC_MESSAGE_ROUTED0(FrameMsg_WillEnterFullscreen)
+
// Send to the RenderFrame to set text tracks state and style settings.
// Sent for top-level frames.
IPC_MESSAGE_ROUTED1(FrameMsg_SetTextTrackSettings,
@@ -809,6 +841,24 @@ IPC_MESSAGE_ROUTED1(FrameMsg_SetTextTrackSettings,
IPC_MESSAGE_ROUTED1(FrameMsg_PostMessageEvent, FrameMsg_PostMessage_Params)
#if defined(OS_ANDROID)
+// Request the distance to the nearest find result in a frame from the point at
+// (x, y), defined in fractions of the content document's width and height. The
+// distance will be returned via FrameHostMsg_GetNearestFindResult_Reply. Note
+// that |nfr_request_id| is a completely seperate ID from the |request_id| used
+// in other find-related IPCs. It is specifically used to uniquely identify a
+// nearest find result request, rather than a find request.
+IPC_MESSAGE_ROUTED3(FrameMsg_GetNearestFindResult,
+ int /* nfr_request_id */,
+ float /* x */,
+ float /* y */)
+
+// Activates a find result. The point (x,y) is in fractions of the content
+// document's width and height.
+IPC_MESSAGE_ROUTED3(FrameMsg_ActivateNearestFindResult,
+ int /* request_id */,
+ float /* x */,
+ float /* y */)
+
// Sent when the browser wants the bounding boxes of the current find matches.
//
// If match rects are already cached on the browser side, |current_version|
@@ -820,18 +870,17 @@ IPC_MESSAGE_ROUTED1(FrameMsg_PostMessageEvent, FrameMsg_PostMessage_Params)
// this immediately after a FrameHostMsg_Find_Reply message arrives with
// final_update set to true).
IPC_MESSAGE_ROUTED1(FrameMsg_FindMatchRects, int /* current_version */)
+#endif
-// External popup menus.
+#if defined(USE_EXTERNAL_POPUP_MENU)
+#if defined(OS_MACOSX)
+IPC_MESSAGE_ROUTED1(FrameMsg_SelectPopupMenuItem,
+ int /* selected index, -1 means no selection */)
+#else
IPC_MESSAGE_ROUTED2(FrameMsg_SelectPopupMenuItems,
bool /* user canceled the popup */,
std::vector<int> /* selected indices */)
-
-#elif defined(OS_MACOSX)
-
-// External popup menus.
-IPC_MESSAGE_ROUTED1(FrameMsg_SelectPopupMenuItem,
- int /* selected index, -1 means no selection */)
-
+#endif
#endif
// PlzNavigate
@@ -839,10 +888,10 @@ IPC_MESSAGE_ROUTED1(FrameMsg_SelectPopupMenuItem,
// request |stream_url| to get access to the stream containing the body of the
// response.
IPC_MESSAGE_ROUTED4(FrameMsg_CommitNavigation,
- content::ResourceResponseHead, /* response */
- GURL, /* stream_url */
- content::CommonNavigationParams, /* common_params */
- content::RequestNavigationParams /* request_params */)
+ content::ResourceResponseHead, /* response */
+ GURL, /* stream_url */
+ content::CommonNavigationParams, /* common_params */
+ content::RequestNavigationParams) /* request_params */
// PlzNavigate
// Tells the renderer that a navigation failed with the error code |error_code|
@@ -887,14 +936,37 @@ IPC_MESSAGE_ROUTED3(FrameMsg_Find,
base::string16 /* search_text */,
blink::WebFindOptions)
-// This message notifies the renderer that the user has closed the find-in-page
+// This message notifies the frame that it is no longer the active frame in the
+// current find session, and so it should clear its active find match (and no
+// longer highlight it with special coloring).
+IPC_MESSAGE_ROUTED0(FrameMsg_ClearActiveFindMatch)
+
+// This message notifies the frame that the user has closed the find-in-page
// window (and what action to take regarding the selection).
IPC_MESSAGE_ROUTED1(FrameMsg_StopFinding, content::StopFindAction /* action */)
+// Copies the image at location x, y to the clipboard (if there indeed is an
+// image at that location).
+IPC_MESSAGE_ROUTED2(FrameMsg_CopyImageAt,
+ int /* x */,
+ int /* y */)
+
+// Saves the image at location x, y to the disk (if there indeed is an
+// image at that location).
+IPC_MESSAGE_ROUTED2(FrameMsg_SaveImageAt,
+ int /* x */,
+ int /* y */)
+
#if defined(ENABLE_PLUGINS)
// Notifies the renderer of updates to the Plugin Power Saver origin whitelist.
IPC_MESSAGE_ROUTED1(FrameMsg_UpdatePluginContentOriginWhitelist,
std::set<url::Origin> /* origin_whitelist */)
+
+// This message notifies that the frame that the volume of the Pepper instance
+// for |pp_instance| should be changed to |volume|.
+IPC_MESSAGE_ROUTED2(FrameMsg_SetPepperVolume,
+ int32_t /* pp_instance */,
+ double /* volume */)
#endif // defined(ENABLE_PLUGINS)
// Used to instruct the RenderFrame to go into "view source" mode. This should
@@ -905,6 +977,9 @@ IPC_MESSAGE_ROUTED0(FrameMsg_EnableViewSourceMode)
// ScopedPageLoadDeferrer is on the stack for SwapOut.
IPC_MESSAGE_ROUTED0(FrameMsg_SuppressFurtherDialogs)
+IPC_MESSAGE_ROUTED1(FrameMsg_RunFileChooserResponse,
+ std::vector<content::FileChooserFileInfo>)
+
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
@@ -987,12 +1062,12 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_DidChangeName,
IPC_MESSAGE_ROUTED1(FrameHostMsg_DidAddContentSecurityPolicy,
content::ContentSecurityPolicyHeader)
-// Sent when the frame starts enforcing strict mixed content
-// checking. Sending this information in DidCommitProvisionalLoad isn't
-// sufficient; this message is needed because, for example, a document
-// can dynamically insert a <meta> tag that causes strict mixed content
-// checking to be enforced.
-IPC_MESSAGE_ROUTED0(FrameHostMsg_EnforceStrictMixedContentChecking)
+// Sent when the frame starts enforcing an insecure request policy. Sending
+// this information in DidCommitProvisionalLoad isn't sufficient; this
+// message is needed because, for example, a document can dynamically insert
+// a <meta> tag that causes strict mixed content checking to be enforced.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_EnforceInsecureRequestPolicy,
+ blink::WebInsecureRequestPolicy)
// Sent when the frame is set to a unique origin. TODO(estark): this IPC
// only exists to support dynamic sandboxing via a CSP delivered in a
@@ -1012,6 +1087,22 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_OpenURL, FrameHostMsg_OpenURL_Params)
IPC_MESSAGE_ROUTED1(FrameHostMsg_DidFinishLoad,
GURL /* validated_url */)
+// Initiates a download based on user actions like 'ALT+click'.
+IPC_MESSAGE_CONTROL5(FrameHostMsg_DownloadUrl,
+ int /* render_view_id */,
+ int /* render_frame_id */,
+ GURL /* url */,
+ content::Referrer /* referrer */,
+ base::string16 /* suggested_name */)
+
+// Asks the browser to save a image (for <canvas> or <img>) from a data URL.
+// Note: |data_url| is the contents of a data:URL, and that it's represented as
+// a string only to work around size limitations for GURLs in IPC messages.
+IPC_MESSAGE_CONTROL3(FrameHostMsg_SaveImageFromDataURL,
+ int /* render_view_id */,
+ int /* render_frame_id */,
+ std::string /* data_url */)
+
// Sent when after the onload handler has been invoked for the document
// in this frame. Sent for top-level frames. |report_type| and |ui_timestamp|
// are used to report navigation metrics starting on the ui input event that
@@ -1344,10 +1435,9 @@ IPC_MESSAGE_ROUTED5(FrameHostMsg_DidLoadResourceFromMemoryCache,
// PlzNavigate
// Tells the browser to perform a navigation.
-IPC_MESSAGE_ROUTED3(FrameHostMsg_BeginNavigation,
+IPC_MESSAGE_ROUTED2(FrameHostMsg_BeginNavigation,
content::CommonNavigationParams,
- content::BeginNavigationParams,
- scoped_refptr<content::ResourceRequestBody>)
+ content::BeginNavigationParams)
// Sent as a response to FrameMsg_VisualStateRequest.
// The message is delivered using RenderWidget::QueueMessage.
@@ -1438,7 +1528,11 @@ IPC_MESSAGE_ROUTED5(FrameHostMsg_Find_Reply,
// Sends hittesting data needed to perform hittesting on the browser process.
IPC_MESSAGE_ROUTED1(FrameHostMsg_HittestData, FrameHostMsg_HittestData_Params)
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+// Asks the browser to display the file chooser. The result is returned in a
+// FrameMsg_RunFileChooserResponse message.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_RunFileChooser, content::FileChooserParams)
+
+#if defined(USE_EXTERNAL_POPUP_MENU)
// Message to show/hide a popup menu using native controls.
IPC_MESSAGE_ROUTED1(FrameHostMsg_ShowPopup,
@@ -1467,6 +1561,12 @@ IPC_MESSAGE_ROUTED3(FrameHostMsg_FindMatchRects_Reply,
int /* version */,
std::vector<gfx::RectF> /* rects */,
gfx::RectF /* active_rect */)
+
+// Response to FrameMsg_GetNearestFindResult. |distance| is the distance to the
+// nearest find result in the sending frame.
+IPC_MESSAGE_ROUTED2(FrameHostMsg_GetNearestFindResult_Reply,
+ int /* nfr_request_id */,
+ float /* distance */)
#endif
// Adding a new message? Stick to the sort order above: first platform
diff --git a/chromium/content/common/frame_replication_state.cc b/chromium/content/common/frame_replication_state.cc
index 00e835f5b92..239c9ab82c2 100644
--- a/chromium/content/common/frame_replication_state.cc
+++ b/chromium/content/common/frame_replication_state.cc
@@ -11,7 +11,7 @@ namespace content {
FrameReplicationState::FrameReplicationState()
: sandbox_flags(blink::WebSandboxFlags::None),
scope(blink::WebTreeScopeType::Document),
- should_enforce_strict_mixed_content_checking(false),
+ insecure_request_policy(blink::kLeaveInsecureRequestsAlone),
has_potentially_trustworthy_unique_origin(false) {}
FrameReplicationState::FrameReplicationState(
@@ -19,15 +19,14 @@ FrameReplicationState::FrameReplicationState(
const std::string& name,
const std::string& unique_name,
blink::WebSandboxFlags sandbox_flags,
- bool should_enforce_strict_mixed_content_checking,
+ blink::WebInsecureRequestPolicy insecure_request_policy,
bool has_potentially_trustworthy_unique_origin)
: origin(),
sandbox_flags(sandbox_flags),
name(name),
unique_name(unique_name),
scope(scope),
- should_enforce_strict_mixed_content_checking(
- should_enforce_strict_mixed_content_checking),
+ insecure_request_policy(insecure_request_policy),
has_potentially_trustworthy_unique_origin(
has_potentially_trustworthy_unique_origin) {}
diff --git a/chromium/content/common/frame_replication_state.h b/chromium/content/common/frame_replication_state.h
index 9cb88af432b..b3d3544d6a6 100644
--- a/chromium/content/common/frame_replication_state.h
+++ b/chromium/content/common/frame_replication_state.h
@@ -10,6 +10,7 @@
#include "content/common/content_export.h"
#include "content/common/content_security_policy_header.h"
+#include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
#include "url/origin.h"
namespace blink {
@@ -27,7 +28,7 @@ struct CONTENT_EXPORT FrameReplicationState {
const std::string& name,
const std::string& unique_name,
blink::WebSandboxFlags sandbox_flags,
- bool should_enforce_strict_mixed_content_checking,
+ blink::WebInsecureRequestPolicy insecure_request_policy,
bool has_potentially_trustworthy_unique_origin);
FrameReplicationState(const FrameReplicationState& other);
~FrameReplicationState();
@@ -95,10 +96,10 @@ struct CONTENT_EXPORT FrameReplicationState {
// operator.
blink::WebTreeScopeType scope;
- // True if a frame's current document should strictly block all mixed
- // content. Updates are immediately sent to all frame proxies when
- // frames live in different processes.
- bool should_enforce_strict_mixed_content_checking;
+ // The insecure request policy that a frame's current document is enforcing.
+ // Updates are immediately sent to all frame proxies when frames live in
+ // different processes.
+ blink::WebInsecureRequestPolicy insecure_request_policy;
// True if a frame's origin is unique and should be considered potentially
// trustworthy.
diff --git a/chromium/content/common/gamepad_user_gesture.cc b/chromium/content/common/gamepad_user_gesture.cc
deleted file mode 100644
index 54220d0e839..00000000000
--- a/chromium/content/common/gamepad_user_gesture.cc
+++ /dev/null
@@ -1,43 +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/common/gamepad_user_gesture.h"
-
-#include <math.h>
-
-#include <algorithm>
-
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-
-namespace {
-// A big enough deadzone to detect accidental presses.
-const float kAxisMoveAmountThreshold = 0.5;
-}
-
-namespace content {
-
-bool GamepadsHaveUserGesture(const blink::WebGamepads& gamepads) {
- for (unsigned int i = 0; i < blink::WebGamepads::itemsLengthCap; i++) {
- const blink::WebGamepad& pad = gamepads.items[i];
-
- // If the device is physically connected, then check the buttons and axes
- // to see if there is currently an intentional user action.
- if (pad.connected) {
- for (unsigned int button_index = 0; button_index < pad.buttonsLength;
- button_index++) {
- if (pad.buttons[button_index].pressed)
- return true;
- }
-
- for (unsigned int axes_index = 0; axes_index < pad.axesLength;
- axes_index++) {
- if (fabs(pad.axes[axes_index]) > kAxisMoveAmountThreshold)
- return true;
- }
- }
- }
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gamepad_user_gesture.h b/chromium/content/common/gamepad_user_gesture.h
deleted file mode 100644
index 899e3660487..00000000000
--- a/chromium/content/common/gamepad_user_gesture.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GAMEPAD_USER_GESTURE_H_
-#define CONTENT_COMMON_GAMEPAD_USER_GESTURE_H_
-
-namespace blink {
-class WebGamepads;
-}
-
-namespace content {
-
-// Returns true if any of the gamepads have a button pressed or axis moved
-// that would be considered a user gesture for interaction.
-bool GamepadsHaveUserGesture(const blink::WebGamepads& gamepads);
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GAMEPAD_USER_GESTURE_H_
diff --git a/chromium/content/common/gpu/OWNERS b/chromium/content/common/gpu/OWNERS
index 66c51fe5fbf..0ea6b105a42 100644
--- a/chromium/content/common/gpu/OWNERS
+++ b/chromium/content/common/gpu/OWNERS
@@ -8,15 +8,5 @@ per-file *gpu_memory_buffer*=reveman@chromium.org
# GPU memory manager.
per-file *gpu_memory_manager*=ccameron@chromium.org
-# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/gpu/client/command_buffer_metrics.cc b/chromium/content/common/gpu/client/command_buffer_metrics.cc
index c4bbf195a95..bc70c88bbdd 100644
--- a/chromium/content/common/gpu/client/command_buffer_metrics.cc
+++ b/chromium/content/common/gpu/client/command_buffer_metrics.cc
@@ -64,6 +64,7 @@ CommandBufferContextLostReason GetContextLostReason(
case gpu::error::kGenericError:
return CONTEXT_PARSE_ERROR_GENERIC_ERROR;
case gpu::error::kDeferCommandUntilLater:
+ case gpu::error::kDeferLaterCommands:
case gpu::error::kNoError:
case gpu::error::kLostContext:
NOTREACHED();
diff --git a/chromium/content/common/gpu/client/context_provider_command_buffer.cc b/chromium/content/common/gpu/client/context_provider_command_buffer.cc
index b30e188706e..a1411c8ab01 100644
--- a/chromium/content/common/gpu/client/context_provider_command_buffer.cc
+++ b/chromium/content/common/gpu/client/context_provider_command_buffer.cc
@@ -59,7 +59,6 @@ ContextProviderCommandBuffer::ContextProviderCommandBuffer(
gpu::GpuStreamPriority stream_priority,
gpu::SurfaceHandle surface_handle,
const GURL& active_url,
- gfx::GpuPreference gpu_preference,
bool automatic_flushes,
bool support_locking,
const gpu::SharedMemoryLimits& memory_limits,
@@ -70,7 +69,6 @@ ContextProviderCommandBuffer::ContextProviderCommandBuffer(
stream_priority_(stream_priority),
surface_handle_(surface_handle),
active_url_(active_url),
- gpu_preference_(gpu_preference),
automatic_flushes_(automatic_flushes),
support_locking_(support_locking),
memory_limits_(memory_limits),
@@ -111,6 +109,15 @@ ContextProviderCommandBuffer::GetCommandBufferProxy() {
return command_buffer_.get();
}
+uint32_t ContextProviderCommandBuffer::GetCopyTextureInternalFormat() {
+ if (attributes_.alpha_size > 0)
+ return GL_RGBA;
+ DCHECK_NE(attributes_.red_size, 0);
+ DCHECK_NE(attributes_.green_size, 0);
+ DCHECK_NE(attributes_.blue_size, 0);
+ return GL_RGB;
+}
+
bool ContextProviderCommandBuffer::BindToCurrentThread() {
// This is called on the thread the context will be used.
DCHECK(context_thread_checker_.CalledOnValidThread());
@@ -151,10 +158,8 @@ bool ContextProviderCommandBuffer::BindToCurrentThread() {
if (!task_runner)
task_runner = base::ThreadTaskRunnerHandle::Get();
command_buffer_ = gpu::CommandBufferProxyImpl::Create(
- std::move(channel_), surface_handle_, gfx::Size(),
- shared_command_buffer, stream_id_, stream_priority_,
- attributes_, active_url_, gpu_preference_,
- std::move(task_runner));
+ std::move(channel_), surface_handle_, shared_command_buffer, stream_id_,
+ stream_priority_, attributes_, active_url_, std::move(task_runner));
if (!command_buffer_) {
DLOG(ERROR) << "GpuChannelHost failed to create command buffer.";
command_buffer_metrics::UmaRecordContextInitFailed(context_type_);
diff --git a/chromium/content/common/gpu/client/context_provider_command_buffer.h b/chromium/content/common/gpu/client/context_provider_command_buffer.h
index 26edb3499ee..9ec79ab109c 100644
--- a/chromium/content/common/gpu/client/context_provider_command_buffer.h
+++ b/chromium/content/common/gpu/client/context_provider_command_buffer.h
@@ -53,7 +53,6 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
gpu::GpuStreamPriority stream_priority,
gpu::SurfaceHandle surface_handle,
const GURL& active_url,
- gfx::GpuPreference gpu_preference,
bool automatic_flushes,
bool support_locking,
const gpu::SharedMemoryLimits& memory_limits,
@@ -62,6 +61,9 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
command_buffer_metrics::ContextType type);
gpu::CommandBufferProxyImpl* GetCommandBufferProxy();
+ // Gives the GL internal format that should be used for calling CopyTexImage2D
+ // on the default framebuffer.
+ uint32_t GetCopyTextureInternalFormat();
// cc::ContextProvider implementation.
bool BindToCurrentThread() override;
@@ -109,7 +111,6 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
const gpu::GpuStreamPriority stream_priority_;
const gpu::SurfaceHandle surface_handle_;
const GURL active_url_;
- const gfx::GpuPreference gpu_preference_;
const bool automatic_flushes_;
const bool support_locking_;
const gpu::SharedMemoryLimits memory_limits_;
diff --git a/chromium/content/common/gpu_host_messages.h b/chromium/content/common/gpu_host_messages.h
index 61e2613497e..ba7379805f9 100644
--- a/chromium/content/common/gpu_host_messages.h
+++ b/chromium/content/common/gpu_host_messages.h
@@ -56,14 +56,6 @@ IPC_STRUCT_BEGIN(GpuMsg_CreateGpuMemoryBuffer_Params)
IPC_STRUCT_MEMBER(gpu::SurfaceHandle, surface_handle)
IPC_STRUCT_END()
-IPC_STRUCT_BEGIN(GpuMsg_CreateGpuMemoryBufferFromHandle_Params)
- IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferHandle, handle)
- IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferId, id)
- IPC_STRUCT_MEMBER(gfx::Size, size)
- IPC_STRUCT_MEMBER(gfx::BufferFormat, format)
- IPC_STRUCT_MEMBER(int32_t, client_id)
-IPC_STRUCT_END()
-
IPC_STRUCT_TRAITS_BEGIN(content::EstablishChannelParams)
IPC_STRUCT_TRAITS_MEMBER(client_id)
IPC_STRUCT_TRAITS_MEMBER(client_tracing_id)
@@ -86,6 +78,7 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::GpuPreferences)
#if defined(OS_WIN)
IPC_STRUCT_TRAITS_MEMBER(enable_accelerated_vpx_decode)
IPC_STRUCT_TRAITS_MEMBER(enable_zero_copy_dxgi_video)
+ IPC_STRUCT_TRAITS_MEMBER(enable_nv12_dxgi_video)
#endif
IPC_STRUCT_TRAITS_MEMBER(compile_shader_always_succeeds)
IPC_STRUCT_TRAITS_MEMBER(disable_gl_error_limit)
@@ -107,6 +100,7 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::GpuPreferences)
IPC_STRUCT_TRAITS_MEMBER(enable_gpu_service_logging)
IPC_STRUCT_TRAITS_MEMBER(enable_gpu_service_tracing)
IPC_STRUCT_TRAITS_MEMBER(enable_unsafe_es3_apis)
+ IPC_STRUCT_TRAITS_MEMBER(use_passthrough_cmd_decoder)
IPC_STRUCT_TRAITS_END()
//------------------------------------------------------------------------------
@@ -141,11 +135,6 @@ IPC_MESSAGE_CONTROL1(GpuMsg_CloseChannel, int32_t /* client_id */)
IPC_MESSAGE_CONTROL1(GpuMsg_CreateGpuMemoryBuffer,
GpuMsg_CreateGpuMemoryBuffer_Params)
-// Tells the GPU process to create a new gpu memory buffer from an existing
-// handle.
-IPC_MESSAGE_CONTROL1(GpuMsg_CreateGpuMemoryBufferFromHandle,
- GpuMsg_CreateGpuMemoryBufferFromHandle_Params)
-
// Tells the GPU process to destroy buffer.
IPC_MESSAGE_CONTROL3(GpuMsg_DestroyGpuMemoryBuffer,
gfx::GpuMemoryBufferId, /* id */
@@ -250,3 +239,6 @@ IPC_MESSAGE_CONTROL3(GpuHostMsg_OnLogMessage,
int /*severity*/,
std::string /* header */,
std::string /* message */)
+
+// Sent by the GPU process to indicate that a fields trial has been activated.
+IPC_MESSAGE_CONTROL1(GpuHostMsg_FieldTrialActivated, std::string /* name */)
diff --git a/chromium/content/common/host_discardable_shared_memory_manager.cc b/chromium/content/common/host_discardable_shared_memory_manager.cc
index 7951ea127cc..bfb68905494 100644
--- a/chromium/content/common/host_discardable_shared_memory_manager.cc
+++ b/chromium/content/common/host_discardable_shared_memory_manager.cc
@@ -222,6 +222,16 @@ HostDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
bool HostDiscardableSharedMemoryManager::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
+ if (args.level_of_detail ==
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
+ base::trace_event::MemoryAllocatorDump* total_dump =
+ pmd->CreateAllocatorDump("discardable");
+ total_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ GetBytesAllocated());
+ return true;
+ }
+
base::AutoLock lock(lock_);
for (const auto& process_entry : processes_) {
const int child_process_id = process_entry.first;
diff --git a/chromium/content/common/image_downloader/OWNERS b/chromium/content/common/image_downloader/OWNERS
new file mode 100644
index 00000000000..08850f42120
--- /dev/null
+++ b/chromium/content/common/image_downloader/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/image_downloader/image_downloader.mojom b/chromium/content/common/image_downloader/image_downloader.mojom
index b6ea34edd25..6cafb4e0100 100644
--- a/chromium/content/common/image_downloader/image_downloader.mojom
+++ b/chromium/content/common/image_downloader/image_downloader.mojom
@@ -5,17 +5,18 @@
module content.mojom;
import "skia/public/interfaces/bitmap.mojom";
-import "ui/mojo/geometry/geometry.mojom";
+import "ui/gfx/geometry/mojo/geometry.mojom";
+import "url/mojo/url.mojom";
interface ImageDownloader {
// Fetch and decode an image from a given URL.
// Returns the decoded images, or http_status_code to indicate error.
// Each call is independent, overlapping calls are possible.
- DownloadImage(string url,
+ DownloadImage(url.mojom.Url url,
bool is_favicon,
uint32 max_bitmap_size,
bool bypass_cache)
=> (int32 http_status_code,
array<skia.mojom.Bitmap> images,
- array<mojo.Size> original_image_sizes);
+ array<gfx.mojom.Size> original_image_sizes);
};
diff --git a/chromium/content/common/indexed_db/OWNERS b/chromium/content/common/indexed_db/OWNERS
index 1f0a278156e..c94a62539a2 100644
--- a/chromium/content/common/indexed_db/OWNERS
+++ b/chromium/content/common/indexed_db/OWNERS
@@ -3,15 +3,5 @@ michaeln@chromium.org
jsbell@chromium.org
cmumford@chromium.org
-# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/input/input_event_utils.cc b/chromium/content/common/input/input_event_utils.cc
deleted file mode 100644
index 31669ed3ca3..00000000000
--- a/chromium/content/common/input/input_event_utils.cc
+++ /dev/null
@@ -1,17 +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/common/input/input_event_utils.h"
-
-#include "base/command_line.h"
-#include "content/public/common/content_switches.h"
-
-namespace content {
-
-bool UseGestureBasedWheelScrolling() {
- base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
- return !cmd->HasSwitch(switches::kDisableWheelGestures);
-}
-
-} // namespace content
diff --git a/chromium/content/common/input/input_event_utils.h b/chromium/content/common/input/input_event_utils.h
deleted file mode 100644
index c1a61ce2444..00000000000
--- a/chromium/content/common/input/input_event_utils.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_INPUT_INPUT_EVENT_UTILS_H_
-#define CONTENT_RENDERER_INPUT_INPUT_EVENT_UTILS_H_
-
-#include "content/common/content_export.h"
-#include "content/public/common/content_switches.h"
-
-namespace content {
-
-CONTENT_EXPORT bool UseGestureBasedWheelScrolling();
-
-}; // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_INPUT_EVENT_UTILS_H_
diff --git a/chromium/content/common/input/synthetic_web_input_event_builders.cc b/chromium/content/common/input/synthetic_web_input_event_builders.cc
index e7e7d49176a..c5962b9a74e 100644
--- a/chromium/content/common/input/synthetic_web_input_event_builders.cc
+++ b/chromium/content/common/input/synthetic_web_input_event_builders.cc
@@ -86,7 +86,6 @@ WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float x,
result.wheelTicksY = dy > 0.0f ? 1.0f : -1.0f;
result.modifiers = modifiers;
result.hasPreciseScrollingDeltas = precise;
- result.canScroll = true;
return result;
}
@@ -170,7 +169,7 @@ WebGestureEvent SyntheticWebGestureEventBuilder::BuildFling(
SyntheticWebTouchEvent::SyntheticWebTouchEvent() : WebTouchEvent() {
uniqueTouchEventId = ui::GetNextTouchEventId();
- SetTimestamp(base::TimeTicks::Now() - base::TimeTicks());
+ SetTimestamp(base::TimeTicks::Now());
}
void SyntheticWebTouchEvent::ResetPoints() {
@@ -237,8 +236,8 @@ void SyntheticWebTouchEvent::CancelPoint(int index) {
WebInputEvent::TouchCancel, timeStampSeconds, this);
}
-void SyntheticWebTouchEvent::SetTimestamp(base::TimeDelta timestamp) {
- timeStampSeconds = timestamp.InSecondsF();
+void SyntheticWebTouchEvent::SetTimestamp(base::TimeTicks timestamp) {
+ timeStampSeconds = ui::EventTimeStampToSeconds(timestamp);
}
} // namespace content
diff --git a/chromium/content/common/input/synthetic_web_input_event_builders.h b/chromium/content/common/input/synthetic_web_input_event_builders.h
index 9d3bc22f419..034ee49ca79 100644
--- a/chromium/content/common/input/synthetic_web_input_event_builders.h
+++ b/chromium/content/common/input/synthetic_web_input_event_builders.h
@@ -86,7 +86,7 @@ class CONTENT_EXPORT SyntheticWebTouchEvent
void ReleasePoint(int index);
void CancelPoint(int index);
- void SetTimestamp(base::TimeDelta timestamp);
+ void SetTimestamp(base::TimeTicks timestamp);
};
} // namespace content
diff --git a/chromium/content/common/input/web_input_event_traits.cc b/chromium/content/common/input/web_input_event_traits.cc
index c94a2d40c9b..fd2115021fc 100644
--- a/chromium/content/common/input/web_input_event_traits.cc
+++ b/chromium/content/common/input/web_input_event_traits.cc
@@ -55,23 +55,15 @@ void ApppendEventDetails(const WebMouseEvent& event, std::string* result) {
}
void ApppendEventDetails(const WebMouseWheelEvent& event, std::string* result) {
- StringAppendF(result,
- "{\n Delta: (%f, %f)\n WheelTicks: (%f, %f)\n Accel: (%f, %f)\n"
- " ScrollByPage: %d\n HasPreciseScrollingDeltas: %d\n"
- " Phase: (%d, %d)\n CanRubberband: (%d, %d)\n CanScroll: %d\n}",
- event.deltaX,
- event.deltaY,
- event.wheelTicksX,
- event.wheelTicksY,
- event.accelerationRatioX,
- event.accelerationRatioY,
- event.scrollByPage,
- event.hasPreciseScrollingDeltas,
- event.phase,
- event.momentumPhase,
- event.canRubberbandLeft,
- event.canRubberbandRight,
- event.canScroll);
+ StringAppendF(
+ result,
+ "{\n Delta: (%f, %f)\n WheelTicks: (%f, %f)\n Accel: (%f, %f)\n"
+ " ScrollByPage: %d\n HasPreciseScrollingDeltas: %d\n"
+ " Phase: (%d, %d)\n CanRubberband: (%d, %d)\n}",
+ event.deltaX, event.deltaY, event.wheelTicksX, event.wheelTicksY,
+ event.accelerationRatioX, event.accelerationRatioY, event.scrollByPage,
+ event.hasPreciseScrollingDeltas, event.phase, event.momentumPhase,
+ event.canRubberbandLeft, event.canRubberbandRight);
}
void ApppendEventDetails(const WebGestureEvent& event, std::string* result) {
@@ -153,8 +145,7 @@ bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
event.phase == event_to_coalesce.phase &&
event.momentumPhase == event_to_coalesce.momentumPhase &&
event.hasPreciseScrollingDeltas ==
- event_to_coalesce.hasPreciseScrollingDeltas &&
- event.canScroll == event_to_coalesce.canScroll;
+ event_to_coalesce.hasPreciseScrollingDeltas;
}
float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
@@ -525,6 +516,18 @@ bool WebInputEventTraits::ShouldBlockEventStream(const WebInputEvent& event) {
}
}
+bool WebInputEventTraits::CanCauseScroll(
+ const blink::WebMouseWheelEvent& event) {
+#if defined(USE_AURA)
+ // Scroll events generated from the mouse wheel when the control key is held
+ // don't trigger scrolling. Instead, they may cause zooming.
+ return event.hasPreciseScrollingDeltas ||
+ (event.modifiers & blink::WebInputEvent::ControlKey) == 0;
+#else
+ return true;
+#endif
+}
+
uint32_t WebInputEventTraits::GetUniqueTouchEventId(
const WebInputEvent& event) {
if (WebInputEvent::isTouchEventType(event.type)) {
diff --git a/chromium/content/common/input/web_input_event_traits.h b/chromium/content/common/input/web_input_event_traits.h
index 2f9ca8c5232..31d22fe8164 100644
--- a/chromium/content/common/input/web_input_event_traits.h
+++ b/chromium/content/common/input/web_input_event_traits.h
@@ -29,6 +29,8 @@ class CONTENT_EXPORT WebInputEventTraits {
blink::WebInputEvent* event);
static bool ShouldBlockEventStream(const blink::WebInputEvent& event);
+ static bool CanCauseScroll(const blink::WebMouseWheelEvent& event);
+
// Return uniqueTouchEventId for WebTouchEvent, otherwise return 0.
static uint32_t GetUniqueTouchEventId(const blink::WebInputEvent& event);
};
diff --git a/chromium/content/common/input/web_input_event_traits_unittest.cc b/chromium/content/common/input/web_input_event_traits_unittest.cc
index 1daf80dcf1a..7c773f4f45a 100644
--- a/chromium/content/common/input/web_input_event_traits_unittest.cc
+++ b/chromium/content/common/input/web_input_event_traits_unittest.cc
@@ -52,14 +52,11 @@ class WebInputEventTraitsTest : public testing::Test {
return event;
}
- static WebMouseWheelEvent CreateMouseWheel(float deltaX,
- float deltaY,
- bool canScroll) {
+ static WebMouseWheelEvent CreateMouseWheel(float deltaX, float deltaY) {
WebMouseWheelEvent event;
event.type = WebInputEvent::MouseWheel;
event.deltaX = deltaX;
event.deltaY = deltaY;
- event.canScroll = canScroll;
return event;
}
};
@@ -202,25 +199,16 @@ TEST_F(WebInputEventTraitsTest, PinchEventCoalescing) {
}
TEST_F(WebInputEventTraitsTest, WebMouseWheelEventCoalescing) {
- WebMouseWheelEvent mouse_wheel_0 =
- CreateMouseWheel(1, 1, true);
- WebMouseWheelEvent mouse_wheel_1 =
- CreateMouseWheel(2, 2, true);
+ WebMouseWheelEvent mouse_wheel_0 = CreateMouseWheel(1, 1);
+ WebMouseWheelEvent mouse_wheel_1 = CreateMouseWheel(2, 2);
// WebMouseWheelEvent objects with same values except different deltaX and
// deltaY should coalesce.
EXPECT_TRUE(WebInputEventTraits::CanCoalesce(mouse_wheel_0, mouse_wheel_1));
- mouse_wheel_0 = CreateMouseWheel(1, 1, true);
- mouse_wheel_1 = CreateMouseWheel(1, 1, false);
-
- // WebMouseWheelEvent objects with different canScroll values should not
- // coalesce.
- EXPECT_FALSE(WebInputEventTraits::CanCoalesce(mouse_wheel_0, mouse_wheel_1));
-
// WebMouseWheelEvent objects with different modifiers should not coalesce.
- mouse_wheel_0 = CreateMouseWheel(1, 1, true);
- mouse_wheel_1 = CreateMouseWheel(1, 1, true);
+ mouse_wheel_0 = CreateMouseWheel(1, 1);
+ mouse_wheel_1 = CreateMouseWheel(1, 1);
mouse_wheel_0.modifiers = blink::WebInputEvent::ControlKey;
mouse_wheel_1.modifiers = blink::WebInputEvent::ShiftKey;
EXPECT_FALSE(WebInputEventTraits::CanCoalesce(mouse_wheel_0, mouse_wheel_1));
@@ -228,9 +216,9 @@ TEST_F(WebInputEventTraitsTest, WebMouseWheelEventCoalescing) {
// Coalescing preserves the newer timestamp.
TEST_F(WebInputEventTraitsTest, TimestampCoalescing) {
- WebMouseWheelEvent mouse_wheel_0 = CreateMouseWheel(1, 1, true);
+ WebMouseWheelEvent mouse_wheel_0 = CreateMouseWheel(1, 1);
mouse_wheel_0.timeStampSeconds = 5.0;
- WebMouseWheelEvent mouse_wheel_1 = CreateMouseWheel(2, 2, true);
+ WebMouseWheelEvent mouse_wheel_1 = CreateMouseWheel(2, 2);
mouse_wheel_1.timeStampSeconds = 10.0;
EXPECT_TRUE(WebInputEventTraits::CanCoalesce(mouse_wheel_0, mouse_wheel_1));
diff --git a/chromium/content/common/input_messages.h b/chromium/content/common/input_messages.h
index 95e094e343f..4d3c0ce4a63 100644
--- a/chromium/content/common/input_messages.h
+++ b/chromium/content/common/input_messages.h
@@ -253,13 +253,6 @@ IPC_MESSAGE_ROUTED1(InputMsg_MoveCaret,
gfx::Point /* location */)
#if defined(OS_ANDROID)
-// Sent when the user clicks on the find result bar to activate a find result.
-// The point (x,y) is in fractions of the content document's width and height.
-IPC_MESSAGE_ROUTED3(InputMsg_ActivateNearestFindResult,
- int /* request_id */,
- float /* x */,
- float /* y */)
-
// Sent by the browser as ACK to ViewHostMsg_TextInputState when necessary.
// NOTE: ImeEventAck and other Ime* messages should be of the same type,
// otherwise a race condition can happen.
diff --git a/chromium/content/common/mac/font_loader.mm b/chromium/content/common/mac/font_loader.mm
index 4ce635973b0..ae036075338 100644
--- a/chromium/content/common/mac/font_loader.mm
+++ b/chromium/content/common/mac/font_loader.mm
@@ -20,42 +20,6 @@
#include <map>
-extern "C" {
-
-// Work around http://crbug.com/93191, a really nasty memory smasher bug.
-// On Mac OS X 10.7 ("Lion"), ATS writes to memory it doesn't own.
-// SendDeactivateFontsInContainerMessage, called by ATSFontDeactivate,
-// may trash memory whenever dlsym(RTLD_DEFAULT,
-// "_CTFontManagerUnregisterFontForData") returns NULL. In that case, it tries
-// to locate that symbol in the CoreText framework, doing some extremely
-// sloppy string handling resulting in a likelihood that the string
-// "Text.framework/Versions/A/CoreText" will be written over memory that it
-// doesn't own. The kicker here is that Apple dlsym always inserts its own
-// leading underscore, so ATS actually winds up looking up a
-// __CTFontManagerUnregisterFontForData symbol, which doesn't even exist in
-// CoreText. It's only got the single-underscore variant corresponding to an
-// underscoreless extern "C" name.
-//
-// Providing a single-underscored extern "C" function by this name results in
-// a __CTFontManagerUnregisterFontForData symbol that, as long as it's public
-// (not private extern) and unstripped, ATS will find. If it finds it, it
-// avoids making amateur string mistakes that ruin everyone else's good time.
-//
-// Since ATS wouldn't normally be able to call this function anyway, it's just
-// left as a no-op here.
-//
-// This file seems as good as any other to place this function. It was chosen
-// because it already interfaces with ATS for other reasons.
-//
-// SendDeactivateFontsInContainerMessage on 10.6 ("Snow Leopard") appears to
-// share this bug but this sort of memory corruption wasn't detected until
-// 10.7. The implementation in 10.5 ("Leopard") does not have this problem.
-__attribute__((visibility("default")))
-void _CTFontManagerUnregisterFontForData(NSUInteger, int) {
-}
-
-} // extern "C"
-
namespace {
uint32_t GetFontIDForFont(const base::FilePath& font_path) {
diff --git a/chromium/content/common/media/OWNERS b/chromium/content/common/media/OWNERS
index bd15b3e0625..5b281449c56 100644
--- a/chromium/content/common/media/OWNERS
+++ b/chromium/content/common/media/OWNERS
@@ -1,27 +1,8 @@
file://media/OWNERS
tommi@chromium.org
-# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
-per-file *_param_traits.*=set noparent
-per-file *_param_traits.*=dcheng@chromium.org
-per-file *_param_traits.*=inferno@chromium.org
-per-file *_param_traits.*=jln@chromium.org
-per-file *_param_traits.*=jschuh@chromium.org
-per-file *_param_traits.*=kenrb@chromium.org
-per-file *_param_traits.*=mkwst@chromium.org
-per-file *_param_traits.*=nasko@chromium.org
-per-file *_param_traits.*=palmer@chromium.org
-per-file *_param_traits.*=tsepez@chromium.org
-per-file *_param_traits.*=wfh@chromium.org
+per-file *_param_traits*.*=set noparent
+per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/media/media_stream_options.cc b/chromium/content/common/media/media_stream_options.cc
index 1b2b1e2750a..944d3d4b561 100644
--- a/chromium/content/common/media/media_stream_options.cc
+++ b/chromium/content/common/media/media_stream_options.cc
@@ -8,18 +8,10 @@
namespace content {
-const char kMediaStreamSource[] = "chromeMediaSource";
-const char kMediaStreamSourceId[] = "chromeMediaSourceId";
-const char kMediaStreamSourceInfoId[] = "sourceId";
const char kMediaStreamSourceTab[] = "tab";
const char kMediaStreamSourceScreen[] = "screen";
const char kMediaStreamSourceDesktop[] = "desktop";
const char kMediaStreamSourceSystem[] = "system";
-const char kMediaStreamRenderToAssociatedSink[] =
- "chromeRenderToAssociatedSink";
-// The prefix of this constant is 'goog' to match with other getUserMedia
-// constraints for audio.
-const char kMediaStreamAudioHotword[] = "googHotword";
TrackControls::TrackControls()
: requested(false) {}
diff --git a/chromium/content/common/media/media_stream_options.h b/chromium/content/common/media/media_stream_options.h
index b815c602cdf..dc458b5224a 100644
--- a/chromium/content/common/media/media_stream_options.h
+++ b/chromium/content/common/media/media_stream_options.h
@@ -13,25 +13,14 @@
namespace content {
-// MediaStreamConstraint keys for constraints that are passed to getUserMedia.
-CONTENT_EXPORT extern const char kMediaStreamSource[];
-CONTENT_EXPORT extern const char kMediaStreamSourceId[];
-CONTENT_EXPORT extern const char kMediaStreamSourceInfoId[];
+// Names for media stream source capture types.
+// These are values of the "TrackControls.stream_source" field, and are
+// set via the "chromeMediaSource" constraint.
CONTENT_EXPORT extern const char kMediaStreamSourceTab[];
CONTENT_EXPORT extern const char kMediaStreamSourceScreen[];
CONTENT_EXPORT extern const char kMediaStreamSourceDesktop[];
CONTENT_EXPORT extern const char kMediaStreamSourceSystem[];
-// Experimental constraint to do device matching. When this optional constraint
-// is set, WebRTC audio renderer will render audio from media streams to an
-// output device that belongs to the same hardware as the requested source
-// device belongs to.
-CONTENT_EXPORT extern const char kMediaStreamRenderToAssociatedSink[];
-
-// Controls whether the hotword audio stream is used on platforms that support
-// it.
-CONTENT_EXPORT extern const char kMediaStreamAudioHotword[];
-
struct CONTENT_EXPORT TrackControls {
public:
TrackControls();
diff --git a/chromium/content/common/media/video_capture_messages.h b/chromium/content/common/media/video_capture_messages.h
index 47c9d532049..4ff6f01d80d 100644
--- a/chromium/content/common/media/video_capture_messages.h
+++ b/chromium/content/common/media/video_capture_messages.h
@@ -33,7 +33,7 @@ IPC_STRUCT_TRAITS_END()
IPC_STRUCT_BEGIN(VideoCaptureMsg_BufferReady_Params)
IPC_STRUCT_MEMBER(int, device_id)
IPC_STRUCT_MEMBER(int, buffer_id)
- IPC_STRUCT_MEMBER(base::TimeTicks, timestamp)
+ IPC_STRUCT_MEMBER(base::TimeDelta, timestamp)
IPC_STRUCT_MEMBER(base::DictionaryValue, metadata)
IPC_STRUCT_MEMBER(media::VideoPixelFormat, pixel_format)
IPC_STRUCT_MEMBER(media::VideoFrame::StorageType, storage_type)
diff --git a/chromium/content/common/mime_registry_messages.h b/chromium/content/common/mime_registry_messages.h
deleted file mode 100644
index e88204779d0..00000000000
--- a/chromium/content/common/mime_registry_messages.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Multiply-included message file, so no include guard.
-
-#include "base/files/file_path.h"
-#include "content/public/common/common_param_traits.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_param_traits.h"
-
-#define IPC_MESSAGE_START MimeRegistryMsgStart
-
-// Mime registry messages sent from the renderer to the browser.
-
-// Sent to query MIME information.
-IPC_SYNC_MESSAGE_CONTROL1_1(MimeRegistryMsg_GetMimeTypeFromExtension,
- base::FilePath::StringType /* extension */,
- std::string /* mime_type */)
diff --git a/chromium/content/common/mojo/OWNERS b/chromium/content/common/mojo/OWNERS
index c5d7458faca..9216e7a75ab 100644
--- a/chromium/content/common/mojo/OWNERS
+++ b/chromium/content/common/mojo/OWNERS
@@ -1,21 +1,5 @@
-# Changes to IPC messages require a security review to avoid introducing
-# new sandbox escapes.
-per-file *_message*.h=set noparent
-per-file *_message*.h=dcheng@chromium.org
-per-file *_message*.h=inferno@chromium.org
-per-file *_message*.h=jln@chromium.org
-per-file *_message*.h=jschuh@chromium.org
-per-file *_message*.h=kenrb@chromium.org
-per-file *_message*.h=nasko@chromium.org
-per-file *_message*.h=palmer@chromium.org
-per-file *_message*.h=tsepez@chromium.org
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
-per-file *param_traits*.h=set noparent
-per-file *param_traits*.h=dcheng@chromium.org
-per-file *param_traits*.h=inferno@chromium.org
-per-file *param_traits*.h=jln@chromium.org
-per-file *param_traits*.h=jschuh@chromium.org
-per-file *param_traits*.h=kenrb@chromium.org
-per-file *param_traits*.h=nasko@chromium.org
-per-file *param_traits*.h=palmer@chromium.org
-per-file *param_traits*.h=tsepez@chromium.org
+per-file *_param_traits*.*=set noparent
+per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/mojo/embedded_application_runner.cc b/chromium/content/common/mojo/embedded_application_runner.cc
index 2bbd45e5f9e..f8778d684aa 100644
--- a/chromium/content/common/mojo/embedded_application_runner.cc
+++ b/chromium/content/common/mojo/embedded_application_runner.cc
@@ -29,8 +29,6 @@ class EmbeddedApplicationRunner::Instance
quit_closure_(quit_closure),
quit_task_runner_(base::ThreadTaskRunnerHandle::Get()),
application_task_runner_(info.application_task_runner) {
- application_thread_checker_.DetachFromThread();
-
if (!use_own_thread_ && !application_task_runner_)
application_task_runner_ = base::ThreadTaskRunnerHandle::Get();
}
@@ -63,7 +61,7 @@ class EmbeddedApplicationRunner::Instance
private:
void BindShellClientRequestOnApplicationThread(
shell::mojom::ShellClientRequest request) {
- DCHECK(application_thread_checker_.CalledOnValidThread());
+ DCHECK(application_task_runner_->BelongsToCurrentThread());
if (!shell_client_) {
shell_client_ = factory_callback_.Run(
@@ -88,7 +86,7 @@ class EmbeddedApplicationRunner::Instance
}
void OnShellConnectionLost(shell::ShellConnection* connection) {
- DCHECK(application_thread_checker_.CalledOnValidThread());
+ DCHECK(application_task_runner_->BelongsToCurrentThread());
for (auto it = shell_connections_.begin(); it != shell_connections_.end();
++it) {
@@ -100,7 +98,7 @@ class EmbeddedApplicationRunner::Instance
}
void Quit() {
- DCHECK(application_thread_checker_.CalledOnValidThread());
+ DCHECK(application_task_runner_->BelongsToCurrentThread());
shell_connections_.clear();
shell_client_.reset();
@@ -124,10 +122,6 @@ class EmbeddedApplicationRunner::Instance
// runner's (i.e. our owner's) thread.
base::ThreadChecker runner_thread_checker_;
- // Thread checker used to ensure certain operations happen only on the
- // application task runner's thread.
- base::ThreadChecker application_thread_checker_;
-
// These fields must only be accessed from the runner's thread.
std::unique_ptr<base::Thread> thread_;
scoped_refptr<base::SingleThreadTaskRunner> application_task_runner_;
diff --git a/chromium/content/common/mojo/mojo_shell_connection_impl.cc b/chromium/content/common/mojo/mojo_shell_connection_impl.cc
index f3b9be56e24..6c5ef64a781 100644
--- a/chromium/content/common/mojo/mojo_shell_connection_impl.cc
+++ b/chromium/content/common/mojo/mojo_shell_connection_impl.cc
@@ -1,20 +1,14 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// 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/common/mojo/mojo_shell_connection_impl.h"
-#include <utility>
-
-#include "base/command_line.h"
+#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
-#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/threading/thread_local.h"
-#include "content/public/common/content_switches.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "content/common/mojo/embedded_application_runner.h"
#include "services/shell/public/cpp/shell_client.h"
#include "services/shell/public/cpp/shell_connection.h"
#include "services/shell/runner/common/client_util.h"
@@ -23,7 +17,7 @@ namespace content {
namespace {
using MojoShellConnectionPtr =
- base::ThreadLocalPointer<MojoShellConnectionImpl>;
+ base::ThreadLocalPointer<MojoShellConnection>;
// Env is thread local so that aura may be used on multiple threads.
base::LazyInstance<MojoShellConnectionPtr>::Leaky lazy_tls_ptr =
@@ -33,40 +27,26 @@ MojoShellConnection::Factory* mojo_shell_connection_factory = nullptr;
} // namespace
-bool IsRunningInMojoShell() {
- return mojo_shell_connection_factory ||
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch);
-}
+////////////////////////////////////////////////////////////////////////////////
+// MojoShellConnection, public:
// static
-bool MojoShellConnectionImpl::CreateUsingFactory() {
- if (mojo_shell_connection_factory) {
- DCHECK(!lazy_tls_ptr.Pointer()->Get());
- mojo_shell_connection_factory->Run();
- DCHECK(lazy_tls_ptr.Pointer()->Get());
- return true;
- }
- return false;
+void MojoShellConnection::SetForProcess(
+ std::unique_ptr<MojoShellConnection> connection) {
+ DCHECK(!lazy_tls_ptr.Pointer()->Get());
+ lazy_tls_ptr.Pointer()->Set(connection.release());
}
// static
-void MojoShellConnectionImpl::Create() {
- DCHECK(!lazy_tls_ptr.Pointer()->Get());
- MojoShellConnectionImpl* connection =
- new MojoShellConnectionImpl(true /* external */);
- lazy_tls_ptr.Pointer()->Set(connection);
+MojoShellConnection* MojoShellConnection::GetForProcess() {
+ return lazy_tls_ptr.Pointer()->Get();
}
// static
-void MojoShellConnection::Create(shell::mojom::ShellClientRequest request,
- bool is_external) {
- DCHECK(!lazy_tls_ptr.Pointer()->Get());
- MojoShellConnectionImpl* connection =
- new MojoShellConnectionImpl(is_external);
- lazy_tls_ptr.Pointer()->Set(connection);
- connection->shell_connection_.reset(
- new shell::ShellConnection(connection, std::move(request)));
+void MojoShellConnection::DestroyForProcess() {
+ // This joins the shell controller thread.
+ delete GetForProcess();
+ lazy_tls_ptr.Pointer()->Set(nullptr);
}
// static
@@ -76,34 +56,102 @@ void MojoShellConnection::SetFactoryForTest(Factory* factory) {
}
// static
-MojoShellConnectionImpl* MojoShellConnectionImpl::Get() {
- // Assume that if a mojo_shell_connection_factory was set that it did not
- // create a MojoShellConnectionImpl.
- return static_cast<MojoShellConnectionImpl*>(MojoShellConnection::Get());
+std::unique_ptr<MojoShellConnection> MojoShellConnection::Create(
+ shell::mojom::ShellClientRequest request) {
+ if (mojo_shell_connection_factory)
+ return mojo_shell_connection_factory->Run();
+ return base::WrapUnique(new MojoShellConnectionImpl(std::move(request)));
}
-void MojoShellConnectionImpl::BindToRequestFromCommandLine() {
- DCHECK(!shell_connection_);
- shell_connection_.reset(new shell::ShellConnection(
- this, shell::GetShellClientRequestFromCommandLine()));
-}
+MojoShellConnection::~MojoShellConnection() {}
-MojoShellConnectionImpl::MojoShellConnectionImpl(bool external)
- : external_(external) {}
+////////////////////////////////////////////////////////////////////////////////
+// MojoShellConnectionImpl, public:
-MojoShellConnectionImpl::~MojoShellConnectionImpl() {
- STLDeleteElements(&listeners_);
-}
+MojoShellConnectionImpl::MojoShellConnectionImpl(
+ shell::mojom::ShellClientRequest request)
+ : shell_connection_(new shell::ShellConnection(this, std::move(request))) {}
+
+MojoShellConnectionImpl::~MojoShellConnectionImpl() {}
+
+////////////////////////////////////////////////////////////////////////////////
+// MojoShellConnectionImpl, shell::ShellClient implementation:
void MojoShellConnectionImpl::Initialize(shell::Connector* connector,
const shell::Identity& identity,
- uint32_t id) {}
+ uint32_t id) {
+ for (auto& client : embedded_shell_clients_)
+ client->Initialize(connector, identity, id);
+}
bool MojoShellConnectionImpl::AcceptConnection(shell::Connection* connection) {
- bool found = false;
- for (auto listener : listeners_)
- found |= listener->AcceptConnection(connection);
- return found;
+ std::string remote_app = connection->GetRemoteIdentity().name();
+ if (remote_app == "mojo:shell") {
+ // Only expose the SCF interface to the shell.
+ connection->AddInterface<shell::mojom::ShellClientFactory>(this);
+ return true;
+ }
+
+ bool accept = false;
+ for (auto& client : embedded_shell_clients_)
+ accept |= client->AcceptConnection(connection);
+
+ // Reject all other connections to this application.
+ return accept;
+}
+
+shell::InterfaceRegistry*
+MojoShellConnectionImpl::GetInterfaceRegistryForConnection() {
+ // TODO(beng): This is really horrible since obviously subject to issues
+ // of ordering, but is no more horrible than this API is in general.
+ shell::InterfaceRegistry* registry = nullptr;
+ for (auto& client : embedded_shell_clients_) {
+ registry = client->GetInterfaceRegistryForConnection();
+ if (registry)
+ return registry;
+ }
+ return nullptr;
+}
+
+shell::InterfaceProvider*
+MojoShellConnectionImpl::GetInterfaceProviderForConnection() {
+ // TODO(beng): This is really horrible since obviously subject to issues
+ // of ordering, but is no more horrible than this API is in general.
+ shell::InterfaceProvider* provider = nullptr;
+ for (auto& client : embedded_shell_clients_) {
+ provider = client->GetInterfaceProviderForConnection();
+ if (provider)
+ return provider;
+ }
+ return nullptr;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MojoShellConnectionImpl,
+// shell::InterfaceFactory<shell::mojom::ShellClientFactory> implementation:
+
+void MojoShellConnectionImpl::Create(
+ shell::Connection* connection,
+ shell::mojom::ShellClientFactoryRequest request) {
+ factory_bindings_.AddBinding(this, std::move(request));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MojoShellConnectionImpl, shell::mojom::ShellClientFactory implementation:
+
+void MojoShellConnectionImpl::CreateShellClient(
+ shell::mojom::ShellClientRequest request,
+ const mojo::String& name) {
+ auto it = request_handlers_.find(name);
+ if (it != request_handlers_.end())
+ it->second.Run(std::move(request));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MojoShellConnectionImpl, MojoShellConnection implementation:
+
+shell::ShellConnection* MojoShellConnectionImpl::GetShellConnection() {
+ return shell_connection_.get();
}
shell::Connector* MojoShellConnectionImpl::GetConnector() {
@@ -116,41 +164,39 @@ const shell::Identity& MojoShellConnectionImpl::GetIdentity() const {
return shell_connection_->identity();
}
-bool MojoShellConnectionImpl::UsingExternalShell() const {
- return external_;
-}
-
void MojoShellConnectionImpl::SetConnectionLostClosure(
const base::Closure& closure) {
shell_connection_->SetConnectionLostClosure(closure);
}
-void MojoShellConnectionImpl::AddListener(std::unique_ptr<Listener> listener) {
- DCHECK(std::find(listeners_.begin(), listeners_.end(), listener.get()) ==
- listeners_.end());
- listeners_.push_back(listener.release());
+void MojoShellConnectionImpl::AddEmbeddedShellClient(
+ std::unique_ptr<shell::ShellClient> shell_client) {
+ embedded_shell_clients_.push_back(shell_client.get());
+ owned_shell_clients_.push_back(std::move(shell_client));
}
-std::unique_ptr<MojoShellConnection::Listener>
-MojoShellConnectionImpl::RemoveListener(Listener* listener) {
- auto it = std::find(listeners_.begin(), listeners_.end(), listener);
- DCHECK(it != listeners_.end());
- listeners_.erase(it);
- return base::WrapUnique(listener);
+void MojoShellConnectionImpl::AddEmbeddedShellClient(
+ shell::ShellClient* shell_client) {
+ embedded_shell_clients_.push_back(shell_client);
}
-// static
-MojoShellConnection* MojoShellConnection::Get() {
- return lazy_tls_ptr.Pointer()->Get();
+void MojoShellConnectionImpl::AddEmbeddedService(
+ const std::string& name,
+ const MojoApplicationInfo& info) {
+ std::unique_ptr<EmbeddedApplicationRunner> app(
+ new EmbeddedApplicationRunner(name, info));
+ AddShellClientRequestHandler(
+ name, base::Bind(&EmbeddedApplicationRunner::BindShellClientRequest,
+ base::Unretained(app.get())));
+ auto result = embedded_apps_.insert(std::make_pair(name, std::move(app)));
+ DCHECK(result.second);
}
-// static
-void MojoShellConnection::Destroy() {
- // This joins the shell controller thread.
- delete Get();
- lazy_tls_ptr.Pointer()->Set(nullptr);
+void MojoShellConnectionImpl::AddShellClientRequestHandler(
+ const std::string& name,
+ const ShellClientRequestHandler& handler) {
+ auto result = request_handlers_.insert(std::make_pair(name, handler));
+ DCHECK(result.second);
}
-MojoShellConnection::~MojoShellConnection() {}
-
} // namespace content
diff --git a/chromium/content/common/mojo/mojo_shell_connection_impl.h b/chromium/content/common/mojo/mojo_shell_connection_impl.h
index 3ad19d239df..b20cd0ad4cb 100644
--- a/chromium/content/common/mojo/mojo_shell_connection_impl.h
+++ b/chromium/content/common/mojo/mojo_shell_connection_impl.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// 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.
@@ -10,61 +10,64 @@
#include "base/macros.h"
#include "content/public/common/mojo_shell_connection.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "services/shell/public/cpp/shell_client.h"
#include "services/shell/public/cpp/shell_connection.h"
+#include "services/shell/public/interfaces/shell_client_factory.mojom.h"
namespace content {
-// Returns true for processes launched from an external mojo shell.
-bool IsRunningInMojoShell();
+class EmbeddedApplicationRunner;
-class MojoShellConnectionImpl : public MojoShellConnection,
- public shell::ShellClient {
- public:
- // Creates the MojoShellConnection using MojoShellConnection::Factory. Returns
- // true if a factory was set and the connection was created, false otherwise.
- static bool CreateUsingFactory();
-
- // Creates an instance of this class and stuffs it in TLS on the calling
- // thread. Retrieve it using MojoShellConnection::Get().
- static void Create();
-
- // Will return null if no connection has been established (either because it
- // hasn't happened yet or the application was not spawned from the external
- // Mojo shell).
- static MojoShellConnectionImpl* Get();
+class MojoShellConnectionImpl
+ : public MojoShellConnection,
+ public shell::ShellClient,
+ public shell::InterfaceFactory<shell::mojom::ShellClientFactory>,
+ public shell::mojom::ShellClientFactory {
- // Binds the shell connection to a ShellClientFactory request pipe from the
- // command line. This must only be called once.
- void BindToRequestFromCommandLine();
-
- // TODO(rockot): Remove this. http://crbug.com/594852.
- shell::ShellConnection* shell_connection() { return shell_connection_.get(); }
+ public:
+ explicit MojoShellConnectionImpl(shell::mojom::ShellClientRequest request);
+ ~MojoShellConnectionImpl() override;
private:
- friend class MojoShellConnection;
-
- explicit MojoShellConnectionImpl(bool external);
- ~MojoShellConnectionImpl() override;
+ // MojoShellConnection:
+ shell::ShellConnection* GetShellConnection() override;
+ shell::Connector* GetConnector() override;
+ const shell::Identity& GetIdentity() const override;
+ void SetConnectionLostClosure(const base::Closure& closure) override;
+ void AddEmbeddedShellClient(
+ std::unique_ptr<shell::ShellClient> shell_client) override;
+ void AddEmbeddedShellClient(shell::ShellClient* shell_client) override;
+ void AddEmbeddedService(const std::string& name,
+ const MojoApplicationInfo& info) override;
+ void AddShellClientRequestHandler(
+ const std::string& name,
+ const ShellClientRequestHandler& handler) override;
// shell::ShellClient:
void Initialize(shell::Connector* connector,
const shell::Identity& identity,
uint32_t id) override;
bool AcceptConnection(shell::Connection* connection) override;
+ shell::InterfaceRegistry* GetInterfaceRegistryForConnection() override;
+ shell::InterfaceProvider* GetInterfaceProviderForConnection() override;
- // MojoShellConnection:
- shell::Connector* GetConnector() override;
- const shell::Identity& GetIdentity() const override;
- bool UsingExternalShell() const override;
- void SetConnectionLostClosure(const base::Closure& closure) override;
- void AddListener(std::unique_ptr<Listener> listener) override;
- std::unique_ptr<Listener> RemoveListener(Listener* listener) override;
+ // shell::InterfaceFactory<shell::mojom::ShellClientFactory>:
+ void Create(shell::Connection* connection,
+ shell::mojom::ShellClientFactoryRequest request) override;
+
+ // shell::mojom::ShellClientFactory:
+ void CreateShellClient(shell::mojom::ShellClientRequest request,
+ const mojo::String& name) override;
- const bool external_;
std::unique_ptr<shell::ShellConnection> shell_connection_;
- std::vector<Listener*> listeners_;
+ mojo::BindingSet<shell::mojom::ShellClientFactory> factory_bindings_;
+ std::vector<shell::ShellClient*> embedded_shell_clients_;
+ std::vector<std::unique_ptr<shell::ShellClient>> owned_shell_clients_;
+ std::unordered_map<std::string, std::unique_ptr<EmbeddedApplicationRunner>>
+ embedded_apps_;
+ std::unordered_map<std::string, ShellClientRequestHandler> request_handlers_;
DISALLOW_COPY_AND_ASSIGN(MojoShellConnectionImpl);
};
diff --git a/chromium/content/common/mojo/service_registry_impl.cc b/chromium/content/common/mojo/service_registry_impl.cc
deleted file mode 100644
index d5e48f1991a..00000000000
--- a/chromium/content/common/mojo/service_registry_impl.cc
+++ /dev/null
@@ -1,113 +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/common/mojo/service_registry_impl.h"
-
-#include <utility>
-
-#include "mojo/common/common_type_converters.h"
-
-namespace content {
-
-ServiceRegistry* ServiceRegistry::Create() {
- return new ServiceRegistryImpl;
-}
-
-ServiceRegistryImpl::ServiceRegistryImpl()
- : binding_(this), weak_factory_(this) {}
-
-ServiceRegistryImpl::~ServiceRegistryImpl() {
- while (!pending_connects_.empty()) {
- mojo::CloseRaw(pending_connects_.front().second);
- pending_connects_.pop();
- }
-}
-
-void ServiceRegistryImpl::Bind(shell::mojom::InterfaceProviderRequest request) {
- binding_.Bind(std::move(request));
- binding_.set_connection_error_handler(base::Bind(
- &ServiceRegistryImpl::OnConnectionError, base::Unretained(this)));
-}
-
-void ServiceRegistryImpl::BindRemoteServiceProvider(
- shell::mojom::InterfaceProviderPtr service_provider) {
- CHECK(!remote_provider_);
- remote_provider_ = std::move(service_provider);
- while (!pending_connects_.empty()) {
- remote_provider_->GetInterface(
- mojo::String::From(pending_connects_.front().first),
- mojo::ScopedMessagePipeHandle(pending_connects_.front().second));
- pending_connects_.pop();
- }
-}
-
-void ServiceRegistryImpl::AddService(const std::string& service_name,
- const ServiceFactory& service_factory) {
- service_factories_[service_name] = service_factory;
-}
-
-void ServiceRegistryImpl::RemoveService(const std::string& service_name) {
- service_factories_.erase(service_name);
-}
-
-void ServiceRegistryImpl::ConnectToRemoteService(
- base::StringPiece service_name,
- mojo::ScopedMessagePipeHandle handle) {
- auto override_it = service_overrides_.find(service_name.as_string());
- if (override_it != service_overrides_.end()) {
- override_it->second.Run(std::move(handle));
- return;
- }
-
- if (!remote_provider_) {
- pending_connects_.push(
- std::make_pair(service_name.as_string(), handle.release()));
- return;
- }
- remote_provider_->GetInterface(
- mojo::String::From(service_name.as_string()), std::move(handle));
-}
-
-void ServiceRegistryImpl::AddServiceOverrideForTesting(
- const std::string& service_name,
- const ServiceFactory& factory) {
- service_overrides_[service_name] = factory;
-}
-
-void ServiceRegistryImpl::ClearServiceOverridesForTesting() {
- service_overrides_.clear();
-}
-
-bool ServiceRegistryImpl::IsBound() const {
- return binding_.is_bound();
-}
-
-base::WeakPtr<ServiceRegistry> ServiceRegistryImpl::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
-}
-
-void ServiceRegistryImpl::GetInterface(
- const mojo::String& name,
- mojo::ScopedMessagePipeHandle client_handle) {
- auto it = service_factories_.find(name);
- if (it == service_factories_.end()) {
- DLOG(ERROR) << name << " not found";
- return;
- }
-
- // It's possible and effectively unavoidable that under certain conditions
- // an invalid handle may be received. Don't invoke the factory in that case.
- if (!client_handle.is_valid()) {
- DVLOG(2) << "Invalid pipe handle for " << name << " interface request.";
- return;
- }
-
- it->second.Run(std::move(client_handle));
-}
-
-void ServiceRegistryImpl::OnConnectionError() {
- binding_.Close();
-}
-
-} // namespace content
diff --git a/chromium/content/common/mojo/service_registry_impl.h b/chromium/content/common/mojo/service_registry_impl.h
deleted file mode 100644
index 38122cd7027..00000000000
--- a/chromium/content/common/mojo/service_registry_impl.h
+++ /dev/null
@@ -1,70 +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_COMMON_MOJO_SERVICE_REGISTRY_IMPL_H_
-#define CONTENT_COMMON_MOJO_SERVICE_REGISTRY_IMPL_H_
-
-#include <map>
-#include <queue>
-#include <string>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/common/service_registry.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace content {
-
-class CONTENT_EXPORT ServiceRegistryImpl
- : public ServiceRegistry,
- public NON_EXPORTED_BASE(shell::mojom::InterfaceProvider) {
- public:
- using ServiceFactory = base::Callback<void(mojo::ScopedMessagePipeHandle)>;
-
- ServiceRegistryImpl();
- ~ServiceRegistryImpl() override;
-
- // ServiceRegistry overrides.
- void Bind(shell::mojom::InterfaceProviderRequest request) override;
- void BindRemoteServiceProvider(
- shell::mojom::InterfaceProviderPtr service_provider) override;
- void AddService(const std::string& service_name,
- const ServiceFactory& service_factory) override;
- void RemoveService(const std::string& service_name) override;
- void ConnectToRemoteService(base::StringPiece service_name,
- mojo::ScopedMessagePipeHandle handle) override;
- void AddServiceOverrideForTesting(
- const std::string& service_name,
- const ServiceFactory& service_factory) override;
- void ClearServiceOverridesForTesting() override;
-
- bool IsBound() const;
-
- base::WeakPtr<ServiceRegistry> GetWeakPtr();
-
- private:
- // mojo::InterfaceProvider overrides.
- void GetInterface(const mojo::String& name,
- mojo::ScopedMessagePipeHandle client_handle) override;
-
- void OnConnectionError();
-
- mojo::Binding<shell::mojom::InterfaceProvider> binding_;
- shell::mojom::InterfaceProviderPtr remote_provider_;
-
- std::map<std::string, ServiceFactory> service_factories_;
- std::queue<std::pair<std::string, mojo::MessagePipeHandle> >
- pending_connects_;
-
- std::map<std::string, ServiceFactory> service_overrides_;
-
- base::WeakPtrFactory<ServiceRegistry> weak_factory_;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_MOJO_SERVICE_REGISTRY_IMPL_H_
diff --git a/chromium/content/common/navigation_params.cc b/chromium/content/common/navigation_params.cc
index f09cccfebbf..ac2cb9cbe31 100644
--- a/chromium/content/common/navigation_params.cc
+++ b/chromium/content/common/navigation_params.cc
@@ -4,10 +4,13 @@
#include "content/common/navigation_params.h"
+#include "base/logging.h"
#include "build/build_config.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/url_constants.h"
+#include "url/gurl.h"
+#include "url/url_constants.h"
namespace content {
@@ -21,6 +24,7 @@ bool ShouldMakeNetworkRequestForURL(const GURL& url) {
// network stack. Neither should pushState/popState.
return !url.SchemeIs(url::kDataScheme) && url != GURL(url::kAboutBlankURL) &&
!url.SchemeIs(url::kJavaScriptScheme) && !url.is_empty() &&
+ !url.SchemeIs(url::kContentIDScheme) &&
url != GURL(content::kAboutSrcDocURL);
}
@@ -47,7 +51,8 @@ CommonNavigationParams::CommonNavigationParams(
const GURL& history_url_for_data_url,
LoFiState lofi_state,
const base::TimeTicks& navigation_start,
- std::string method)
+ std::string method,
+ const scoped_refptr<ResourceRequestBodyImpl>& post_data)
: url(url),
referrer(referrer),
transition(transition),
@@ -60,7 +65,14 @@ CommonNavigationParams::CommonNavigationParams(
history_url_for_data_url(history_url_for_data_url),
lofi_state(lofi_state),
navigation_start(navigation_start),
- method(method) {}
+ method(method),
+ post_data(post_data) {
+ // |method != "POST"| should imply absence of |post_data|.
+ if (method != "POST" && post_data) {
+ NOTREACHED();
+ this->post_data = nullptr;
+ }
+}
CommonNavigationParams::CommonNavigationParams(
const CommonNavigationParams& other) = default;
@@ -100,14 +112,12 @@ StartNavigationParams::StartNavigationParams()
StartNavigationParams::StartNavigationParams(
const std::string& extra_headers,
- const std::vector<unsigned char>& browser_initiated_post_data,
#if defined(OS_ANDROID)
bool has_user_gesture,
#endif
int transferred_request_child_id,
int transferred_request_request_id)
: extra_headers(extra_headers),
- browser_initiated_post_data(browser_initiated_post_data),
#if defined(OS_ANDROID)
has_user_gesture(has_user_gesture),
#endif
@@ -135,8 +145,7 @@ RequestNavigationParams::RequestNavigationParams()
current_history_list_length(0),
is_view_source(false),
should_clear_history_list(false),
- should_create_service_worker(false),
- service_worker_provider_id(kInvalidServiceWorkerProviderId) {}
+ should_create_service_worker(false) {}
RequestNavigationParams::RequestNavigationParams(
bool is_overriding_user_agent,
@@ -169,8 +178,7 @@ RequestNavigationParams::RequestNavigationParams(
current_history_list_length(current_history_list_length),
is_view_source(is_view_source),
should_clear_history_list(should_clear_history_list),
- should_create_service_worker(false),
- service_worker_provider_id(kInvalidServiceWorkerProviderId) {}
+ should_create_service_worker(false) {}
RequestNavigationParams::RequestNavigationParams(
const RequestNavigationParams& other) = default;
diff --git a/chromium/content/common/navigation_params.h b/chromium/content/common/navigation_params.h
index d2f83e756c1..f08c8bb393d 100644
--- a/chromium/content/common/navigation_params.h
+++ b/chromium/content/common/navigation_params.h
@@ -9,10 +9,12 @@
#include <string>
+#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/common/frame_message_enums.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/public/common/page_state.h"
#include "content/public/common/referrer.h"
#include "content/public/common/request_context_type.h"
@@ -37,7 +39,7 @@ enum LoFiState {
// Helper function to determine if the navigation to |url| should make a request
// to the network stack. A request should not be sent for data URLs, JavaScript
// URLs or about:blank. In these cases, no request needs to be sent.
-bool ShouldMakeNetworkRequestForURL(const GURL& url);
+bool CONTENT_EXPORT ShouldMakeNetworkRequestForURL(const GURL& url);
// The following structures hold parameters used during a navigation. In
// particular they are used by FrameMsg_Navigate, FrameMsg_CommitNavigation and
@@ -48,19 +50,21 @@ bool ShouldMakeNetworkRequestForURL(const GURL& url);
// Used by all navigation IPCs.
struct CONTENT_EXPORT CommonNavigationParams {
CommonNavigationParams();
- CommonNavigationParams(const GURL& url,
- const Referrer& referrer,
- ui::PageTransition transition,
- FrameMsg_Navigate_Type::Value navigation_type,
- bool allow_download,
- bool should_replace_current_entry,
- base::TimeTicks ui_timestamp,
- FrameMsg_UILoadMetricsReportType::Value report_type,
- const GURL& base_url_for_data_url,
- const GURL& history_url_for_data_url,
- LoFiState lofi_state,
- const base::TimeTicks& navigation_start,
- std::string method);
+ CommonNavigationParams(
+ const GURL& url,
+ const Referrer& referrer,
+ ui::PageTransition transition,
+ FrameMsg_Navigate_Type::Value navigation_type,
+ bool allow_download,
+ bool should_replace_current_entry,
+ base::TimeTicks ui_timestamp,
+ FrameMsg_UILoadMetricsReportType::Value report_type,
+ const GURL& base_url_for_data_url,
+ const GURL& history_url_for_data_url,
+ LoFiState lofi_state,
+ const base::TimeTicks& navigation_start,
+ std::string method,
+ const scoped_refptr<ResourceRequestBodyImpl>& post_data);
CommonNavigationParams(const CommonNavigationParams& other);
~CommonNavigationParams();
@@ -118,6 +122,9 @@ struct CONTENT_EXPORT CommonNavigationParams {
// The request method: GET, POST, etc.
std::string method;
+
+ // Body of HTTP POST request.
+ scoped_refptr<ResourceRequestBodyImpl> post_data;
};
// Provided by the renderer ----------------------------------------------------
@@ -172,30 +179,24 @@ struct CONTENT_EXPORT BeginNavigationParams {
// PlzNavigate: These are not used.
struct CONTENT_EXPORT StartNavigationParams {
StartNavigationParams();
- StartNavigationParams(
- const std::string& extra_headers,
- const std::vector<unsigned char>& browser_initiated_post_data,
+ StartNavigationParams(const std::string& extra_headers,
#if defined(OS_ANDROID)
- bool has_user_gesture,
+ bool has_user_gesture,
#endif
- int transferred_request_child_id,
- int transferred_request_request_id);
+ int transferred_request_child_id,
+ int transferred_request_request_id);
StartNavigationParams(const StartNavigationParams& other);
~StartNavigationParams();
// Extra headers (separated by \n) to send during the request.
std::string extra_headers;
- // If is_post is true, holds the post_data information from browser. Empty
- // otherwise.
- std::vector<unsigned char> browser_initiated_post_data;
-
#if defined(OS_ANDROID)
bool has_user_gesture;
#endif
// The following two members identify a previous request that has been
- // created before this navigation is being transferred to a new render view.
+ // created before this navigation is being transferred to a new process.
// This serves the purpose of recycling the old request.
// Unless this refers to a transferred navigation, these values are -1 and -1.
int transferred_request_child_id;
@@ -297,13 +298,6 @@ struct CONTENT_EXPORT RequestNavigationParams {
// Whether a ServiceWorkerProviderHost should be created for the window.
bool should_create_service_worker;
- // PlzNavigate
- // The ServiceWorkerProviderHost ID used for navigations, if it was already
- // created by the browser. Set to kInvalidServiceWorkerProviderId otherwise.
- // This parameter is not used in the current navigation architecture, where
- // it will always be equal to kInvalidServiceWorkerProviderId.
- int service_worker_provider_id;
-
#if defined(OS_ANDROID)
// The real content of the data: URL. Only used in Android WebView for
// implementing LoadDataWithBaseUrl API method to circumvent the restriction
diff --git a/chromium/content/common/navigation_params_unittest.cc b/chromium/content/common/navigation_params_unittest.cc
new file mode 100644
index 00000000000..0dec5df6b9e
--- /dev/null
+++ b/chromium/content/common/navigation_params_unittest.cc
@@ -0,0 +1,28 @@
+// 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/common/navigation_params.h"
+
+#include "content/public/common/browser_side_navigation_policy.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+TEST(NavigationParamsTest, ShouldMakeNetworkRequestForURL) {
+ if (!IsBrowserSideNavigationEnabled())
+ return;
+
+ EXPECT_TRUE(ShouldMakeNetworkRequestForURL(GURL("http://foo/bar.html")));
+ EXPECT_TRUE(ShouldMakeNetworkRequestForURL(GURL("https://foo/bar.html")));
+
+ EXPECT_FALSE(ShouldMakeNetworkRequestForURL(GURL("data://foo")));
+ EXPECT_FALSE(ShouldMakeNetworkRequestForURL(GURL("about:blank")));
+ EXPECT_FALSE(ShouldMakeNetworkRequestForURL(GURL("about:srcdoc")));
+ EXPECT_FALSE(ShouldMakeNetworkRequestForURL(GURL("javascript://foo.js")));
+ EXPECT_FALSE(ShouldMakeNetworkRequestForURL(GURL("cid:foo@bar")));
+ EXPECT_FALSE(ShouldMakeNetworkRequestForURL(GURL()));
+}
+
+} // namespace content
diff --git a/chromium/content/common/net/url_request_user_data.h b/chromium/content/common/net/url_request_user_data.h
index 58d97b7f32a..3af3d0ddc2f 100644
--- a/chromium/content/common/net/url_request_user_data.h
+++ b/chromium/content/common/net/url_request_user_data.h
@@ -10,7 +10,7 @@
namespace content {
// Used to annotate all URLRequests for which the request can be associated
-// with a given render view.
+// with a given RenderFrame.
class URLRequestUserData : public base::SupportsUserData::Data {
public:
URLRequestUserData(int render_process_id,
diff --git a/chromium/content/common/origin_trials/trial_token_validator.cc b/chromium/content/common/origin_trials/trial_token_validator.cc
index f9261fe19a3..3f98ad67e72 100644
--- a/chromium/content/common/origin_trials/trial_token_validator.cc
+++ b/chromium/content/common/origin_trials/trial_token_validator.cc
@@ -7,6 +7,7 @@
#include "base/time/time.h"
#include "content/common/origin_trials/trial_token.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/origin_trial_policy.h"
#include "third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h"
namespace content {
@@ -15,10 +16,18 @@ blink::WebOriginTrialTokenStatus TrialTokenValidator::ValidateToken(
const std::string& token,
const url::Origin& origin,
base::StringPiece feature_name) {
+ ContentClient* content_client = GetContentClient();
+ const OriginTrialPolicy* origin_trial_policy =
+ content_client->GetOriginTrialPolicy();
+ if (!origin_trial_policy)
+ return blink::WebOriginTrialTokenStatus::NotSupported;
+
+ if (origin_trial_policy->IsFeatureDisabled(feature_name))
+ return blink::WebOriginTrialTokenStatus::FeatureDisabled;
+
// TODO(iclelland): Allow for multiple signing keys, and iterate over all
// active keys here. https://crbug.com/543220
- ContentClient* content_client = GetContentClient();
- base::StringPiece public_key = content_client->GetOriginTrialPublicKey();
+ base::StringPiece public_key = origin_trial_policy->GetPublicKey();
if (public_key.empty()) {
return blink::WebOriginTrialTokenStatus::NotSupported;
}
diff --git a/chromium/content/common/origin_trials/trial_token_validator_unittest.cc b/chromium/content/common/origin_trials/trial_token_validator_unittest.cc
index 8cce482bb26..af18d227600 100644
--- a/chromium/content/common/origin_trials/trial_token_validator_unittest.cc
+++ b/chromium/content/common/origin_trials/trial_token_validator_unittest.cc
@@ -5,12 +5,15 @@
#include "content/common/origin_trials/trial_token_validator.h"
#include <memory>
+#include <set>
+#include <string>
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/origin_trial_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h"
#include "url/gurl.h"
@@ -84,14 +87,43 @@ const char kExpiredToken[] =
const char kUnparsableToken[] = "abcde";
-class TestContentClient : public ContentClient {
+class TestOriginTrialPolicy : public OriginTrialPolicy {
public:
- base::StringPiece GetOriginTrialPublicKey() override {
+ base::StringPiece GetPublicKey() const override {
return base::StringPiece(reinterpret_cast<const char*>(key_),
arraysize(kTestPublicKey));
}
- void SetOriginTrialPublicKey(const uint8_t* key) { key_ = key; }
+ bool IsFeatureDisabled(base::StringPiece feature) const override {
+ return disabled_features_.count(feature.as_string()) > 0;
+ }
+
+ // Test setup methods
+ void SetPublicKey(const uint8_t* key) { key_ = key; }
+ void DisableFeature(const std::string& feature) {
+ disabled_features_.insert(feature);
+ }
+
+ private:
const uint8_t* key_ = nullptr;
+ std::set<std::string> disabled_features_;
+};
+
+class TestContentClient : public ContentClient {
+ public:
+ // ContentRendererClient methods
+ OriginTrialPolicy* GetOriginTrialPolicy() override {
+ return &origin_trial_policy_;
+ }
+ // Test setup methods
+ void SetOriginTrialPublicKey(const uint8_t* key) {
+ origin_trial_policy_.SetPublicKey(key);
+ }
+ void DisableFeature(const std::string& feature) {
+ origin_trial_policy_.DisableFeature(feature);
+ }
+
+ private:
+ TestOriginTrialPolicy origin_trial_policy_;
};
} // namespace
@@ -112,6 +144,10 @@ class TrialTokenValidatorTest : public testing::Test {
test_content_client_.SetOriginTrialPublicKey(key);
}
+ void DisableFeature(const std::string& feature) {
+ test_content_client_.DisableFeature(feature);
+ }
+
const url::Origin appropriate_origin_;
const url::Origin inappropriate_origin_;
const url::Origin insecure_origin_;
@@ -168,4 +204,17 @@ TEST_F(TrialTokenValidatorTest, ValidateValidTokenWithIncorrectKey) {
kSampleToken, appropriate_origin_, kAppropriateFeatureName));
}
+TEST_F(TrialTokenValidatorTest, ValidatorRespectsDisabledFeatures) {
+ // Disable an irrelevant feature; token should still validate
+ DisableFeature(kInappropriateFeatureName);
+ EXPECT_EQ(blink::WebOriginTrialTokenStatus::Success,
+ TrialTokenValidator::ValidateToken(
+ kSampleToken, appropriate_origin_, kAppropriateFeatureName));
+ // Disable the token's feature; it should no longer be valid
+ DisableFeature(kAppropriateFeatureName);
+ EXPECT_EQ(blink::WebOriginTrialTokenStatus::FeatureDisabled,
+ TrialTokenValidator::ValidateToken(
+ kSampleToken, appropriate_origin_, kAppropriateFeatureName));
+}
+
} // namespace content
diff --git a/chromium/content/common/page_messages.h b/chromium/content/common/page_messages.h
index afe62b8a24a..77aa978ce9c 100644
--- a/chromium/content/common/page_messages.h
+++ b/chromium/content/common/page_messages.h
@@ -27,6 +27,12 @@ IPC_MESSAGE_ROUTED2(PageMsg_SetZoomLevel,
PageMsg_SetZoomLevel_Command /* command */,
double /* zoom_level */)
+// Informs the renderer that the page was hidden.
+IPC_MESSAGE_ROUTED0(PageMsg_WasHidden)
+
+// Informs the renderer that the page is no longer hidden.
+IPC_MESSAGE_ROUTED0(PageMsg_WasShown)
+
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
diff --git a/chromium/content/common/page_state_serialization.cc b/chromium/content/common/page_state_serialization.cc
index af0db11467f..7a917d6f394 100644
--- a/chromium/content/common/page_state_serialization.cc
+++ b/chromium/content/common/page_state_serialization.cc
@@ -10,10 +10,12 @@
#include <limits>
#include "base/pickle.h"
+#include "base/strings/nullable_string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "content/common/resource_request_body_impl.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -26,58 +28,52 @@ float g_device_scale_factor_for_testing = 0.0;
//-----------------------------------------------------------------------------
-void AppendDataToHttpBody(ExplodedHttpBody* http_body, const char* data,
- int data_length) {
- ExplodedHttpBodyElement element;
- element.type = blink::WebHTTPBody::Element::TypeData;
- element.data.assign(data, data_length);
- http_body->elements.push_back(element);
-}
-
-void AppendFileRangeToHttpBody(ExplodedHttpBody* http_body,
- const base::NullableString16& file_path,
- int file_start,
- int file_length,
- double file_modification_time) {
- ExplodedHttpBodyElement element;
- element.type = blink::WebHTTPBody::Element::TypeFile;
- element.file_path = file_path;
- element.file_start = file_start;
- element.file_length = file_length;
- element.file_modification_time = file_modification_time;
- http_body->elements.push_back(element);
-}
-
-void AppendURLRangeToHttpBody(ExplodedHttpBody* http_body,
- const GURL& url,
- int file_start,
- int file_length,
- double file_modification_time) {
- ExplodedHttpBodyElement element;
- element.type = blink::WebHTTPBody::Element::TypeFileSystemURL;
- element.filesystem_url = url;
- element.file_start = file_start;
- element.file_length = file_length;
- element.file_modification_time = file_modification_time;
- http_body->elements.push_back(element);
-}
-
-void AppendBlobToHttpBody(ExplodedHttpBody* http_body,
- const std::string& uuid) {
- ExplodedHttpBodyElement element;
- element.type = blink::WebHTTPBody::Element::TypeBlob;
- element.blob_uuid = uuid;
- http_body->elements.push_back(element);
+void AppendDataToRequestBody(
+ const scoped_refptr<ResourceRequestBodyImpl>& request_body,
+ const char* data,
+ int data_length) {
+ request_body->AppendBytes(data, data_length);
+}
+
+void AppendFileRangeToRequestBody(
+ const scoped_refptr<ResourceRequestBodyImpl>& request_body,
+ const base::NullableString16& file_path,
+ int file_start,
+ int file_length,
+ double file_modification_time) {
+ request_body->AppendFileRange(
+ base::FilePath::FromUTF16Unsafe(file_path.string()),
+ static_cast<uint64_t>(file_start), static_cast<uint64_t>(file_length),
+ base::Time::FromDoubleT(file_modification_time));
+}
+
+void AppendURLRangeToRequestBody(
+ const scoped_refptr<ResourceRequestBodyImpl>& request_body,
+ const GURL& url,
+ int file_start,
+ int file_length,
+ double file_modification_time) {
+ request_body->AppendFileSystemFileRange(
+ url, static_cast<uint64_t>(file_start),
+ static_cast<uint64_t>(file_length),
+ base::Time::FromDoubleT(file_modification_time));
+}
+
+void AppendBlobToRequestBody(
+ const scoped_refptr<ResourceRequestBodyImpl>& request_body,
+ const std::string& uuid) {
+ request_body->AppendBlob(uuid);
}
//----------------------------------------------------------------------------
void AppendReferencedFilesFromHttpBody(
- const std::vector<ExplodedHttpBodyElement>& elements,
+ const std::vector<ResourceRequestBodyImpl::Element>& elements,
std::vector<base::NullableString16>* referenced_files) {
for (size_t i = 0; i < elements.size(); ++i) {
- if (elements[i].type == blink::WebHTTPBody::Element::TypeFile)
- referenced_files->push_back(elements[i].file_path);
+ if (elements[i].type() == ResourceRequestBodyImpl::Element::TYPE_FILE)
+ referenced_files->push_back(
+ base::NullableString16(elements[i].path().AsUTF16Unsafe(), false));
}
}
@@ -141,9 +137,9 @@ bool AppendReferencedFilesFromDocumentState(
bool RecursivelyAppendReferencedFiles(
const ExplodedFrameState& frame_state,
std::vector<base::NullableString16>* referenced_files) {
- if (!frame_state.http_body.is_null) {
- AppendReferencedFilesFromHttpBody(frame_state.http_body.elements,
- referenced_files);
+ if (frame_state.http_body.request_body != nullptr) {
+ AppendReferencedFilesFromHttpBody(
+ *frame_state.http_body.request_body->elements(), referenced_files);
}
if (!AppendReferencedFilesFromDocumentState(frame_state.document_state,
@@ -396,48 +392,48 @@ void ReadStringVector(SerializeObject* obj,
(*result)[i] = ReadString(obj);
}
-// Writes an ExplodedHttpBody object into a SerializeObject for serialization.
-void WriteHttpBody(const ExplodedHttpBody& http_body, SerializeObject* obj) {
- WriteBoolean(!http_body.is_null, obj);
-
- if (http_body.is_null)
- return;
-
- WriteAndValidateVectorSize(http_body.elements, obj);
- for (size_t i = 0; i < http_body.elements.size(); ++i) {
- const ExplodedHttpBodyElement& element = http_body.elements[i];
- WriteInteger(element.type, obj);
- if (element.type == blink::WebHTTPBody::Element::TypeData) {
- WriteData(element.data.data(), static_cast<int>(element.data.size()),
- obj);
- } else if (element.type == blink::WebHTTPBody::Element::TypeFile) {
- WriteString(element.file_path, obj);
- WriteInteger64(element.file_start, obj);
- WriteInteger64(element.file_length, obj);
- WriteReal(element.file_modification_time, obj);
- } else if (element.type ==
- blink::WebHTTPBody::Element::TypeFileSystemURL) {
- WriteGURL(element.filesystem_url, obj);
- WriteInteger64(element.file_start, obj);
- WriteInteger64(element.file_length, obj);
- WriteReal(element.file_modification_time, obj);
- } else {
- DCHECK(element.type == blink::WebHTTPBody::Element::TypeBlob);
- WriteStdString(element.blob_uuid, obj);
+void WriteResourceRequestBody(const ResourceRequestBodyImpl& request_body,
+ SerializeObject* obj) {
+ WriteAndValidateVectorSize(*request_body.elements(), obj);
+ for (const auto& element : *request_body.elements()) {
+ switch (element.type()) {
+ case ResourceRequestBodyImpl::Element::TYPE_BYTES:
+ WriteInteger(blink::WebHTTPBody::Element::TypeData, obj);
+ WriteData(element.bytes(), static_cast<int>(element.length()), obj);
+ break;
+ case ResourceRequestBodyImpl::Element::TYPE_FILE:
+ WriteInteger(blink::WebHTTPBody::Element::TypeFile, obj);
+ WriteString(
+ base::NullableString16(element.path().AsUTF16Unsafe(), false), obj);
+ WriteInteger64(static_cast<int64_t>(element.offset()), obj);
+ WriteInteger64(static_cast<int64_t>(element.length()), obj);
+ WriteReal(element.expected_modification_time().ToDoubleT(), obj);
+ break;
+ case ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM:
+ WriteInteger(blink::WebHTTPBody::Element::TypeFileSystemURL, obj);
+ WriteGURL(element.filesystem_url(), obj);
+ WriteInteger64(static_cast<int64_t>(element.offset()), obj);
+ WriteInteger64(static_cast<int64_t>(element.length()), obj);
+ WriteReal(element.expected_modification_time().ToDoubleT(), obj);
+ break;
+ case ResourceRequestBodyImpl::Element::TYPE_BLOB:
+ WriteInteger(blink::WebHTTPBody::Element::TypeBlob, obj);
+ WriteStdString(element.blob_uuid(), obj);
+ break;
+ case ResourceRequestBodyImpl::Element::TYPE_BYTES_DESCRIPTION:
+ case ResourceRequestBodyImpl::Element::TYPE_DISK_CACHE_ENTRY:
+ default:
+ NOTREACHED();
+ continue;
}
}
- WriteInteger64(http_body.identifier, obj);
- WriteBoolean(http_body.contains_passwords, obj);
+ WriteInteger64(request_body.identifier(), obj);
}
-void ReadHttpBody(SerializeObject* obj, ExplodedHttpBody* http_body) {
- // An initial boolean indicates if we have an HTTP body.
- if (!ReadBoolean(obj))
- return;
- http_body->is_null = false;
-
+void ReadResourceRequestBody(
+ SerializeObject* obj,
+ const scoped_refptr<ResourceRequestBodyImpl>& request_body) {
int num_elements = ReadInteger(obj);
-
for (int i = 0; i < num_elements; ++i) {
int type = ReadInteger(obj);
if (type == blink::WebHTTPBody::Element::TypeData) {
@@ -445,33 +441,53 @@ void ReadHttpBody(SerializeObject* obj, ExplodedHttpBody* http_body) {
int length = -1;
ReadData(obj, &data, &length);
if (length >= 0) {
- AppendDataToHttpBody(http_body, static_cast<const char*>(data),
- length);
+ AppendDataToRequestBody(request_body, static_cast<const char*>(data),
+ length);
}
} else if (type == blink::WebHTTPBody::Element::TypeFile) {
base::NullableString16 file_path = ReadString(obj);
int64_t file_start = ReadInteger64(obj);
int64_t file_length = ReadInteger64(obj);
double file_modification_time = ReadReal(obj);
- AppendFileRangeToHttpBody(http_body, file_path, file_start, file_length,
- file_modification_time);
+ AppendFileRangeToRequestBody(request_body, file_path, file_start,
+ file_length, file_modification_time);
} else if (type == blink::WebHTTPBody::Element::TypeFileSystemURL) {
GURL url = ReadGURL(obj);
int64_t file_start = ReadInteger64(obj);
int64_t file_length = ReadInteger64(obj);
double file_modification_time = ReadReal(obj);
- AppendURLRangeToHttpBody(http_body, url, file_start, file_length,
- file_modification_time);
+ AppendURLRangeToRequestBody(request_body, url, file_start, file_length,
+ file_modification_time);
} else if (type == blink::WebHTTPBody::Element::TypeBlob) {
if (obj->version >= 16) {
std::string blob_uuid = ReadStdString(obj);
- AppendBlobToHttpBody(http_body, blob_uuid);
+ AppendBlobToRequestBody(request_body, blob_uuid);
} else {
ReadGURL(obj); // Skip the obsolete blob url value.
}
}
}
- http_body->identifier = ReadInteger64(obj);
+ request_body->set_identifier(ReadInteger64(obj));
+}
+
+// Writes an ExplodedHttpBody object into a SerializeObject for serialization.
+void WriteHttpBody(const ExplodedHttpBody& http_body, SerializeObject* obj) {
+ bool is_null = http_body.request_body == nullptr;
+ WriteBoolean(!is_null, obj);
+ if (is_null)
+ return;
+
+ WriteResourceRequestBody(*http_body.request_body, obj);
+ WriteBoolean(http_body.contains_passwords, obj);
+}
+
+void ReadHttpBody(SerializeObject* obj, ExplodedHttpBody* http_body) {
+ // An initial boolean indicates if we have an HTTP body.
+ if (!ReadBoolean(obj))
+ return;
+
+ http_body->request_body = new ResourceRequestBodyImpl();
+ ReadResourceRequestBody(obj, http_body->request_body);
if (obj->version >= 12)
http_body->contains_passwords = ReadBoolean(obj);
@@ -666,24 +682,7 @@ void ReadPageState(SerializeObject* obj, ExplodedPageState* state) {
} // namespace
-ExplodedHttpBodyElement::ExplodedHttpBodyElement()
- : type(blink::WebHTTPBody::Element::TypeData),
- file_start(0),
- file_length(-1),
- file_modification_time(std::numeric_limits<double>::quiet_NaN()) {
-}
-
-ExplodedHttpBodyElement::ExplodedHttpBodyElement(
- const ExplodedHttpBodyElement& other) = default;
-
-ExplodedHttpBodyElement::~ExplodedHttpBodyElement() {
-}
-
-ExplodedHttpBody::ExplodedHttpBody()
- : identifier(0),
- contains_passwords(false),
- is_null(true) {
-}
+ExplodedHttpBody::ExplodedHttpBody() : contains_passwords(false) {}
ExplodedHttpBody::~ExplodedHttpBody() {
}
@@ -760,6 +759,24 @@ bool DecodePageStateWithDeviceScaleFactorForTesting(
g_device_scale_factor_for_testing = 0.0;
return rv;
}
+
+scoped_refptr<ResourceRequestBodyImpl> DecodeResourceRequestBody(
+ const char* data,
+ size_t size) {
+ scoped_refptr<ResourceRequestBodyImpl> result = new ResourceRequestBodyImpl();
+ SerializeObject obj(data, static_cast<int>(size));
+ ReadResourceRequestBody(&obj, result);
+ return obj.parse_error ? nullptr : result;
+}
+
+std::string EncodeResourceRequestBody(
+ const ResourceRequestBodyImpl& resource_request_body) {
+ SerializeObject obj;
+ obj.version = kCurrentVersion;
+ WriteResourceRequestBody(resource_request_body, &obj);
+ return obj.GetAsString();
+}
+
#endif
} // namespace content
diff --git a/chromium/content/common/page_state_serialization.h b/chromium/content/common/page_state_serialization.h
index 24d81981ef8..90484c4387b 100644
--- a/chromium/content/common/page_state_serialization.h
+++ b/chromium/content/common/page_state_serialization.h
@@ -7,11 +7,13 @@
#include <stdint.h>
+#include <string>
#include <vector>
#include "base/strings/nullable_string16.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
+#include "content/common/resource_request_body_impl.h"
#include "third_party/WebKit/public/platform/WebHTTPBody.h"
#include "third_party/WebKit/public/platform/WebHistoryScrollRestorationType.h"
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
@@ -21,27 +23,10 @@
namespace content {
-struct CONTENT_EXPORT ExplodedHttpBodyElement {
- blink::WebHTTPBody::Element::Type type;
- std::string data;
- base::NullableString16 file_path;
- GURL filesystem_url;
- int64_t file_start;
- int64_t file_length;
- double file_modification_time;
- std::string blob_uuid;
-
- ExplodedHttpBodyElement();
- ExplodedHttpBodyElement(const ExplodedHttpBodyElement& other);
- ~ExplodedHttpBodyElement();
-};
-
struct CONTENT_EXPORT ExplodedHttpBody {
base::NullableString16 http_content_type;
- std::vector<ExplodedHttpBodyElement> elements;
- int64_t identifier;
+ scoped_refptr<ResourceRequestBodyImpl> request_body;
bool contains_passwords;
- bool is_null;
ExplodedHttpBody();
~ExplodedHttpBody();
@@ -73,9 +58,10 @@ private:
};
struct CONTENT_EXPORT ExplodedPageState {
- // TODO(creis): Move referenced_files to ExplodedFrameState.
- // It currently contains a list from all frames, but cannot be deserialized
- // into the files referenced by each frame. See http://crbug.com/441966.
+ // TODO(creis, lukasza): Instead of storing them in |referenced_files|,
+ // extract referenced files from ExplodedHttpBody. |referenced_files|
+ // currently contains a list from all frames, but cannot be deserialized into
+ // the files referenced by each frame. See http://crbug.com/441966.
std::vector<base::NullableString16> referenced_files;
ExplodedFrameState top;
@@ -93,6 +79,17 @@ CONTENT_EXPORT bool DecodePageStateWithDeviceScaleFactorForTesting(
const std::string& encoded,
float device_scale_factor,
ExplodedPageState* exploded);
+
+// Converts results of EncodeResourceRequestBody (passed in as a pair of |data|
+// + |size|) back into a ResourceRequestBodyImpl. Returns nullptr if the
+// decoding fails (e.g. if |data| is malformed).
+scoped_refptr<ResourceRequestBodyImpl> DecodeResourceRequestBody(
+ const char* data,
+ size_t size);
+
+// Encodes |resource_request_body| into |encoded|.
+std::string EncodeResourceRequestBody(
+ const ResourceRequestBodyImpl& resource_request_body);
#endif
} // namespace content
diff --git a/chromium/content/common/page_state_serialization_unittest.cc b/chromium/content/common/page_state_serialization_unittest.cc
index dbf845bbbb3..99039f2a7f7 100644
--- a/chromium/content/common/page_state_serialization_unittest.cc
+++ b/chromium/content/common/page_state_serialization_unittest.cc
@@ -41,28 +41,33 @@ void ExpectEquality(const std::vector<T>& a, const std::vector<T>& b) {
}
template <>
-void ExpectEquality(const ExplodedHttpBodyElement& a,
- const ExplodedHttpBodyElement& b) {
- EXPECT_EQ(a.type, b.type);
- EXPECT_EQ(a.data, b.data);
- EXPECT_EQ(a.file_path, b.file_path);
- EXPECT_EQ(a.filesystem_url, b.filesystem_url);
- EXPECT_EQ(a.file_start, b.file_start);
- EXPECT_EQ(a.file_length, b.file_length);
- if (!(std::isnan(a.file_modification_time) &&
- std::isnan(b.file_modification_time))) {
- EXPECT_DOUBLE_EQ(a.file_modification_time, b.file_modification_time);
+void ExpectEquality(const ResourceRequestBodyImpl::Element& a,
+ const ResourceRequestBodyImpl::Element& b) {
+ EXPECT_EQ(a.type(), b.type());
+ if (a.type() == ResourceRequestBodyImpl::Element::TYPE_BYTES &&
+ b.type() == ResourceRequestBodyImpl::Element::TYPE_BYTES) {
+ EXPECT_EQ(std::string(a.bytes(), a.length()),
+ std::string(b.bytes(), b.length()));
}
- EXPECT_EQ(a.blob_uuid, b.blob_uuid);
+ EXPECT_EQ(a.path(), b.path());
+ EXPECT_EQ(a.filesystem_url(), b.filesystem_url());
+ EXPECT_EQ(a.offset(), b.offset());
+ EXPECT_EQ(a.length(), b.length());
+ EXPECT_EQ(a.expected_modification_time(), b.expected_modification_time());
+ EXPECT_EQ(a.blob_uuid(), b.blob_uuid());
}
template <>
void ExpectEquality(const ExplodedHttpBody& a, const ExplodedHttpBody& b) {
EXPECT_EQ(a.http_content_type, b.http_content_type);
- EXPECT_EQ(a.identifier, b.identifier);
EXPECT_EQ(a.contains_passwords, b.contains_passwords);
- EXPECT_EQ(a.is_null, b.is_null);
- ExpectEquality(a.elements, b.elements);
+ if (a.request_body == nullptr || b.request_body == nullptr) {
+ EXPECT_EQ(nullptr, a.request_body);
+ EXPECT_EQ(nullptr, b.request_body);
+ } else {
+ EXPECT_EQ(a.request_body->identifier(), b.request_body->identifier());
+ ExpectEquality(*a.request_body->elements(), *b.request_body->elements());
+ }
}
template <>
@@ -114,25 +119,20 @@ class PageStateSerializationTest : public testing::Test {
void PopulateHttpBody(ExplodedHttpBody* http_body,
std::vector<base::NullableString16>* referenced_files) {
- http_body->is_null = false;
- http_body->identifier = 12345;
+ http_body->request_body = new ResourceRequestBodyImpl();
+ http_body->request_body->set_identifier(12345);
http_body->contains_passwords = false;
http_body->http_content_type = NS16("text/foo");
- ExplodedHttpBodyElement e1;
- e1.type = blink::WebHTTPBody::Element::TypeData;
- e1.data = "foo";
- http_body->elements.push_back(e1);
+ std::string test_body("foo");
+ http_body->request_body->AppendBytes(test_body.data(), test_body.size());
- ExplodedHttpBodyElement e2;
- e2.type = blink::WebHTTPBody::Element::TypeFile;
- e2.file_path = NS16("file.txt");
- e2.file_start = 100;
- e2.file_length = 1024;
- e2.file_modification_time = 9999.0;
- http_body->elements.push_back(e2);
+ base::FilePath path(FILE_PATH_LITERAL("file.txt"));
+ http_body->request_body->AppendFileRange(base::FilePath(path), 100, 1024,
+ base::Time::FromDoubleT(9999.0));
- referenced_files->push_back(e2.file_path);
+ referenced_files->push_back(
+ base::NullableString16(path.AsUTF16Unsafe(), false));
}
void PopulateFrameStateForBackwardsCompatTest(
@@ -163,23 +163,20 @@ class PageStateSerializationTest : public testing::Test {
if (!is_child) {
frame_state->http_body.http_content_type = NS16("foo/bar");
- frame_state->http_body.identifier = 789;
- frame_state->http_body.is_null = false;
-
- ExplodedHttpBodyElement e1;
- e1.type = blink::WebHTTPBody::Element::TypeData;
- e1.data = "first data block";
- frame_state->http_body.elements.push_back(e1);
-
- ExplodedHttpBodyElement e2;
- e2.type = blink::WebHTTPBody::Element::TypeFile;
- e2.file_path = NS16("file.txt");
- frame_state->http_body.elements.push_back(e2);
-
- ExplodedHttpBodyElement e3;
- e3.type = blink::WebHTTPBody::Element::TypeData;
- e3.data = "data the second";
- frame_state->http_body.elements.push_back(e3);
+ frame_state->http_body.request_body = new ResourceRequestBodyImpl();
+ frame_state->http_body.request_body->set_identifier(789);
+
+ std::string test_body("first data block");
+ frame_state->http_body.request_body->AppendBytes(test_body.data(),
+ test_body.size());
+
+ frame_state->http_body.request_body->AppendFileRange(
+ base::FilePath(FILE_PATH_LITERAL("file.txt")), 0,
+ std::numeric_limits<uint64_t>::max(), base::Time::FromDoubleT(0.0));
+
+ std::string test_body2("data the second");
+ frame_state->http_body.request_body->AppendBytes(test_body2.data(),
+ test_body2.size());
ExplodedFrameState child_state;
PopulateFrameStateForBackwardsCompatTest(&child_state, true);
diff --git a/chromium/content/common/pepper_messages.h b/chromium/content/common/pepper_messages.h
deleted file mode 100644
index caeb7a55a44..00000000000
--- a/chromium/content/common/pepper_messages.h
+++ /dev/null
@@ -1,28 +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.
-
-// Multiply-included message file, no traditional include guard
-#include "content/common/content_export.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_platform_file.h"
-#include "ppapi/c/private/ppb_flash.h"
-#include "ppapi/proxy/ppapi_param_traits.h"
-#include "url/gurl.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-#define IPC_MESSAGE_START PepperMsgStart
-
-IPC_ENUM_TRAITS(PP_FlashLSORestrictions)
-
-// Pepper (non-file-system) messages sent from the renderer to the browser.
-
-IPC_SYNC_MESSAGE_CONTROL1_1(PepperMsg_GetLocalTimeZoneOffset,
- base::Time /* t */,
- double /* result */)
-
-IPC_SYNC_MESSAGE_CONTROL2_1(PepperMsg_GetLocalDataRestrictions,
- GURL /* document_url */,
- GURL /* plugin_url */,
- PP_FlashLSORestrictions /* restrictions */)
diff --git a/chromium/content/common/platform_notification_messages.h b/chromium/content/common/platform_notification_messages.h
index dc79fe4fc24..7f27b8b4168 100644
--- a/chromium/content/common/platform_notification_messages.h
+++ b/chromium/content/common/platform_notification_messages.h
@@ -14,8 +14,6 @@
#include "content/public/common/notification_resources.h"
#include "content/public/common/platform_notification_data.h"
#include "ipc/ipc_message_macros.h"
-#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
-#include "third_party/skia/include/core/SkBitmap.h"
// Singly-included section for type definitions.
#ifndef CONTENT_COMMON_PLATFORM_NOTIFICATION_MESSAGES_H_
@@ -125,8 +123,3 @@ IPC_MESSAGE_CONTROL1(PlatformNotificationHostMsg_Close,
IPC_MESSAGE_CONTROL2(PlatformNotificationHostMsg_ClosePersistent,
GURL /* origin */,
int64_t /* persistent_notification_id */)
-
-IPC_SYNC_MESSAGE_CONTROL1_1(
- PlatformNotificationHostMsg_CheckPermission,
- GURL /* origin */,
- blink::mojom::PermissionStatus /* permission_status */)
diff --git a/chromium/content/common/plugin_list.cc b/chromium/content/common/plugin_list.cc
index eff0f66b269..9d650aac1d1 100644
--- a/chromium/content/common/plugin_list.cc
+++ b/chromium/content/common/plugin_list.cc
@@ -172,7 +172,7 @@ void PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) {
base::AutoLock lock(lock_);
// If we haven't been invalidated in the mean time, mark the plugin list as
- // up-to-date.
+ // up to date.
if (loading_state_ != LOADING_STATE_NEEDS_REFRESH)
loading_state_ = LOADING_STATE_UP_TO_DATE;
diff --git a/chromium/content/common/plugin_list.h b/chromium/content/common/plugin_list.h
index b18b061043b..e321ebafaa1 100644
--- a/chromium/content/common/plugin_list.h
+++ b/chromium/content/common/plugin_list.h
@@ -75,7 +75,7 @@ class CONTENT_EXPORT PluginList {
void GetPlugins(std::vector<WebPluginInfo>* plugins);
// Copies the list of plugins into |plugins| without loading them.
- // Returns true if the list of plugins is up-to-date.
+ // Returns true if the list of plugins is up to date.
bool GetPluginsNoRefresh(std::vector<WebPluginInfo>* plugins);
// Returns a list in |info| containing plugins that are found for
@@ -156,7 +156,7 @@ class CONTENT_EXPORT PluginList {
// States whether we will load the plugin list the next time we try to access
// it, whether we are currently in the process of loading it, or whether we
- // consider it up-to-date.
+ // consider it up to date.
LoadingState loading_state_;
// Extra plugin paths that we want to search when loading.
diff --git a/chromium/content/common/render_frame_setup.mojom b/chromium/content/common/render_frame_setup.mojom
deleted file mode 100644
index b020f420628..00000000000
--- a/chromium/content/common/render_frame_setup.mojom
+++ /dev/null
@@ -1,14 +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.
-
-module content.mojom;
-
-import "services/shell/public/interfaces/interface_provider.mojom";
-
-interface RenderFrameSetup {
- ExchangeInterfaceProviders(
- int32 frame_routing_id,
- shell.mojom.InterfaceProvider& remote_interfaces,
- shell.mojom.InterfaceProvider local_interfaces);
-};
diff --git a/chromium/content/common/render_process_messages.h b/chromium/content/common/render_process_messages.h
index d306b4e1df5..d72a2b3d14c 100644
--- a/chromium/content/common/render_process_messages.h
+++ b/chromium/content/common/render_process_messages.h
@@ -84,8 +84,4 @@ IPC_SYNC_MESSAGE_CONTROL1_3(RenderProcessHostMsg_LoadFont,
IPC_SYNC_MESSAGE_CONTROL2_0(RenderProcessHostMsg_PreCacheFontCharacters,
LOGFONT /* font_data */,
base::string16 /* characters */)
-
-// Asks the browser for the user's monitor profile.
-IPC_SYNC_MESSAGE_CONTROL0_1(RenderProcessHostMsg_GetMonitorColorProfile,
- std::vector<char> /* profile */)
#endif
diff --git a/chromium/content/common/resource_messages.cc b/chromium/content/common/resource_messages.cc
index f30501476f4..3b738693c74 100644
--- a/chromium/content/common/resource_messages.cc
+++ b/chromium/content/common/resource_messages.cc
@@ -389,8 +389,9 @@ void ParamTraits<net::LoadTimingInfo>::Log(const param_type& p,
l->append(")");
}
-void ParamTraits<scoped_refptr<content::ResourceRequestBody>>::GetSize(
- base::PickleSizer* s, const param_type& p) {
+void ParamTraits<scoped_refptr<content::ResourceRequestBodyImpl>>::GetSize(
+ base::PickleSizer* s,
+ const param_type& p) {
GetParamSize(s, p.get() != NULL);
if (p.get()) {
GetParamSize(s, *p->elements());
@@ -398,7 +399,7 @@ void ParamTraits<scoped_refptr<content::ResourceRequestBody>>::GetSize(
}
}
-void ParamTraits<scoped_refptr<content::ResourceRequestBody>>::Write(
+void ParamTraits<scoped_refptr<content::ResourceRequestBodyImpl>>::Write(
base::Pickle* m,
const param_type& p) {
WriteParam(m, p.get() != NULL);
@@ -408,7 +409,7 @@ void ParamTraits<scoped_refptr<content::ResourceRequestBody>>::Write(
}
}
-bool ParamTraits<scoped_refptr<content::ResourceRequestBody>>::Read(
+bool ParamTraits<scoped_refptr<content::ResourceRequestBodyImpl>>::Read(
const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
@@ -423,15 +424,16 @@ bool ParamTraits<scoped_refptr<content::ResourceRequestBody>>::Read(
int64_t identifier;
if (!ReadParam(m, iter, &identifier))
return false;
- *r = new content::ResourceRequestBody;
+ *r = new content::ResourceRequestBodyImpl;
(*r)->swap_elements(&elements);
(*r)->set_identifier(identifier);
return true;
}
-void ParamTraits<scoped_refptr<content::ResourceRequestBody> >::Log(
- const param_type& p, std::string* l) {
- l->append("<ResourceRequestBody>");
+void ParamTraits<scoped_refptr<content::ResourceRequestBodyImpl>>::Log(
+ const param_type& p,
+ std::string* l) {
+ l->append("<ResourceRequestBodyImpl>");
}
void ParamTraits<scoped_refptr<net::ct::SignedCertificateTimestamp>>::GetSize(
diff --git a/chromium/content/common/resource_messages.h b/chromium/content/common/resource_messages.h
index c74a4e81056..0f343e72c8c 100644
--- a/chromium/content/common/resource_messages.h
+++ b/chromium/content/common/resource_messages.h
@@ -15,7 +15,7 @@
#include "content/common/content_param_traits_macros.h"
#include "content/common/navigation_params.h"
#include "content/common/resource_request.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/common/resource_request_completion_status.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/common_param_traits.h"
@@ -86,8 +86,8 @@ struct ParamTraits<net::LoadTimingInfo> {
};
template <>
-struct ParamTraits<scoped_refptr<content::ResourceRequestBody> > {
- typedef scoped_refptr<content::ResourceRequestBody> param_type;
+struct ParamTraits<scoped_refptr<content::ResourceRequestBodyImpl>> {
+ typedef scoped_refptr<content::ResourceRequestBodyImpl> param_type;
static void GetSize(base::PickleSizer* s, const param_type& p);
static void Write(base::Pickle* m, const param_type& p);
static bool Read(const base::Pickle* m,
@@ -129,6 +129,9 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::FetchCredentialsMode,
IPC_ENUM_TRAITS_MAX_VALUE(content::FetchRedirectMode,
content::FetchRedirectMode::LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::SkipServiceWorker,
+ content::SkipServiceWorker::LAST)
+
IPC_ENUM_TRAITS_MAX_VALUE(
net::NetworkQualityEstimator::EffectiveConnectionType,
net::NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_LAST - 1)
@@ -180,14 +183,19 @@ IPC_STRUCT_TRAITS_BEGIN(content::ResourceResponseInfo)
IPC_STRUCT_TRAITS_MEMBER(is_using_lofi)
IPC_STRUCT_TRAITS_MEMBER(effective_connection_type)
IPC_STRUCT_TRAITS_MEMBER(signed_certificate_timestamps)
+ IPC_STRUCT_TRAITS_MEMBER(cors_exposed_header_names)
IPC_STRUCT_TRAITS_END()
+IPC_ENUM_TRAITS_MAX_VALUE(net::URLRequest::ReferrerPolicy,
+ net::URLRequest::MAX_REFERRER_POLICY - 1)
+
IPC_STRUCT_TRAITS_BEGIN(net::RedirectInfo)
IPC_STRUCT_TRAITS_MEMBER(status_code)
IPC_STRUCT_TRAITS_MEMBER(new_method)
IPC_STRUCT_TRAITS_MEMBER(new_url)
IPC_STRUCT_TRAITS_MEMBER(new_first_party_for_cookies)
IPC_STRUCT_TRAITS_MEMBER(new_referrer)
+ IPC_STRUCT_TRAITS_MEMBER(new_referrer_policy)
IPC_STRUCT_TRAITS_MEMBER(referred_token_binding_host)
IPC_STRUCT_TRAITS_END()
@@ -240,6 +248,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::ResourceRequest)
IPC_STRUCT_TRAITS_MEMBER(report_raw_headers)
IPC_STRUCT_TRAITS_MEMBER(lofi_state)
IPC_STRUCT_TRAITS_MEMBER(resource_body_stream_url)
+ IPC_STRUCT_TRAITS_MEMBER(initiated_in_secure_context)
IPC_STRUCT_TRAITS_END()
// Parameters for a ResourceMsg_RequestComplete
diff --git a/chromium/content/common/resource_request.h b/chromium/content/common/resource_request.h
index d59dbf78dac..83263cc5c1c 100644
--- a/chromium/content/common/resource_request.h
+++ b/chromium/content/common/resource_request.h
@@ -11,7 +11,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/common/navigation_params.h"
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/appcache_info.h"
#include "content/public/common/request_context_frame_type.h"
@@ -93,8 +93,8 @@ struct CONTENT_EXPORT ResourceRequest {
// fetch() in the Service Worker script.
bool originated_from_service_worker = false;
- // True if the request should not be handled by the ServiceWorker.
- bool skip_service_worker = false;
+ // Indicates which types of ServiceWorkers should skip handling this request.
+ SkipServiceWorker skip_service_worker = SkipServiceWorker::NONE;
// The request mode passed to the ServiceWorker.
FetchRequestMode fetch_request_mode = FETCH_REQUEST_MODE_SAME_ORIGIN;
@@ -114,7 +114,7 @@ struct CONTENT_EXPORT ResourceRequest {
REQUEST_CONTEXT_FRAME_TYPE_AUXILIARY;
// Optional resource request body (may be null).
- scoped_refptr<ResourceRequestBody> request_body;
+ scoped_refptr<ResourceRequestBodyImpl> request_body;
bool download_to_file = false;
@@ -150,7 +150,7 @@ struct CONTENT_EXPORT ResourceRequest {
bool should_replace_current_entry = false;
// The following two members identify a previous request that has been
- // created before this navigation has been transferred to a new render view.
+ // created before this navigation has been transferred to a new process.
// This serves the purpose of recycling the old request.
// Unless this refers to a transferred navigation, these values are -1 and -1.
int transferred_request_child_id = -1;
@@ -170,6 +170,9 @@ struct CONTENT_EXPORT ResourceRequest {
// access to the body of the response that has already been fetched by the
// browser.
GURL resource_body_stream_url;
+
+ // Wether or not the initiator of this request is a secure context.
+ bool initiated_in_secure_context = false;
};
} // namespace content
diff --git a/chromium/content/common/resource_request_body.cc b/chromium/content/common/resource_request_body_impl.cc
index 2aa3f7ec2fa..80212bd96a1 100644
--- a/chromium/content/common/resource_request_body.cc
+++ b/chromium/content/common/resource_request_body_impl.cc
@@ -2,22 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/resource_request_body.h"
+#include "content/common/resource_request_body_impl.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "content/common/page_state_serialization.h"
+
+using blink::WebHTTPBody;
+using blink::WebString;
namespace content {
-ResourceRequestBody::ResourceRequestBody()
- : identifier_(0) {
-}
+ResourceRequestBodyImpl::ResourceRequestBodyImpl() : identifier_(0) {}
-void ResourceRequestBody::AppendBytes(const char* bytes, int bytes_len) {
+void ResourceRequestBodyImpl::AppendBytes(const char* bytes, int bytes_len) {
if (bytes_len > 0) {
elements_.push_back(Element());
elements_.back().SetToBytes(bytes, bytes_len);
}
}
-void ResourceRequestBody::AppendFileRange(
+void ResourceRequestBodyImpl::AppendFileRange(
const base::FilePath& file_path,
uint64_t offset,
uint64_t length,
@@ -27,12 +31,12 @@ void ResourceRequestBody::AppendFileRange(
expected_modification_time);
}
-void ResourceRequestBody::AppendBlob(const std::string& uuid) {
+void ResourceRequestBodyImpl::AppendBlob(const std::string& uuid) {
elements_.push_back(Element());
elements_.back().SetToBlob(uuid);
}
-void ResourceRequestBody::AppendFileSystemFileRange(
+void ResourceRequestBodyImpl::AppendFileSystemFileRange(
const GURL& url,
uint64_t offset,
uint64_t length,
@@ -42,7 +46,16 @@ void ResourceRequestBody::AppendFileSystemFileRange(
expected_modification_time);
}
-ResourceRequestBody::~ResourceRequestBody() {
+std::vector<base::FilePath> ResourceRequestBodyImpl::GetReferencedFiles()
+ const {
+ std::vector<base::FilePath> result;
+ for (const auto& element : *elements()) {
+ if (element.type() == Element::TYPE_FILE)
+ result.push_back(element.path());
+ }
+ return result;
}
+ResourceRequestBodyImpl::~ResourceRequestBodyImpl() {}
+
} // namespace content
diff --git a/chromium/content/common/resource_request_body.h b/chromium/content/common/resource_request_body_impl.h
index 9c87e570661..4cc8ad04b8b 100644
--- a/chromium/content/common/resource_request_body.h
+++ b/chromium/content/common/resource_request_body_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_RESOURCE_REQUEST_BODY_H_
-#define CONTENT_COMMON_RESOURCE_REQUEST_BODY_H_
+#ifndef CONTENT_COMMON_RESOURCE_REQUEST_BODY_IMPL_H_
+#define CONTENT_COMMON_RESOURCE_REQUEST_BODY_IMPL_H_
#include <stdint.h>
@@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
+#include "content/public/common/resource_request_body.h"
#include "storage/common/data_element.h"
#include "url/gurl.h"
@@ -24,13 +25,12 @@ namespace content {
// A struct used to represent upload data. The data field is populated by
// WebURLLoader from the data given as WebHTTPBody.
-class CONTENT_EXPORT ResourceRequestBody
- : public base::RefCountedThreadSafe<ResourceRequestBody>,
- public base::SupportsUserData {
+class CONTENT_EXPORT ResourceRequestBodyImpl : public ResourceRequestBody,
+ public base::SupportsUserData {
public:
typedef storage::DataElement Element;
- ResourceRequestBody();
+ ResourceRequestBodyImpl();
void AppendBytes(const char* bytes, int bytes_len);
void AppendFileRange(const base::FilePath& file_path,
@@ -55,16 +55,18 @@ class CONTENT_EXPORT ResourceRequestBody
void set_identifier(int64_t id) { identifier_ = id; }
int64_t identifier() const { return identifier_; }
+ // Returns paths referred to by |elements| of type Element::TYPE_FILE.
+ std::vector<base::FilePath> GetReferencedFiles() const;
+
private:
- friend class base::RefCountedThreadSafe<ResourceRequestBody>;
- ~ResourceRequestBody() override;
+ ~ResourceRequestBodyImpl() override;
std::vector<Element> elements_;
int64_t identifier_;
- DISALLOW_COPY_AND_ASSIGN(ResourceRequestBody);
+ DISALLOW_COPY_AND_ASSIGN(ResourceRequestBodyImpl);
};
} // namespace content
-#endif // CONTENT_COMMON_RESOURCE_REQUEST_BODY_H_
+#endif // CONTENT_COMMON_RESOURCE_REQUEST_BODY_IMPL_H_
diff --git a/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc b/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
index 4fd335b2e0d..e8264cfe04e 100644
--- a/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
+++ b/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
@@ -172,7 +172,7 @@ std::unique_ptr<SandboxBPFBasePolicy> GetGpuProcessSandbox() {
} else {
bool allow_mincore = command_line.HasSwitch(switches::kUseGL) &&
command_line.GetSwitchValueASCII(switches::kUseGL) ==
- gfx::kGLImplementationEGLName;
+ gl::kGLImplementationEGLName;
return std::unique_ptr<SandboxBPFBasePolicy>(
new GpuProcessPolicy(allow_mincore));
}
diff --git a/chromium/content/common/sandbox_mac.mm b/chromium/content/common/sandbox_mac.mm
index ab87ff4a0ce..bd9eb73cbd2 100644
--- a/chromium/content/common/sandbox_mac.mm
+++ b/chromium/content/common/sandbox_mac.mm
@@ -341,14 +341,11 @@ void Sandbox::SandboxWarmup(int sandbox_type) {
[color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
}
- if (sandbox_type == SANDBOX_TYPE_RENDERER &&
- base::mac::IsOSMountainLionOrLater()) {
+ if (sandbox_type == SANDBOX_TYPE_RENDERER) {
// Now disconnect from WindowServer, after all objects have been warmed up.
// Shutting down the connection requires connecting to WindowServer,
- // so do this before actually engaging the sandbox. This is only done on
- // 10.8 and higher because doing it on earlier OSes causes layout tests to
- // fail <http://crbug.com/397642#c48>. This may cause two log messages to
- // be printed to the system logger on certain OS versions.
+ // so do this before actually engaging the sandbox. This may cause two log
+ // messages to be printed to the system logger on certain OS versions.
CGSSetDenyWindowServerConnections(true);
CGSShutdownServerConnections();
}
diff --git a/chromium/content/common/service_worker/OWNERS b/chromium/content/common/service_worker/OWNERS
index 668d3968853..e154b05bb25 100644
--- a/chromium/content/common/service_worker/OWNERS
+++ b/chromium/content/common/service_worker/OWNERS
@@ -3,22 +3,8 @@ falken@chromium.org
horo@chromium.org
nhiroki@chromium.org
-# Changes to IPC messages require a security review to avoid introducing
-# new sandbox escapes.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
-# Changes to Mojo interfaces require a security review to avoid
-# introducing new sandbox escapes.
per-file *.mojom=set noparent
-per-file *.mojom=palmer@chromium.org
-per-file *.mojom=tsepez@chromium.org
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/service_worker/service_worker_messages.h b/chromium/content/common/service_worker/service_worker_messages.h
index 6684a4c5ad2..6e8c3fe7376 100644
--- a/chromium/content/common/service_worker/service_worker_messages.h
+++ b/chromium/content/common/service_worker/service_worker_messages.h
@@ -90,6 +90,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerResponse)
IPC_STRUCT_TRAITS_MEMBER(response_time)
IPC_STRUCT_TRAITS_MEMBER(is_in_cache_storage)
IPC_STRUCT_TRAITS_MEMBER(cache_storage_cache_name)
+ IPC_STRUCT_TRAITS_MEMBER(cors_exposed_header_names)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerObjectInfo)
@@ -243,28 +244,35 @@ IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_TerminateWorker,
int /* handle_id */)
-// Informs the browser that |provider_id| is associated
-// with a service worker script running context and
-// |version_id| identifies which ServiceWorkerVersion.
-IPC_MESSAGE_CONTROL2(ServiceWorkerHostMsg_SetVersionId,
+// Informs the browser that a service worker is starting up in a provider.
+// |provider_id| identifies the ServiceWorkerProviderHost hosting the service
+// worker. |version_id| identifies the ServiceWorkerVersion and
+// |embedded_worker_id| identifies the EmbeddedWorkerInstance.
+IPC_MESSAGE_CONTROL3(ServiceWorkerHostMsg_SetVersionId,
int /* provider_id */,
- int64_t /* version_id */)
+ int64_t /* version_id */,
+ int /* embedded_worker_id */)
// Informs the browser that event handling has finished.
// Routed to the target ServiceWorkerVersion.
-IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_InstallEventFinished,
+IPC_MESSAGE_ROUTED3(ServiceWorkerHostMsg_InstallEventFinished,
int /* request_id */,
- blink::WebServiceWorkerEventResult)
+ blink::WebServiceWorkerEventResult,
+ bool /* has_fetch_event_handler */)
+
IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_ActivateEventFinished,
int /* request_id */,
blink::WebServiceWorkerEventResult)
IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_ExtendableMessageEventFinished,
int /* request_id */,
blink::WebServiceWorkerEventResult)
-IPC_MESSAGE_ROUTED3(ServiceWorkerHostMsg_FetchEventFinished,
- int /* request_id */,
+IPC_MESSAGE_ROUTED3(ServiceWorkerHostMsg_FetchEventResponse,
+ int /* response_id */,
content::ServiceWorkerFetchEventResult,
content::ServiceWorkerResponse)
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_FetchEventFinished,
+ int /* event_finish_id */,
+ blink::WebServiceWorkerEventResult)
IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_NotificationClickEventFinished,
int /* request_id */,
blink::WebServiceWorkerEventResult)
@@ -474,8 +482,9 @@ IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_ActivateEvent,
IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_ExtendableMessageEvent,
int /* request_id */,
ServiceWorkerMsg_ExtendableMessageEvent_Params)
-IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_FetchEvent,
- int /* request_id */,
+IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_FetchEvent,
+ int /* response_id */,
+ int /* event_finish_id */,
content::ServiceWorkerFetchRequest)
IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_NotificationClickEvent,
int /* request_id */,
diff --git a/chromium/content/common/service_worker/service_worker_types.cc b/chromium/content/common/service_worker/service_worker_types.cc
index a320c29725a..aaa516bf230 100644
--- a/chromium/content/common/service_worker/service_worker_types.cc
+++ b/chromium/content/common/service_worker/service_worker_types.cc
@@ -73,7 +73,8 @@ ServiceWorkerResponse::ServiceWorkerResponse(
blink::WebServiceWorkerResponseError error,
base::Time response_time,
bool is_in_cache_storage,
- const std::string& cache_storage_cache_name)
+ const std::string& cache_storage_cache_name,
+ const ServiceWorkerHeaderList& cors_exposed_headers)
: url(url),
status_code(status_code),
status_text(status_text),
@@ -85,7 +86,8 @@ ServiceWorkerResponse::ServiceWorkerResponse(
error(error),
response_time(response_time),
is_in_cache_storage(is_in_cache_storage),
- cache_storage_cache_name(cache_storage_cache_name) {}
+ cache_storage_cache_name(cache_storage_cache_name),
+ cors_exposed_header_names(cors_exposed_headers) {}
ServiceWorkerResponse::ServiceWorkerResponse(
const ServiceWorkerResponse& other) = default;
diff --git a/chromium/content/common/service_worker/service_worker_types.h b/chromium/content/common/service_worker/service_worker_types.h
index 8291329aec9..d1196d6755c 100644
--- a/chromium/content/common/service_worker/service_worker_types.h
+++ b/chromium/content/common/service_worker/service_worker_types.h
@@ -97,6 +97,19 @@ enum class FetchRedirectMode {
LAST = MANUAL_MODE
};
+// Indicates which types of ServiceWorkers should skip handling a request.
+enum class SkipServiceWorker {
+ // Request can be handled both by a controlling same-origin worker and
+ // a cross-origin foreign fetch service worker.
+ NONE,
+ // Request should not be handled by a same-origin controlling worker,
+ // but can be intercepted by a foreign fetch service worker.
+ CONTROLLING,
+ // Request should skip all possible service workers.
+ ALL,
+ LAST = ALL
+};
+
// Indicates how the service worker handled a fetch event.
enum ServiceWorkerFetchEventResult {
// Browser should fallback to native fetch.
@@ -118,8 +131,10 @@ struct ServiceWorkerCaseInsensitiveCompare {
}
};
-typedef std::map<std::string, std::string, ServiceWorkerCaseInsensitiveCompare>
- ServiceWorkerHeaderMap;
+using ServiceWorkerHeaderMap =
+ std::map<std::string, std::string, ServiceWorkerCaseInsensitiveCompare>;
+
+using ServiceWorkerHeaderList = std::vector<std::string>;
// To dispatch fetch request from browser to child process.
struct CONTENT_EXPORT ServiceWorkerFetchRequest {
@@ -152,18 +167,20 @@ struct CONTENT_EXPORT ServiceWorkerFetchRequest {
// Represents a response to a fetch.
struct CONTENT_EXPORT ServiceWorkerResponse {
ServiceWorkerResponse();
- ServiceWorkerResponse(const GURL& url,
- int status_code,
- const std::string& status_text,
- blink::WebServiceWorkerResponseType response_type,
- const ServiceWorkerHeaderMap& headers,
- const std::string& blob_uuid,
- uint64_t blob_size,
- const GURL& stream_url,
- blink::WebServiceWorkerResponseError error,
- base::Time response_time,
- bool is_in_cache_storage,
- const std::string& cache_storage_cache_name);
+ ServiceWorkerResponse(
+ const GURL& url,
+ int status_code,
+ const std::string& status_text,
+ blink::WebServiceWorkerResponseType response_type,
+ const ServiceWorkerHeaderMap& headers,
+ const std::string& blob_uuid,
+ uint64_t blob_size,
+ const GURL& stream_url,
+ blink::WebServiceWorkerResponseError error,
+ base::Time response_time,
+ bool is_in_cache_storage,
+ const std::string& cache_storage_cache_name,
+ const ServiceWorkerHeaderList& cors_exposed_header_names);
ServiceWorkerResponse(const ServiceWorkerResponse& other);
~ServiceWorkerResponse();
@@ -179,6 +196,7 @@ struct CONTENT_EXPORT ServiceWorkerResponse {
base::Time response_time;
bool is_in_cache_storage = false;
std::string cache_storage_cache_name;
+ ServiceWorkerHeaderList cors_exposed_header_names;
};
// Represents initialization info for a WebServiceWorker object.
diff --git a/chromium/content/common/ssl_status_serialization.cc b/chromium/content/common/ssl_status_serialization.cc
index ead01b642d6..96349da3d39 100644
--- a/chromium/content/common/ssl_status_serialization.cc
+++ b/chromium/content/common/ssl_status_serialization.cc
@@ -41,6 +41,7 @@ std::string SerializeSecurityInfo(const SSLStatus& ssl_status) {
pickle.WriteUInt32(ssl_status.num_unknown_scts);
pickle.WriteUInt32(ssl_status.num_invalid_scts);
pickle.WriteUInt32(ssl_status.num_valid_scts);
+ pickle.WriteBool(ssl_status.pkp_bypassed);
return std::string(static_cast<const char*>(pickle.data()), pickle.size());
}
@@ -62,7 +63,8 @@ bool DeserializeSecurityInfo(const std::string& state, SSLStatus* ssl_status) {
!iter.ReadInt(&ssl_status->connection_status) ||
!iter.ReadUInt32(&ssl_status->num_unknown_scts) ||
!iter.ReadUInt32(&ssl_status->num_invalid_scts) ||
- !iter.ReadUInt32(&ssl_status->num_valid_scts)) {
+ !iter.ReadUInt32(&ssl_status->num_valid_scts) ||
+ !iter.ReadBool(&ssl_status->pkp_bypassed)) {
*ssl_status = SSLStatus();
return false;
}
diff --git a/chromium/content/common/view_messages.h b/chromium/content/common/view_messages.h
index 38ce9bab7e7..a70cb9c58cb 100644
--- a/chromium/content/common/view_messages.h
+++ b/chromium/content/common/view_messages.h
@@ -27,8 +27,6 @@
#include "content/common/view_message_enums.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/favicon_url.h"
-#include "content/public/common/file_chooser_file_info.h"
-#include "content/public/common/file_chooser_params.h"
#include "content/public/common/menu_item.h"
#include "content/public/common/page_state.h"
#include "content/public/common/page_zoom.h"
@@ -55,7 +53,6 @@
#include "third_party/WebKit/public/web/WebSharedWorkerCreationContextType.h"
#include "third_party/WebKit/public/web/WebSharedWorkerCreationErrors.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ui_base_types.h"
@@ -98,7 +95,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebDisplayMode,
blink::WebDisplayMode::WebDisplayModeLast)
IPC_ENUM_TRAITS_MAX_VALUE(WindowContainerType, WINDOW_CONTAINER_TYPE_MAX_VALUE)
IPC_ENUM_TRAITS(content::FaviconURL::IconType)
-IPC_ENUM_TRAITS(content::FileChooserParams::Mode)
IPC_ENUM_TRAITS(content::MenuItem::Type)
IPC_ENUM_TRAITS_MAX_VALUE(content::NavigationGesture,
content::NavigationGestureLast)
@@ -214,27 +210,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::FaviconURL)
IPC_STRUCT_TRAITS_MEMBER(icon_sizes)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::FileChooserFileInfo)
- IPC_STRUCT_TRAITS_MEMBER(file_path)
- IPC_STRUCT_TRAITS_MEMBER(display_name)
- IPC_STRUCT_TRAITS_MEMBER(file_system_url)
- IPC_STRUCT_TRAITS_MEMBER(modification_time)
- IPC_STRUCT_TRAITS_MEMBER(length)
- IPC_STRUCT_TRAITS_MEMBER(is_directory)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::FileChooserParams)
- IPC_STRUCT_TRAITS_MEMBER(mode)
- IPC_STRUCT_TRAITS_MEMBER(title)
- IPC_STRUCT_TRAITS_MEMBER(default_file_name)
- IPC_STRUCT_TRAITS_MEMBER(accept_types)
- IPC_STRUCT_TRAITS_MEMBER(need_local_path)
-#if defined(OS_ANDROID)
- IPC_STRUCT_TRAITS_MEMBER(capture)
-#endif
- IPC_STRUCT_TRAITS_MEMBER(requestor)
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_TRAITS_BEGIN(content::RendererPreferences)
IPC_STRUCT_TRAITS_MEMBER(can_accept_load_drops)
IPC_STRUCT_TRAITS_MEMBER(should_antialias_text)
@@ -514,6 +489,9 @@ IPC_STRUCT_BEGIN(ViewMsg_New_Params)
// The page zoom level.
IPC_STRUCT_MEMBER(double, page_zoom_level)
+
+ // The color profile to use for image decode.
+ IPC_STRUCT_MEMBER(std::vector<char>, image_decode_color_profile)
IPC_STRUCT_END()
#if defined(OS_MACOSX)
@@ -596,11 +574,6 @@ IPC_MESSAGE_ROUTED1(ViewMsg_EnableDeviceEmulation,
// Disables device emulation, enabled previously by EnableDeviceEmulation.
IPC_MESSAGE_ROUTED0(ViewMsg_DisableDeviceEmulation)
-// Sent to inform the renderer of its screen device color profile. An empty
-// profile tells the renderer use the default sRGB color profile.
-IPC_MESSAGE_ROUTED1(ViewMsg_ColorProfile,
- std::vector<char> /* color profile */)
-
// Tells the render view that the resize rect has changed.
IPC_MESSAGE_ROUTED1(ViewMsg_ChangeResizeRect,
gfx::Rect /* resizer_rect */)
@@ -628,18 +601,6 @@ IPC_MESSAGE_ROUTED2(ViewMsg_ShowContextMenu,
ui::MenuSourceType,
gfx::Point /* location where menu should be shown */)
-// Copies the image at location x, y to the clipboard (if there indeed is an
-// image at that location).
-IPC_MESSAGE_ROUTED2(ViewMsg_CopyImageAt,
- int /* x */,
- int /* y */)
-
-// Saves the image at location x, y to the disk (if there indeed is an
-// image at that location).
-IPC_MESSAGE_ROUTED2(ViewMsg_SaveImageAt,
- int /* x */,
- int /* y */)
-
// Tells the renderer to perform the given action on the media player
// located at the given point.
IPC_MESSAGE_ROUTED2(ViewMsg_MediaPlayerActionAt,
@@ -691,9 +652,6 @@ IPC_MESSAGE_ROUTED2(ViewMsg_SetWebUIProperty,
// to prevent target URLs spamming the browser.
IPC_MESSAGE_ROUTED0(ViewMsg_UpdateTargetURL_ACK)
-IPC_MESSAGE_ROUTED1(ViewMsg_RunFileChooserResponse,
- std::vector<content::FileChooserFileInfo>)
-
// Provides the results of directory enumeration.
IPC_MESSAGE_ROUTED2(ViewMsg_EnumerateDirectoryResponse,
int /* request_id */,
@@ -869,6 +827,9 @@ IPC_MESSAGE_ROUTED0(ViewMsg_SelectWordAroundCaret)
IPC_MESSAGE_ROUTED1(ViewMsg_ForceRedraw,
int /* request_id */)
+// Let renderer know begin frame messages won't be sent even if requested.
+IPC_MESSAGE_ROUTED1(ViewMsg_SetBeginFramePaused, bool /* paused */)
+
// Sent by the browser when the renderer should generate a new frame.
IPC_MESSAGE_ROUTED1(ViewMsg_BeginFrame,
cc::BeginFrameArgs /* args */)
@@ -1029,14 +990,6 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_AppCacheAccessed,
GURL /* manifest url */,
bool /* blocked by policy */)
-// Initiates a download based on user actions like 'ALT+click'.
-IPC_MESSAGE_CONTROL5(ViewHostMsg_DownloadUrl,
- int /* render_view_id */,
- int /* render_frame_id */,
- GURL /* url */,
- content::Referrer /* referrer */,
- base::string16 /* suggested_name */)
-
// Used to go to the session history entry at the given offset (ie, -1 will
// return the "back" item).
IPC_MESSAGE_ROUTED1(ViewHostMsg_GoToEntryAtOffset,
@@ -1090,11 +1043,6 @@ IPC_MESSAGE_ROUTED3(ViewHostMsg_SelectionChanged,
IPC_MESSAGE_ROUTED1(ViewHostMsg_SelectionBoundsChanged,
ViewHostMsg_SelectionBounds_Params)
-// Asks the browser to display the file chooser. The result is returned in a
-// ViewMsg_RunFileChooserResponse message.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_RunFileChooser,
- content::FileChooserParams)
-
// Asks the browser to enumerate a directory. This is equivalent to running
// the file chooser in directory-enumeration mode and having the user select
// the given directory. The result is returned in a
@@ -1103,14 +1051,6 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_EnumerateDirectory,
int /* request_id */,
base::FilePath /* file_path */)
-// Asks the browser to save a image (for <canvas> or <img>) from a data URL.
-// Note: |data_url| is the contents of a data:URL, and that it's represented as
-// a string only to work around size limitations for GURLs in IPC messages.
-IPC_MESSAGE_CONTROL3(ViewHostMsg_SaveImageFromDataURL,
- int /* render_view_id */,
- int /* render_frame_id */,
- std::string /* data_url */)
-
// Tells the browser to move the focus to the next (previous if reverse is
// true) focusable element.
IPC_MESSAGE_ROUTED1(ViewHostMsg_TakeFocus,
diff --git a/chromium/content/common/websocket_messages.h b/chromium/content/common/websocket_messages.h
index 383eb5a1f4a..ce250780b9c 100644
--- a/chromium/content/common/websocket_messages.h
+++ b/chromium/content/common/websocket_messages.h
@@ -46,6 +46,15 @@
IPC_ENUM_TRAITS_MAX_VALUE(content::WebSocketMessageType,
content::WEB_SOCKET_MESSAGE_TYPE_LAST)
+IPC_STRUCT_BEGIN(WebSocketHostMsg_AddChannelRequest_Params)
+ IPC_STRUCT_MEMBER(GURL, socket_url)
+ IPC_STRUCT_MEMBER(std::vector<std::string>, requested_protocols)
+ IPC_STRUCT_MEMBER(url::Origin, origin)
+ IPC_STRUCT_MEMBER(GURL, first_party_for_cookies)
+ IPC_STRUCT_MEMBER(std::string, user_agent_override)
+ IPC_STRUCT_MEMBER(int, render_frame_id)
+IPC_STRUCT_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::WebSocketHandshakeRequest)
IPC_STRUCT_TRAITS_MEMBER(url)
IPC_STRUCT_TRAITS_MEMBER(headers)
@@ -67,11 +76,8 @@ IPC_STRUCT_TRAITS_END()
// Open new WebSocket connection to |socket_url|. |requested_protocols| is a
// list of tokens identifying sub-protocols the renderer would like to use, as
// described in RFC6455 "Subprotocols Using the WebSocket Protocol".
-IPC_MESSAGE_ROUTED4(WebSocketHostMsg_AddChannelRequest,
- GURL /* socket_url */,
- std::vector<std::string> /* requested_protocols */,
- url::Origin /* origin */,
- int /* render_frame_id */)
+IPC_MESSAGE_ROUTED1(WebSocketHostMsg_AddChannelRequest,
+ WebSocketHostMsg_AddChannelRequest_Params)
// Send a complete binary WebSocket message consisting of the Blob identified by
// |uuid|. The message will be split into frames as necessary. |expected_size|
diff --git a/chromium/content/content.gyp b/chromium/content/content.gyp
index 5ddc7177546..d06051241f1 100644
--- a/chromium/content/content.gyp
+++ b/chromium/content/content.gyp
@@ -78,6 +78,20 @@
'hard_dependency': 1,
},
{
+ # GN version: //content/public/app:gpu_manifest
+ 'target_name': 'content_app_gpu_manifest',
+ 'type': 'none',
+ 'variables': {
+ 'application_type': 'exe',
+ 'application_name': 'content_gpu',
+ 'source_manifest': '<(DEPTH)/content/public/app/mojo/content_gpu_manifest.json',
+ },
+ 'includes': [
+ '../mojo/public/mojo_application_manifest.gypi',
+ ],
+ 'hard_dependency': 1,
+ },
+ {
# GN version: //content/public/app:renderer_manifest
'target_name': 'content_app_renderer_manifest',
'type': 'none',
@@ -91,6 +105,20 @@
],
'hard_dependency': 1,
},
+ {
+ # GN version: //content/public/app:utility_manifest
+ 'target_name': 'content_app_utility_manifest',
+ 'type': 'none',
+ 'variables': {
+ 'application_type': 'exe',
+ 'application_name': 'content_utility',
+ 'source_manifest': '<(DEPTH)/content/public/app/mojo/content_utility_manifest.json',
+ },
+ 'includes': [
+ '../mojo/public/mojo_application_manifest.gypi',
+ ],
+ 'hard_dependency': 1,
+ },
],
'includes': [
'../build/win_precompile.gypi',
@@ -233,6 +261,11 @@
'content_utility',
],
}],
+ # Shard this target into parts to work around linker limitations
+ # on link time code generation builds. See crbug.com/616946
+ ['OS=="win" and buildtype=="Official"', {
+ 'msvs_shard': 5,
+ }],
],
},
{
@@ -484,12 +517,12 @@
'../mojo/mojo_public.gyp:mojo_bindings_java',
'../net/net.gyp:net',
'../skia/skia.gyp:skia_mojo',
+ '../third_party/android_tools/android_tools.gyp:android_support_v13_javalib',
+ '../third_party/WebKit/public/blink_headers.gyp:blink_headers_java',
'../ui/android/ui_android.gyp:ui_java',
+ '../ui/gfx/gfx.gyp:mojo_geometry_bindings',
'../ui/touch_selection/ui_touch_selection.gyp:selection_event_type_java',
'../ui/touch_selection/ui_touch_selection.gyp:touch_handle_orientation_java',
- '../third_party/android_tools/android_tools.gyp:android_support_v13_javalib',
- '../third_party/WebKit/public/blink_headers.gyp:blink_headers_java',
- '../ui/mojo/geometry/mojo_bindings.gyp:mojo_geometry_bindings',
'common_aidl',
'console_message_level_java',
'content_common',
diff --git a/chromium/content/content_app.gypi b/chromium/content/content_app.gypi
index 2ed4ed7fd97..e82a541179e 100644
--- a/chromium/content/content_app.gypi
+++ b/chromium/content/content_app.gypi
@@ -22,8 +22,8 @@
'sources': [
'app/android/app_jni_registrar.cc',
'app/android/app_jni_registrar.h',
- 'app/android/child_process_service.cc',
- 'app/android/child_process_service.h',
+ 'app/android/child_process_service_impl.cc',
+ 'app/android/child_process_service_impl.h',
'app/android/content_jni_onload.cc',
'app/android/content_main.cc',
'app/android/content_main.h',
diff --git a/chromium/content/content_browser.gypi b/chromium/content/content_browser.gypi
index 150367d6afe..fc59ad9cc0d 100644
--- a/chromium/content/content_browser.gypi
+++ b/chromium/content/content_browser.gypi
@@ -13,11 +13,14 @@
'../components/mime_util/mime_util.gyp:mime_util',
'../components/scheduler/scheduler.gyp:scheduler_common',
'../components/url_formatter/url_formatter.gyp:url_formatter',
+ '../components/components.gyp:webmessaging',
'../crypto/crypto.gyp:crypto',
'../device/battery/battery.gyp:device_battery',
'../device/battery/battery.gyp:device_battery_mojo_bindings',
'../device/bluetooth/bluetooth.gyp:device_bluetooth',
+ '../device/gamepad/gamepad.gyp:device_gamepad',
'../device/usb/usb.gyp:device_usb',
+ '../device/power_save_blocker/power_save_blocker.gyp:device_power_save_blocker',
'../device/vibration/vibration.gyp:device_vibration',
'../device/vibration/vibration.gyp:device_vibration_mojo_bindings',
'../gin/gin.gyp:gin',
@@ -25,8 +28,7 @@
'../gpu/gpu.gyp:gpu',
'../gpu/gpu.gyp:gpu_ipc_client',
'../gpu/gpu.gyp:gpu_ipc_common',
- '../mojo/mojo_base.gyp:mojo_geometry_lib',
- '../mojo/mojo_base.gyp:mojo_url_type_converters',
+ '../media/mojo/interfaces/mojo_bindings.gyp:image_capture_mojo_bindings',
'../mojo/mojo_public.gyp:mojo_cpp_bindings',
'../mojo/mojo_public.gyp:mojo_js_bindings',
'../net/net.gyp:http_server',
@@ -67,6 +69,7 @@
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/gfx/gfx.gyp:gfx_range',
+ '../ui/gfx/gfx.gyp:mojo_geometry_bindings',
'../ui/resources/ui_resources.gyp:ui_resources',
'../ui/snapshot/snapshot.gyp:snapshot',
'../ui/surface/surface.gyp:surface',
@@ -110,8 +113,6 @@
'public/browser/android/content_view_core.h',
'public/browser/android/content_view_layer_renderer.h',
'public/browser/android/devtools_auth.h',
- 'public/browser/android/download_controller_android.cc',
- 'public/browser/android/download_controller_android.h',
'public/browser/android/external_video_surface_container.h',
'public/browser/android/service_registry_android.h',
'public/browser/android/synchronous_compositor.cc',
@@ -190,6 +191,7 @@
'public/browser/file_descriptor_info.h',
'public/browser/focused_node_details.h',
'public/browser/font_list_async.h',
+ 'public/browser/geolocation_delegate.cc',
'public/browser/geolocation_provider.h',
'public/browser/global_request_id.h',
'public/browser/gpu_data_manager.h',
@@ -220,16 +222,15 @@
'public/browser/memory_pressure_controller.h',
'public/browser/message_port_delegate.h',
'public/browser/message_port_provider.h',
- 'public/browser/mojo_app_connection.h',
'public/browser/native_web_keyboard_event.h',
'public/browser/navigation_controller.cc',
'public/browser/navigation_controller.h',
+ 'public/browser/navigation_data.h',
'public/browser/navigation_details.cc',
'public/browser/navigation_details.h',
'public/browser/navigation_entry.h',
'public/browser/navigation_handle.cc',
'public/browser/navigation_handle.h',
- 'public/browser/navigation_data.h',
'public/browser/navigation_throttle.cc',
'public/browser/navigation_throttle.h',
'public/browser/navigation_type.h',
@@ -246,6 +247,7 @@
'public/browser/page_navigator.cc',
'public/browser/page_navigator.h',
'public/browser/pepper_flash_settings_helper.h',
+ 'public/browser/pepper_vpn_provider_resource_host_proxy.h',
'public/browser/permission_manager.h',
'public/browser/permission_type.h',
'public/browser/platform_notification_context.h',
@@ -253,7 +255,6 @@
'public/browser/plugin_data_remover.h',
'public/browser/plugin_service.h',
'public/browser/plugin_service_filter.h',
- 'public/browser/power_save_blocker.h',
'public/browser/presentation_screen_availability_listener.h',
'public/browser/presentation_service_delegate.h',
'public/browser/presentation_session.cc',
@@ -323,6 +324,8 @@
'public/browser/url_data_source.h',
'public/browser/user_metrics.h',
'public/browser/utility_process_host.h',
+ 'public/browser/utility_process_mojo_client.h',
+ 'public/browser/vpn_service_proxy.h',
'public/browser/web_contents.cc',
'public/browser/web_contents.h',
'public/browser/web_contents_delegate.cc',
@@ -376,10 +379,10 @@
'browser/accessibility/browser_accessibility.h',
'browser/accessibility/browser_accessibility_cocoa.h',
'browser/accessibility/browser_accessibility_cocoa.mm',
- 'browser/accessibility/browser_accessibility_event.h',
'browser/accessibility/browser_accessibility_event.cc',
- 'browser/accessibility/browser_accessibility_event_win.h',
+ 'browser/accessibility/browser_accessibility_event.h',
'browser/accessibility/browser_accessibility_event_win.cc',
+ 'browser/accessibility/browser_accessibility_event_win.h',
'browser/accessibility/browser_accessibility_mac.h',
'browser/accessibility/browser_accessibility_mac.mm',
'browser/accessibility/browser_accessibility_manager.cc',
@@ -485,17 +488,17 @@
'browser/blob_storage/blob_dispatcher_host.h',
'browser/blob_storage/chrome_blob_storage_context.cc',
'browser/blob_storage/chrome_blob_storage_context.h',
+ 'browser/bluetooth/bluetooth_adapter_factory_wrapper.cc',
+ 'browser/bluetooth/bluetooth_adapter_factory_wrapper.h',
'browser/bluetooth/bluetooth_allowed_devices_map.cc',
'browser/bluetooth/bluetooth_allowed_devices_map.h',
'browser/bluetooth/bluetooth_blacklist.cc',
'browser/bluetooth/bluetooth_blacklist.h',
- 'browser/bluetooth/bluetooth_dispatcher_host.cc',
- 'browser/bluetooth/bluetooth_dispatcher_host.h',
+ 'browser/bluetooth/bluetooth_device_chooser_controller.cc',
+ 'browser/bluetooth/bluetooth_device_chooser_controller.h',
'browser/bluetooth/bluetooth_metrics.cc',
'browser/bluetooth/bluetooth_metrics.h',
'browser/bluetooth/cache_query_result.h',
- 'browser/bluetooth/first_device_bluetooth_chooser.cc',
- 'browser/bluetooth/first_device_bluetooth_chooser.h',
'browser/bluetooth/frame_connected_bluetooth_devices.cc',
'browser/bluetooth/frame_connected_bluetooth_devices.h',
'browser/bluetooth/web_bluetooth_service_impl.cc',
@@ -537,6 +540,8 @@
'browser/cache_storage/cache_storage_blob_to_disk_cache.h',
'browser/cache_storage/cache_storage_cache.cc',
'browser/cache_storage/cache_storage_cache.h',
+ 'browser/cache_storage/cache_storage_cache_handle.cc',
+ 'browser/cache_storage/cache_storage_cache_handle.h',
'browser/cache_storage/cache_storage_context_impl.cc',
'browser/cache_storage/cache_storage_context_impl.h',
'browser/cache_storage/cache_storage_dispatcher_host.cc',
@@ -605,6 +610,8 @@
'browser/devtools/devtools_protocol_handler.h',
'browser/devtools/forwarding_agent_host.cc',
'browser/devtools/forwarding_agent_host.h',
+ 'browser/devtools/protocol/browser_handler.cc',
+ 'browser/devtools/protocol/browser_handler.h',
'browser/devtools/protocol/color_picker.cc',
'browser/devtools/protocol/color_picker.h',
'browser/devtools/protocol/devtools_protocol_client.cc',
@@ -759,6 +766,8 @@
'browser/frame_host/frame_tree.h',
'browser/frame_host/frame_tree_node.cc',
'browser/frame_host/frame_tree_node.h',
+ 'browser/frame_host/frame_tree_node_blame_context.cc',
+ 'browser/frame_host/frame_tree_node_blame_context.h',
'browser/frame_host/interstitial_page_impl.cc',
'browser/frame_host/interstitial_page_impl.h',
'browser/frame_host/interstitial_page_navigator_impl.cc',
@@ -802,33 +811,10 @@
'browser/frame_host/render_widget_host_view_child_frame.h',
'browser/frame_host/render_widget_host_view_guest.cc',
'browser/frame_host/render_widget_host_view_guest.h',
- 'browser/frame_host/traced_frame_tree_node.cc',
- 'browser/frame_host/traced_frame_tree_node.h',
- 'browser/gamepad/gamepad_consumer.h',
- 'browser/gamepad/gamepad_data_fetcher.cc',
- 'browser/gamepad/gamepad_data_fetcher.h',
- 'browser/gamepad/gamepad_platform_data_fetcher.h',
- 'browser/gamepad/gamepad_platform_data_fetcher_android.cc',
- 'browser/gamepad/gamepad_platform_data_fetcher_android.h',
- 'browser/gamepad/gamepad_platform_data_fetcher_linux.cc',
- 'browser/gamepad/gamepad_platform_data_fetcher_linux.h',
- 'browser/gamepad/gamepad_platform_data_fetcher_mac.h',
- 'browser/gamepad/gamepad_platform_data_fetcher_mac.mm',
- 'browser/gamepad/gamepad_platform_data_fetcher_win.cc',
- 'browser/gamepad/gamepad_platform_data_fetcher_win.h',
- 'browser/gamepad/gamepad_provider.cc',
- 'browser/gamepad/gamepad_provider.h',
'browser/gamepad/gamepad_service.cc',
'browser/gamepad/gamepad_service.h',
- 'browser/gamepad/gamepad_standard_mappings.cc',
- 'browser/gamepad/gamepad_standard_mappings.h',
- 'browser/gamepad/gamepad_standard_mappings_linux.cc',
- 'browser/gamepad/gamepad_standard_mappings_mac.mm',
- 'browser/gamepad/gamepad_standard_mappings_win.cc',
- 'browser/gamepad/raw_input_data_fetcher_win.cc',
- 'browser/gamepad/raw_input_data_fetcher_win.h',
- 'browser/gamepad/xbox_data_fetcher_mac.cc',
- 'browser/gamepad/xbox_data_fetcher_mac.h',
+ 'browser/gamepad/gamepad_shared_buffer_impl.cc',
+ 'browser/gamepad/gamepad_shared_buffer_impl.h',
'browser/geolocation/empty_wifi_data_provider.cc',
'browser/geolocation/empty_wifi_data_provider.h',
'browser/geolocation/geolocation_provider_impl.cc',
@@ -978,6 +964,7 @@
'browser/loader/global_routing_id.h',
'browser/loader/layered_resource_handler.cc',
'browser/loader/layered_resource_handler.h',
+ 'browser/loader/loader_delegate.h',
'browser/loader/mime_type_resource_handler.cc',
'browser/loader/mime_type_resource_handler.h',
'browser/loader/navigation_resource_handler.cc',
@@ -1030,6 +1017,8 @@
'browser/loader/throttling_resource_handler.h',
'browser/loader/upload_data_stream_builder.cc',
'browser/loader/upload_data_stream_builder.h',
+ 'browser/loader_delegate_impl.cc',
+ 'browser/loader_delegate_impl.h',
'browser/mach_broker_mac.h',
'browser/mach_broker_mac.mm',
'browser/manifest/manifest_manager_host.cc',
@@ -1121,16 +1110,10 @@
'browser/message_port_provider.cc',
'browser/message_port_service.cc',
'browser/message_port_service.h',
- 'browser/mime_registry_message_filter.cc',
- 'browser/mime_registry_message_filter.h',
- 'browser/mojo/browser_shell_connection.cc',
- 'browser/mojo/browser_shell_connection.h',
+ 'browser/mime_registry_impl.cc',
+ 'browser/mime_registry_impl.h',
'browser/mojo/constants.cc',
'browser/mojo/constants.h',
- 'browser/mojo/mojo_app_connection_impl.cc',
- 'browser/mojo/mojo_app_connection_impl.h',
- 'browser/mojo/mojo_application_host.cc',
- 'browser/mojo/mojo_application_host.h',
'browser/mojo/mojo_child_connection.cc',
'browser/mojo/mojo_child_connection.h',
'browser/mojo/mojo_shell_context.cc',
@@ -1149,6 +1132,8 @@
'browser/net/view_http_cache_job_factory.h',
'browser/notification_service_impl.cc',
'browser/notification_service_impl.h',
+ 'browser/notifications/blink_notification_service_impl.cc',
+ 'browser/notifications/blink_notification_service_impl.h',
'browser/notifications/notification_database.cc',
'browser/notifications/notification_database.h',
'browser/notifications/notification_database_data_conversions.cc',
@@ -1171,14 +1156,6 @@
'browser/permissions/permission_service_impl.h',
'browser/power_monitor_message_broadcaster.cc',
'browser/power_monitor_message_broadcaster.h',
- 'browser/power_save_blocker_android.h',
- 'browser/power_save_blocker_chromeos.cc',
- 'browser/power_save_blocker_impl.cc',
- 'browser/power_save_blocker_impl.h',
- 'browser/power_save_blocker_mac.cc',
- 'browser/power_save_blocker_ozone.cc',
- 'browser/power_save_blocker_win.cc',
- 'browser/power_save_blocker_x11.cc',
'browser/power_usage_monitor_impl.cc',
'browser/power_usage_monitor_impl.h',
'browser/presentation/presentation_service_impl.cc',
@@ -1288,8 +1265,6 @@
'browser/renderer_host/input/touchpad_tap_suppression_controller.h',
'browser/renderer_host/input/touchscreen_tap_suppression_controller.cc',
'browser/renderer_host/input/touchscreen_tap_suppression_controller.h',
- 'browser/renderer_host/input/ui_touch_selection_helper.cc',
- 'browser/renderer_host/input/ui_touch_selection_helper.h',
'browser/renderer_host/input/web_input_event_builders_android.cc',
'browser/renderer_host/input/web_input_event_builders_android.h',
'browser/renderer_host/input/web_input_event_builders_mac.h',
@@ -1341,6 +1316,8 @@
'browser/renderer_host/media/video_capture_manager.h',
'browser/renderer_host/native_web_keyboard_event_aura.cc',
'browser/renderer_host/native_web_keyboard_event_mac.mm',
+ 'browser/renderer_host/offscreen_canvas_surface_impl.cc',
+ 'browser/renderer_host/offscreen_canvas_surface_impl.h',
'browser/renderer_host/overscroll_configuration.cc',
'browser/renderer_host/overscroll_controller.cc',
'browser/renderer_host/overscroll_controller.h',
@@ -1387,6 +1364,8 @@
'browser/renderer_host/text_input_client_mac.mm',
'browser/renderer_host/text_input_client_message_filter.h',
'browser/renderer_host/text_input_client_message_filter.mm',
+ 'browser/renderer_host/text_input_manager.cc',
+ 'browser/renderer_host/text_input_manager.h',
'browser/renderer_host/ui_events_helper.cc',
'browser/renderer_host/ui_events_helper.h',
'browser/renderer_host/web_input_event_aura.cc',
@@ -1414,6 +1393,7 @@
'browser/service_worker/embedded_worker_instance.h',
'browser/service_worker/embedded_worker_registry.cc',
'browser/service_worker/embedded_worker_registry.h',
+ 'browser/service_worker/embedded_worker_status.h',
'browser/service_worker/foreign_fetch_request_handler.cc',
'browser/service_worker/foreign_fetch_request_handler.h',
'browser/service_worker/link_header_support.cc',
@@ -1453,10 +1433,6 @@
'browser/service_worker/service_worker_job_coordinator.h',
'browser/service_worker/service_worker_metrics.cc',
'browser/service_worker/service_worker_metrics.h',
- 'browser/service_worker/service_worker_navigation_handle.cc',
- 'browser/service_worker/service_worker_navigation_handle.h',
- 'browser/service_worker/service_worker_navigation_handle_core.cc',
- 'browser/service_worker/service_worker_navigation_handle_core.h',
'browser/service_worker/service_worker_process_manager.cc',
'browser/service_worker/service_worker_process_manager.h',
'browser/service_worker/service_worker_provider_host.cc',
@@ -1666,10 +1642,6 @@
'browser/android/content_view_statics.h',
'browser/android/date_time_chooser_android.cc',
'browser/android/date_time_chooser_android.h',
- 'browser/android/deferred_download_observer.cc',
- 'browser/android/deferred_download_observer.h',
- 'browser/android/download_controller_android_impl.cc',
- 'browser/android/download_controller_android_impl.h',
'browser/android/gesture_event_type.h',
'browser/android/interstitial_page_delegate_android.cc',
'browser/android/interstitial_page_delegate_android.h',
@@ -1705,7 +1677,6 @@
'browser/android/tracing_controller_android.h',
'browser/android/web_contents_observer_proxy.cc',
'browser/android/web_contents_observer_proxy.h',
- 'browser/power_save_blocker_android.cc',
'browser/renderer_host/compositor_impl_android.cc',
'browser/renderer_host/compositor_impl_android.h',
'browser/renderer_host/ime_adapter_android.cc',
@@ -1761,6 +1732,8 @@
'browser/compositor/browser_compositor_output_surface.h',
'browser/compositor/gpu_browser_compositor_output_surface.cc',
'browser/compositor/gpu_browser_compositor_output_surface.h',
+ 'browser/compositor/gpu_output_surface_mac.h',
+ 'browser/compositor/gpu_output_surface_mac.mm',
'browser/compositor/gpu_process_transport_factory.cc',
'browser/compositor/gpu_process_transport_factory.h',
'browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc',
@@ -1800,6 +1773,8 @@
'browser/plugin_content_origin_whitelist.h',
'browser/plugin_data_remover_impl.cc',
'browser/plugin_data_remover_impl.h',
+ 'browser/plugin_private_storage_helper.cc',
+ 'browser/plugin_private_storage_helper.h',
'browser/plugin_service_impl.cc',
'browser/plugin_service_impl.h',
'browser/ppapi_plugin_process_host.cc',
@@ -1882,11 +1857,6 @@
'browser/file_descriptor_info_impl.h',
]
}],
- ['OS!="win" and OS!="mac" and OS!="android" and (OS!="linux" or use_udev==0)', {
- 'sources': [
- 'browser/gamepad/gamepad_platform_data_fetcher.cc',
- ]
- }],
['debug_devtools==1', {
'defines': [
'DEBUG_DEVTOOLS=1',
@@ -2010,11 +1980,7 @@
['use_udev == 1', {
'dependencies': [
'../device/udev_linux/udev.gyp:udev_linux',
- '../media/media.gyp:media',
- ],
- }, {
- 'sources!': [
- 'browser/gamepad/gamepad_platform_data_fetcher_linux.cc',
+ '../media/capture/capture.gyp:capture',
],
}],
['OS=="linux" and use_aura==1', {
@@ -2102,13 +2068,6 @@
'sources!': [
'browser/device_sensors/data_fetcher_shared_memory_default.cc',
'browser/geolocation/wifi_data_provider_linux.cc',
- 'browser/power_save_blocker_ozone.cc',
- 'browser/power_save_blocker_x11.cc',
- ],
- }],
- ['os_bsd==1', {
- 'sources/': [
- ['exclude', '^browser/gamepad/gamepad_platform_data_fetcher_linux\\.cc$'],
],
}],
['use_aura==1', {
diff --git a/chromium/content/content_child.gypi b/chromium/content/content_child.gypi
index aab2dfdd2a7..fb24836e5a2 100644
--- a/chromium/content/content_child.gypi
+++ b/chromium/content/content_child.gypi
@@ -129,8 +129,6 @@
'child/indexed_db/webidbfactory_impl.h',
'child/memory/child_memory_message_filter.cc',
'child/memory/child_memory_message_filter.h',
- 'child/mojo/mojo_application.cc',
- 'child/mojo/mojo_application.h',
'child/mojo/type_converters.h',
'child/notifications/notification_data_conversions.cc',
'child/notifications/notification_data_conversions.h',
@@ -223,6 +221,8 @@
'child/websocket_bridge.h',
'child/websocket_dispatcher.cc',
'child/websocket_dispatcher.h',
+ 'child/websocket_message_filter.cc',
+ 'child/websocket_message_filter.h',
'child/webthemeengine_impl_android.cc',
'child/webthemeengine_impl_android.h',
'child/webthemeengine_impl_default.cc',
diff --git a/chromium/content/content_common.gypi b/chromium/content/content_common.gypi
index e9e6e813a11..ca81c603f07 100644
--- a/chromium/content/content_common.gypi
+++ b/chromium/content/content_common.gypi
@@ -8,7 +8,6 @@
'../cc/cc.gyp:cc',
'../cc/ipc/cc_ipc.gyp:cc_ipc',
'../components/tracing.gyp:tracing',
- '../device/bluetooth/bluetooth.gyp:device_bluetooth',
'../gpu/command_buffer/command_buffer.gyp:gles2_utils',
'../gpu/gpu.gyp:command_buffer_service',
'../gpu/gpu.gyp:gles2_c_lib',
@@ -16,8 +15,8 @@
'../gpu/gpu.gyp:gpu',
'../gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings',
'../ipc/ipc.gyp:ipc',
- '../ipc/mojo/ipc_mojo.gyp:ipc_mojo',
'../media/base/ipc/media_base_ipc.gyp:media_base_ipc',
+ '../media/capture/capture.gyp:capture',
'../media/media.gyp:media',
'../media/media.gyp:media_gpu',
'../media/media.gyp:shared_memory_support',
@@ -32,6 +31,7 @@
'../skia/skia.gyp:skia',
'../storage/storage_common.gyp:storage_common',
'../third_party/WebKit/public/blink.gyp:blink',
+ '../third_party/WebKit/public/blink.gyp:mojo_bindings',
'../third_party/WebKit/public/blink_headers.gyp:blink_headers',
'../third_party/boringssl/boringssl.gyp:boringssl',
'../third_party/icu/icu.gyp:icuuc',
@@ -53,6 +53,11 @@
'content.gyp:common_features',
'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
],
+ # content/public/common/common_param_traits_macros.h includes a generated
+ # header from blink.gyp:mojo_bindings. We need to be sure any targets that
+ # depend on content_common also depend upon blink.gyp:mojo_bindings so
+ # that the header is generated before compile starts.
+ 'hard_dependency': '1',
'include_dirs': [
'..',
],
@@ -178,6 +183,8 @@
'public/common/request_context_type.h',
'public/common/resource_devtools_info.cc',
'public/common/resource_devtools_info.h',
+ 'public/common/resource_request_body.cc',
+ 'public/common/resource_request_body.h',
'public/common/resource_response.cc',
'public/common/resource_response.h',
'public/common/resource_response_info.cc',
@@ -193,7 +200,6 @@
'public/common/screen_orientation_values.h',
'public/common/security_style.h',
'public/common/send_zygote_child_ping_linux.h',
- 'public/common/service_registry.h',
'public/common/speech_recognition_error.h',
'public/common/speech_recognition_grammar.h',
'public/common/speech_recognition_result.cc',
@@ -237,6 +243,8 @@
'common/android/hash_set.h',
'common/android/media_metadata_android.cc',
'common/android/media_metadata_android.h',
+ 'common/android/resource_request_body_android.cc',
+ 'common/android/resource_request_body_android.h',
'common/android/sync_compositor_messages.cc',
'common/android/sync_compositor_messages.h',
'common/android/sync_compositor_statics.cc',
@@ -246,11 +254,6 @@
'common/appcache_messages.h',
'common/ax_content_node_data.cc',
'common/ax_content_node_data.h',
- 'common/bluetooth/bluetooth_device.cc',
- 'common/bluetooth/bluetooth_device.h',
- 'common/bluetooth/bluetooth_messages.h',
- 'common/bluetooth/bluetooth_scan_filter.cc',
- 'common/bluetooth/bluetooth_scan_filter.h',
'common/browser_plugin/browser_plugin_constants.cc',
'common/browser_plugin/browser_plugin_constants.h',
'common/browser_plugin/browser_plugin_messages.h',
@@ -307,8 +310,6 @@
'common/drag_messages.h',
'common/drag_traits.h',
'common/dwrite_font_proxy_messages.h',
- 'common/dwrite_text_analysis_source_win.cc',
- 'common/dwrite_text_analysis_source_win.h',
'common/edit_command.h',
'common/establish_channel_params.cc',
'common/establish_channel_params.h',
@@ -333,8 +334,6 @@
'common/gamepad_messages.h',
'common/gamepad_param_traits.cc',
'common/gamepad_param_traits.h',
- 'common/gamepad_user_gesture.cc',
- 'common/gamepad_user_gesture.h',
'common/generic_shared_memory_id_generator.cc',
'common/generic_shared_memory_id_generator.h',
'common/gin_java_bridge_messages.h',
@@ -372,8 +371,6 @@
'common/input/input_event_dispatch_type.h',
'common/input/input_event_stream_validator.cc',
'common/input/input_event_stream_validator.h',
- 'common/input/input_event_utils.cc',
- 'common/input/input_event_utils.h',
'common/input/input_param_traits.cc',
'common/input/input_param_traits.h',
'common/input/scoped_web_input_event.cc',
@@ -430,13 +427,10 @@
'common/media/webrtc_identity_messages.h',
'common/memory_messages.h',
'common/message_port_messages.h',
- 'common/mime_registry_messages.h',
'common/mojo/embedded_application_runner.cc',
'common/mojo/embedded_application_runner.h',
'common/mojo/mojo_shell_connection_impl.cc',
'common/mojo/mojo_shell_connection_impl.h',
- 'common/mojo/service_registry_impl.cc',
- 'common/mojo/service_registry_impl.h',
'common/navigation_gesture.h',
'common/navigation_params.cc',
'common/navigation_params.h',
@@ -458,7 +452,6 @@
'common/page_zoom.cc',
'common/pepper_file_util.cc',
'common/pepper_file_util.h',
- 'common/pepper_messages.h',
'common/pepper_plugin_list.cc',
'common/pepper_plugin_list.h',
'common/pepper_renderer_instance_data.cc',
@@ -477,8 +470,8 @@
'common/resource_messages.h',
'common/resource_request.cc',
'common/resource_request.h',
- 'common/resource_request_body.cc',
- 'common/resource_request_body.h',
+ 'common/resource_request_body_impl.cc',
+ 'common/resource_request_body_impl.h',
'common/resource_request_completion_status.cc',
'common/resource_request_completion_status.h',
'common/sandbox_init_mac.cc',
@@ -611,7 +604,6 @@
'sources!': [
'common/pepper_file_util.cc',
'common/pepper_file_util.h',
- 'common/pepper_messages.h',
'common/pepper_plugin_list.cc',
'common/pepper_plugin_list.h',
'common/pepper_renderer_instance_data.cc',
@@ -668,5 +660,11 @@
'common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h',
],
}],
+ ['enable_ipc_fuzzer==1', {
+ 'sources': [
+ 'common/external_ipc_dumper.cc',
+ 'common/external_ipc_dumper.h',
+ ],
+ }],
],
}
diff --git a/chromium/content/content_common_mojo_bindings.gyp b/chromium/content/content_common_mojo_bindings.gyp
index 807c78b9a3d..c898f87fb97 100644
--- a/chromium/content/content_common_mojo_bindings.gyp
+++ b/chromium/content/content_common_mojo_bindings.gyp
@@ -11,15 +11,16 @@
'variables': {
'mojom_files': [
# NOTE: Sources duplicated in //content/common/BUILD.gn:mojo_bindings.
- 'common/application_setup.mojom',
+ 'common/frame.mojom',
'common/image_downloader/image_downloader.mojom',
'common/leveldb_wrapper.mojom',
'common/process_control.mojom',
- 'common/render_frame_setup.mojom',
'common/service_worker/embedded_worker_setup.mojom',
'common/storage_partition_service.mojom',
],
'mojom_typemaps': [
+ '../skia/public/interfaces/skbitmap.typemap',
+ '../ui/gfx/geometry/mojo/geometry.typemap',
'../url/mojo/gurl.typemap',
'../url/mojo/origin.typemap',
],
@@ -30,7 +31,7 @@
'../services/shell/shell_public.gyp:shell_public',
'../skia/skia.gyp:skia_mojo',
'../third_party/WebKit/public/blink.gyp:mojo_bindings',
- '../ui/mojo/geometry/mojo_bindings.gyp:mojo_geometry_bindings',
+ '../ui/gfx/gfx.gyp:mojo_geometry_bindings',
],
'includes': [ '../mojo/mojom_bindings_generator_explicit.gypi' ],
},
@@ -42,9 +43,11 @@
},
'dependencies': [
'../url/url.gyp:url_mojom',
+ '../skia/skia.gyp:skia',
'content_common_mojo_bindings_mojom',
],
'export_dependent_settings': [
+ '../skia/skia.gyp:skia',
'../url/url.gyp:url_mojom',
],
},
diff --git a/chromium/content/content_jni.gypi b/chromium/content/content_jni.gypi
index 2f1ccf829ff..04d7215ec1e 100644
--- a/chromium/content/content_jni.gypi
+++ b/chromium/content/content_jni.gypi
@@ -8,7 +8,7 @@
# TODO(jrg): when doing the above, make sure we support multiple
# output directories (e.g. browser/jni and common/jni if needed).
'sources': [
- 'public/android/java/src/org/chromium/content/app/ChildProcessService.java',
+ 'public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java',
'public/android/java/src/org/chromium/content/app/ContentMain.java',
'public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java',
'public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java',
@@ -19,8 +19,6 @@
'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java',
'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java',
'public/android/java/src/org/chromium/content/browser/DeviceSensors.java',
- 'public/android/java/src/org/chromium/content/browser/DownloadController.java',
- 'public/android/java/src/org/chromium/content/browser/input/GamepadList.java',
'public/android/java/src/org/chromium/content/browser/input/HandleViewResources.java',
'public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java',
'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java',
@@ -31,7 +29,6 @@
'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java',
'public/android/java/src/org/chromium/content/browser/MediaThrottler.java',
'public/android/java/src/org/chromium/content/browser/MotionEventSynthesizer.java',
- 'public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java',
'public/android/java/src/org/chromium/content/browser/ServiceRegistrar.java',
'public/android/java/src/org/chromium/content/browser/ServiceRegistry.java',
'public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java',
@@ -43,6 +40,7 @@
'public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java',
'public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java',
'public/android/java/src/org/chromium/content_public/common/MediaMetadata.java',
+ 'public/android/java/src/org/chromium/content_public/common/ResourceRequestBody.java',
],
'variables': {
'jni_gen_package': 'content',
diff --git a/chromium/content/content_renderer.gypi b/chromium/content/content_renderer.gypi
index 2e4eb60909e..dbf3b2b45da 100644
--- a/chromium/content/content_renderer.gypi
+++ b/chromium/content/content_renderer.gypi
@@ -23,8 +23,6 @@
'../media/gpu/ipc/media_ipc.gyp:media_gpu_ipc_common',
'../media/media.gyp:media',
'../media/media.gyp:media_gpu',
- '../mojo/mojo_base.gyp:mojo_geometry_lib',
- '../mojo/mojo_base.gyp:mojo_url_type_converters',
'../mojo/mojo_edk.gyp:mojo_js_lib',
'../net/net.gyp:net',
'../services/shell/shell_public.gyp:shell_public',
@@ -45,6 +43,7 @@
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/gfx/gfx.gyp:gfx_range',
+ '../ui/gfx/gfx.gyp:mojo_geometry_bindings',
'../ui/native_theme/native_theme.gyp:native_theme',
'../ui/surface/surface.gyp:surface',
'../url/ipc/url_ipc.gyp:url_ipc',
@@ -76,6 +75,7 @@
'public/renderer/navigation_state.h',
'public/renderer/pepper_plugin_instance.h',
'public/renderer/platform_event_observer.h',
+ 'public/renderer/render_accessibility.h',
'public/renderer/render_frame.h',
'public/renderer/render_frame_observer.cc',
'public/renderer/render_frame_observer.h',
@@ -93,7 +93,7 @@
'public/renderer/resource_fetcher.h',
'public/renderer/video_encode_accelerator.cc',
'public/renderer/video_encode_accelerator.h',
- 'public/renderer/video_frame_provider.h',
+ 'public/renderer/media_stream_video_renderer.h',
],
'public_renderer_plugin_sources': [
'public/renderer/plugin_instance_throttler.h',
@@ -103,8 +103,8 @@
'renderer/accessibility/blink_ax_enum_conversion.h',
'renderer/accessibility/blink_ax_tree_source.cc',
'renderer/accessibility/blink_ax_tree_source.h',
- 'renderer/accessibility/renderer_accessibility.cc',
- 'renderer/accessibility/renderer_accessibility.h',
+ 'renderer/accessibility/render_accessibility_impl.cc',
+ 'renderer/accessibility/render_accessibility_impl.h',
'renderer/android/address_detector.cc',
'renderer/android/address_detector.h',
'renderer/android/content_detector.cc',
@@ -117,8 +117,6 @@
'renderer/android/phone_number_detector.h',
'renderer/android/renderer_date_time_picker.cc',
'renderer/android/renderer_date_time_picker.h',
- 'renderer/android/synchronous_compositor_external_begin_frame_source.cc',
- 'renderer/android/synchronous_compositor_external_begin_frame_source.h',
'renderer/android/synchronous_compositor_filter.cc',
'renderer/android/synchronous_compositor_filter.h',
'renderer/android/synchronous_compositor_output_surface.cc',
@@ -128,10 +126,8 @@
'renderer/android/synchronous_compositor_registry.h',
'renderer/background_sync/background_sync_client_impl.cc',
'renderer/background_sync/background_sync_client_impl.h',
- 'renderer/bluetooth/bluetooth_dispatcher.cc',
- 'renderer/bluetooth/bluetooth_dispatcher.h',
- 'renderer/bluetooth/bluetooth_message_filter.cc',
- 'renderer/bluetooth/bluetooth_message_filter.h',
+ 'renderer/bluetooth/bluetooth_type_converters.cc',
+ 'renderer/bluetooth/bluetooth_type_converters.h',
'renderer/bluetooth/web_bluetooth_impl.cc',
'renderer/bluetooth/web_bluetooth_impl.h',
'renderer/browser_plugin/browser_plugin.cc',
@@ -144,6 +140,8 @@
'renderer/cache_storage/cache_storage_message_filter.h',
'renderer/cache_storage/webserviceworkercachestorage_impl.cc',
'renderer/cache_storage/webserviceworkercachestorage_impl.h',
+ 'renderer/categorized_worker_pool.cc',
+ 'renderer/categorized_worker_pool.h',
'renderer/child_frame_compositing_helper.cc',
'renderer/child_frame_compositing_helper.h',
'renderer/clipboard_utils.cc',
@@ -216,14 +214,10 @@
'renderer/gpu/compositor_forwarding_message_filter.h',
'renderer/gpu/compositor_output_surface.cc',
'renderer/gpu/compositor_output_surface.h',
- 'renderer/gpu/delegated_compositor_output_surface.cc',
- 'renderer/gpu/delegated_compositor_output_surface.h',
'renderer/gpu/frame_swap_message_queue.cc',
'renderer/gpu/frame_swap_message_queue.h',
'renderer/gpu/gpu_benchmarking_extension.cc',
'renderer/gpu/gpu_benchmarking_extension.h',
- 'renderer/gpu/mailbox_output_surface.cc',
- 'renderer/gpu/mailbox_output_surface.h',
'renderer/gpu/queue_message_swap_promise.cc',
'renderer/gpu/queue_message_swap_promise.h',
'renderer/gpu/render_widget_compositor.cc',
@@ -307,6 +301,9 @@
'renderer/media/audio_message_filter.h',
'renderer/media/audio_renderer_mixer_manager.cc',
'renderer/media/audio_renderer_mixer_manager.h',
+ 'renderer/media/audio_renderer_sink_cache.h',
+ 'renderer/media/audio_renderer_sink_cache_impl.cc',
+ 'renderer/media/audio_renderer_sink_cache_impl.h',
'renderer/media/cdm/pepper_cdm_wrapper.h',
'renderer/media/cdm/pepper_cdm_wrapper_impl.cc',
'renderer/media/cdm/pepper_cdm_wrapper_impl.h',
@@ -314,6 +311,8 @@
'renderer/media/cdm/ppapi_decryptor.h',
'renderer/media/cdm/render_cdm_factory.cc',
'renderer/media/cdm/render_cdm_factory.h',
+ 'renderer/media/html_audio_element_capturer_source.cc',
+ 'renderer/media/html_audio_element_capturer_source.h',
'renderer/media/external_media_stream_audio_source.cc',
'renderer/media/external_media_stream_audio_source.h',
'renderer/media/media_permission_dispatcher.cc',
@@ -368,8 +367,8 @@
'renderer/menu_item_builder.h',
'renderer/mojo/blink_service_registry_impl.cc',
'renderer/mojo/blink_service_registry_impl.h',
- 'renderer/mojo/service_registry_js_wrapper.cc',
- 'renderer/mojo/service_registry_js_wrapper.h',
+ 'renderer/mojo/interface_provider_js_wrapper.cc',
+ 'renderer/mojo/interface_provider_js_wrapper.h',
'renderer/mojo_bindings_controller.cc',
'renderer/mojo_bindings_controller.h',
'renderer/mojo_context_state.cc',
@@ -394,8 +393,6 @@
'renderer/presentation/presentation_dispatcher.h',
'renderer/push_messaging/push_messaging_dispatcher.cc',
'renderer/push_messaging/push_messaging_dispatcher.h',
- 'renderer/raster_worker_pool.cc',
- 'renderer/raster_worker_pool.h',
'renderer/render_frame_impl.cc',
'renderer/render_frame_impl.h',
'renderer/render_frame_proxy.cc',
@@ -409,13 +406,13 @@
'renderer/render_view_impl.h',
'renderer/render_view_impl_android.cc',
'renderer/render_view_linux.cc',
- 'renderer/render_view_mouse_lock_dispatcher.cc',
- 'renderer/render_view_mouse_lock_dispatcher.h',
'renderer/render_view_win.cc',
'renderer/render_widget.cc',
'renderer/render_widget.h',
'renderer/render_widget_fullscreen.cc',
'renderer/render_widget_fullscreen.h',
+ 'renderer/render_widget_mouse_lock_dispatcher.cc',
+ 'renderer/render_widget_mouse_lock_dispatcher.h',
'renderer/render_widget_owner_delegate.h',
'renderer/renderer_blink_platform_impl.cc',
'renderer/renderer_blink_platform_impl.h',
@@ -520,6 +517,8 @@
'renderer/pepper/host_var_tracker.h',
'renderer/pepper/message_channel.cc',
'renderer/pepper/message_channel.h',
+ 'renderer/pepper/pepper_audio_controller.cc',
+ 'renderer/pepper/pepper_audio_controller.h',
'renderer/pepper/pepper_audio_encoder_host.cc',
'renderer/pepper/pepper_audio_encoder_host.h',
'renderer/pepper/pepper_audio_input_host.cc',
@@ -647,6 +646,14 @@
'renderer/media/audio_track_recorder.h',
'renderer/media/canvas_capture_handler.cc',
'renderer/media/canvas_capture_handler.h',
+ 'renderer/media/gpu/rtc_video_decoder.cc',
+ 'renderer/media/gpu/rtc_video_decoder.h',
+ 'renderer/media/gpu/rtc_video_decoder_factory.cc',
+ 'renderer/media/gpu/rtc_video_decoder_factory.h',
+ 'renderer/media/gpu/rtc_video_encoder.cc',
+ 'renderer/media/gpu/rtc_video_encoder.h',
+ 'renderer/media/gpu/rtc_video_encoder_factory.cc',
+ 'renderer/media/gpu/rtc_video_encoder_factory.h',
'renderer/media/html_video_element_capturer_source.cc',
'renderer/media/html_video_element_capturer_source.h',
'renderer/media/image_capture_frame_grabber.cc',
@@ -688,14 +695,6 @@
'renderer/media/rtc_dtmf_sender_handler.h',
'renderer/media/rtc_peer_connection_handler.cc',
'renderer/media/rtc_peer_connection_handler.h',
- 'renderer/media/rtc_video_decoder.cc',
- 'renderer/media/rtc_video_decoder.h',
- 'renderer/media/rtc_video_decoder_factory.cc',
- 'renderer/media/rtc_video_decoder_factory.h',
- 'renderer/media/rtc_video_encoder.cc',
- 'renderer/media/rtc_video_encoder.h',
- 'renderer/media/rtc_video_encoder_factory.cc',
- 'renderer/media/rtc_video_encoder_factory.h',
'renderer/media/secure_display_link_tracker.h',
'renderer/media/speech_recognition_audio_sink.cc',
'renderer/media/speech_recognition_audio_sink.h',
diff --git a/chromium/content/content_resources.grd b/chromium/content/content_resources.grd
index 014468c2134..64d2f5300fc 100644
--- a/chromium/content/content_resources.grd
+++ b/chromium/content/content_resources.grd
@@ -13,32 +13,34 @@
<include name="IDR_ACCESSIBILITY_HTML" file="browser/resources/accessibility/accessibility.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_ACCESSIBILITY_CSS" file="browser/resources/accessibility/accessibility.css" type="BINDATA" />
<include name="IDR_ACCESSIBILITY_JS" file="browser/resources/accessibility/accessibility.js" flattenhtml="true" type="BINDATA" />
- <include name="IDR_APPCACHE_INTERNALS_HTML" file="browser/resources/appcache/appcache_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
- <include name="IDR_APPCACHE_INTERNALS_JS" file="browser/resources/appcache/appcache_internals.js" flattenhtml="false" type="BINDATA" />
- <include name="IDR_APPCACHE_INTERNALS_CSS" file="browser/resources/appcache/appcache_internals.css" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_APPCACHE_INTERNALS_HTML" file="browser/resources/appcache/appcache_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_APPCACHE_INTERNALS_JS" file="browser/resources/appcache/appcache_internals.js" flattenhtml="false" compress="gzip" type="BINDATA" />
+ <include name="IDR_APPCACHE_INTERNALS_CSS" file="browser/resources/appcache/appcache_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_DEVTOOLS_PINCH_CURSOR_ICON" file="browser/resources/devtools/devtools_pinch_cursor.png" type="BINDATA" />
<include name="IDR_DEVTOOLS_PINCH_CURSOR_ICON_2X" file="browser/resources/devtools/devtools_pinch_cursor_2x.png" type="BINDATA" />
<include name="IDR_DEVTOOLS_TOUCH_CURSOR_ICON" file="browser/resources/devtools/devtools_touch_cursor.png" type="BINDATA" />
<include name="IDR_DEVTOOLS_TOUCH_CURSOR_ICON_2X" file="browser/resources/devtools/devtools_touch_cursor_2x.png" type="BINDATA" />
- <include name="IDR_GPU_INTERNALS_HTML" file="browser/resources/gpu/gpu_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
- <include name="IDR_GPU_INTERNALS_JS" file="browser/resources/gpu/gpu_internals.js" flattenhtml="true" type="BINDATA" />
- <include name="IDR_INDEXED_DB_INTERNALS_HTML" file="browser/resources/indexed_db/indexeddb_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
- <include name="IDR_INDEXED_DB_INTERNALS_JS" file="browser/resources/indexed_db/indexeddb_internals.js" flattenhtml="true" type="BINDATA" />
- <include name="IDR_INDEXED_DB_INTERNALS_CSS" file="browser/resources/indexed_db/indexeddb_internals.css" flattenhtml="true" type="BINDATA" />
- <include name="IDR_MEDIA_INTERNALS_HTML" file="browser/resources/media/media_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
- <include name="IDR_MEDIA_INTERNALS_JS" file="browser/resources/media/media_internals.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_GPU_INTERNALS_HTML" file="browser/resources/gpu/gpu_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_GPU_INTERNALS_JS" file="browser/resources/gpu/gpu_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_INDEXED_DB_INTERNALS_HTML" file="browser/resources/indexed_db/indexeddb_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_INDEXED_DB_INTERNALS_JS" file="browser/resources/indexed_db/indexeddb_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_INDEXED_DB_INTERNALS_CSS" file="browser/resources/indexed_db/indexeddb_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_MEDIA_INTERNALS_HTML" file="browser/resources/media/media_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_MEDIA_INTERNALS_JS" file="browser/resources/media/media_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_MOJO_CATALOG_MANIFEST" file="../services/catalog/manifest.json" type="BINDATA" />
<include name="IDR_MOJO_CONTENT_BROWSER_MANIFEST" file="${root_out_dir}/content_browser_manifest.json" use_base_dir="false" type="BINDATA" />
+ <include name="IDR_MOJO_CONTENT_GPU_MANIFEST" file="${root_out_dir}/content_gpu_manifest.json" use_base_dir="false" type="BINDATA" />
<include name="IDR_MOJO_CONTENT_RENDERER_MANIFEST" file="${root_out_dir}/content_renderer_manifest.json" use_base_dir="false" type="BINDATA" />
+ <include name="IDR_MOJO_CONTENT_UTILITY_MANIFEST" file="${root_out_dir}/content_utility_manifest.json" use_base_dir="false" type="BINDATA" />
<include name="IDR_MOJO_PROFILE_MANIFEST" file="../services/user/manifest.json" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_HTML" file="browser/resources/net/network_errors_listing.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_JS" file="browser/resources/net/network_errors_listing.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_CSS" file="browser/resources/net/network_errors_listing.css" flattenhtml="true" type="BINDATA" />
- <include name="IDR_SERVICE_WORKER_INTERNALS_HTML" file="browser/resources/service_worker/serviceworker_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
- <include name="IDR_SERVICE_WORKER_INTERNALS_JS" file="browser/resources/service_worker/serviceworker_internals.js" flattenhtml="true" type="BINDATA" />
- <include name="IDR_SERVICE_WORKER_INTERNALS_CSS" file="browser/resources/service_worker/serviceworker_internals.css" flattenhtml="true" type="BINDATA" />
- <include name="IDR_WEBRTC_INTERNALS_HTML" file="browser/resources/media/webrtc_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
- <include name="IDR_WEBRTC_INTERNALS_JS" file="browser/resources/media/webrtc_internals.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_SERVICE_WORKER_INTERNALS_HTML" file="browser/resources/service_worker/serviceworker_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_SERVICE_WORKER_INTERNALS_JS" file="browser/resources/service_worker/serviceworker_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_SERVICE_WORKER_INTERNALS_CSS" file="browser/resources/service_worker/serviceworker_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_WEBRTC_INTERNALS_HTML" file="browser/resources/media/webrtc_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_WEBRTC_INTERNALS_JS" file="browser/resources/media/webrtc_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<if expr="is_macosx">
<include name="IDR_GPU_SANDBOX_PROFILE" file="browser/gpu.sb" type="BINDATA" />
<include name="IDR_COMMON_SANDBOX_PROFILE" file="common/common.sb" type="BINDATA" />
diff --git a/chromium/content/content_resources.gypi b/chromium/content/content_resources.gypi
index 0838f75691a..a9dfe226de5 100644
--- a/chromium/content/content_resources.gypi
+++ b/chromium/content/content_resources.gypi
@@ -34,7 +34,9 @@
'dependencies': [
'<(DEPTH)/services/shell/shell.gyp:catalog_manifest',
'content_app_browser_manifest',
+ 'content_app_gpu_manifest',
'content_app_renderer_manifest',
+ 'content_app_utility_manifest',
],
},
],
diff --git a/chromium/content/content_shell.gypi b/chromium/content/content_shell.gypi
index 9358219c171..999577e54dc 100644
--- a/chromium/content/content_shell.gypi
+++ b/chromium/content/content_shell.gypi
@@ -41,6 +41,7 @@
'../components/components.gyp:crash_component_breakpad_to_be_deleted',
'../components/components.gyp:devtools_discovery',
'../components/components.gyp:devtools_http_handler',
+ '../components/components.gyp:network_session_configurator_switches',
'../components/components.gyp:web_cache_renderer',
'../components/components.gyp:plugins_renderer',
'../components/test_runner/test_runner.gyp:test_runner',
@@ -120,6 +121,8 @@
'shell/browser/layout_test/layout_test_devtools_frontend.h',
'shell/browser/layout_test/layout_test_download_manager_delegate.cc',
'shell/browser/layout_test/layout_test_download_manager_delegate.h',
+ 'shell/browser/layout_test/layout_test_first_device_bluetooth_chooser.cc',
+ 'shell/browser/layout_test/layout_test_first_device_bluetooth_chooser.h',
'shell/browser/layout_test/layout_test_javascript_dialog_manager.cc',
'shell/browser/layout_test/layout_test_javascript_dialog_manager.h',
'shell/browser/layout_test/layout_test_message_filter.cc',
@@ -205,6 +208,8 @@
'shell/common/leak_detection_result.h',
'shell/common/shell_content_client.cc',
'shell/common/shell_content_client.h',
+ 'shell/common/shell_origin_trial_policy.cc',
+ 'shell/common/shell_origin_trial_policy.h',
'shell/common/shell_messages.cc',
'shell/common/shell_messages.h',
'shell/common/shell_switches.cc',
@@ -227,8 +232,8 @@
'shell/renderer/layout_test/leak_detector.h',
'shell/renderer/layout_test/test_media_stream_renderer_factory.cc',
'shell/renderer/layout_test/test_media_stream_renderer_factory.h',
- 'shell/renderer/layout_test/test_video_frame_provider.cc',
- 'shell/renderer/layout_test/test_video_frame_provider.h',
+ 'shell/renderer/layout_test/test_media_stream_video_renderer.cc',
+ 'shell/renderer/layout_test/test_media_stream_video_renderer.h',
'shell/renderer/shell_content_renderer_client.cc',
'shell/renderer/shell_content_renderer_client.h',
'shell/renderer/shell_render_view_observer.cc',
diff --git a/chromium/content/content_tests.gypi b/chromium/content/content_tests.gypi
index 77d0856d429..e89ee96fd97 100644
--- a/chromium/content/content_tests.gypi
+++ b/chromium/content/content_tests.gypi
@@ -95,10 +95,14 @@
'public/test/test_web_contents_factory.h',
'public/test/test_web_ui.cc',
'public/test/test_web_ui.h',
+ 'public/test/text_input_test_utils.cc',
+ 'public/test/text_input_test_utils.h',
'public/test/unittest_test_suite.cc',
'public/test/unittest_test_suite.h',
'public/test/web_contents_tester.cc',
'public/test/web_contents_tester.h',
+ 'test/accessibility_browser_test_utils.cc',
+ 'test/accessibility_browser_test_utils.h',
'test/appcache_test_helper.cc',
'test/appcache_test_helper.h',
'test/blink_test_environment.cc',
@@ -273,6 +277,7 @@
'browser/tracing/memory_tracing_browsertest.cc',
'browser/tracing/tracing_controller_browsertest.cc',
'browser/utility_process_host_impl_browsertest.cc',
+ 'browser/utility_process_mojo_client_browsertest.cc',
'browser/vibration_browsertest.cc',
'browser/wake_lock/wake_lock_browsertest.cc',
'browser/web_contents/opened_by_dom_browsertest.cc',
@@ -281,7 +286,7 @@
'browser/webkit_browsertest.cc',
'browser/webui/web_ui_mojo_browsertest.cc',
'child/site_isolation_stats_gatherer_browsertest.cc',
- 'renderer/accessibility/renderer_accessibility_browsertest.cc',
+ 'renderer/accessibility/render_accessibility_impl_browsertest.cc',
'renderer/devtools/v8_sampling_profiler_browsertest.cc',
'renderer/gin_browsertest.cc',
'renderer/history_controller_browsertest.cc',
@@ -293,8 +298,6 @@
'renderer/render_view_browsertest_mac.mm',
'renderer/render_widget_browsertest.cc',
'renderer/visual_state_browsertest.cc',
- 'test/accessibility_browser_test_utils.cc',
- 'test/accessibility_browser_test_utils.h',
'test/browser_test_utils_browsertest.cc',
'test/content_browser_test_test.cc',
'test/webui_resource_browsertest.cc',
@@ -307,7 +310,7 @@
'content_browsertests_webrtc_sources': [
'browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc',
'browser/media/webrtc/webrtc_browsertest.cc',
- 'browser/media/webrtc/webrtc_canvas_capture_browsertest.cc',
+ 'browser/media/webrtc/webrtc_capture_from_element_browsertest.cc',
'browser/media/webrtc/webrtc_datachannel_browsertest.cc',
'browser/media/webrtc/webrtc_getusermedia_browsertest.cc',
'browser/media/webrtc/webrtc_internals_browsertest.cc',
@@ -393,7 +396,6 @@
'browser/cache_storage/cache_storage_cache_unittest.cc',
'browser/cache_storage/cache_storage_manager_unittest.cc',
'browser/cache_storage/cache_storage_scheduler_unittest.cc',
- 'browser/cache_storage/cache_storage_unittest.cc',
'browser/child_process_security_policy_unittest.cc',
'browser/cocoa/system_hotkey_map_unittest.mm',
'browser/compositor/reflector_impl_unittest.cc',
@@ -461,6 +463,7 @@
'browser/fileapi/timed_task_helper_unittest.cc',
'browser/fileapi/transient_file_util_unittest.cc',
'browser/fileapi/upload_file_system_file_element_reader_unittest.cc',
+ 'browser/frame_host/frame_tree_node_blame_context_unittest.cc',
'browser/frame_host/frame_tree_unittest.cc',
'browser/frame_host/navigation_controller_impl_unittest.cc',
'browser/frame_host/navigation_entry_impl_unittest.cc',
@@ -469,10 +472,9 @@
'browser/frame_host/render_frame_host_manager_unittest.cc',
'browser/frame_host/render_widget_host_view_child_frame_unittest.cc',
'browser/frame_host/render_widget_host_view_guest_unittest.cc',
- 'browser/gamepad/gamepad_provider_unittest.cc',
'browser/gamepad/gamepad_service_unittest.cc',
- 'browser/gamepad/gamepad_test_helpers.cc',
- 'browser/gamepad/gamepad_test_helpers.h',
+ 'browser/gamepad/gamepad_service_test_helpers.cc',
+ 'browser/gamepad/gamepad_service_test_helpers.h',
'browser/geolocation/geolocation_provider_impl_unittest.cc',
'browser/geolocation/location_arbitrator_impl_unittest.cc',
'browser/geolocation/network_location_provider_unittest.cc',
@@ -602,9 +604,9 @@
'browser/service_worker/embedded_worker_test_helper.h',
'browser/service_worker/link_header_support_unittest.cc',
'browser/service_worker/service_worker_cache_writer_unittest.cc',
+ 'browser/service_worker/service_worker_context_core_unittest.cc',
'browser/service_worker/service_worker_context_request_handler_unittest.cc',
'browser/service_worker/service_worker_context_unittest.cc',
- 'browser/service_worker/service_worker_context_core_unittest.cc',
'browser/service_worker/service_worker_controllee_request_handler_unittest.cc',
'browser/service_worker/service_worker_database_unittest.cc',
'browser/service_worker/service_worker_dispatcher_host_unittest.cc',
@@ -688,6 +690,7 @@
'common/inter_process_time_ticks_converter_unittest.cc',
'common/mac/attributed_string_coder_unittest.mm',
'common/mac/font_descriptor_unittest.mm',
+ 'common/navigation_params_unittest.cc',
'common/one_writer_seqlock_unittest.cc',
'common/origin_trials/trial_token_unittest.cc',
'common/origin_trials/trial_token_validator_unittest.cc',
@@ -708,6 +711,7 @@
'renderer/android/email_detector_unittest.cc',
'renderer/android/phone_number_detector_unittest.cc',
'renderer/bmp_image_decoder_unittest.cc',
+ 'renderer/categorized_worker_pool_unittest.cc',
'renderer/device_sensors/device_light_event_pump_unittest.cc',
'renderer/device_sensors/device_motion_event_pump_unittest.cc',
'renderer/device_sensors/device_orientation_event_pump_unittest.cc',
@@ -723,6 +727,8 @@
'renderer/media/android/media_info_loader_unittest.cc',
'renderer/media/audio_message_filter_unittest.cc',
'renderer/media/audio_renderer_mixer_manager_unittest.cc',
+ 'renderer/media/audio_renderer_sink_cache_unittest.cc',
+ 'renderer/media/html_audio_element_capturer_source_unittest.cc',
'renderer/media/media_stream_audio_unittest.cc',
'renderer/media/midi_message_filter_unittest.cc',
'renderer/media/mock_audio_device_factory.cc',
@@ -734,7 +740,6 @@
'renderer/media/video_capture_message_filter_unittest.cc',
'renderer/media/webmediaplayer_ms_unittest.cc',
'renderer/peripheral_content_heuristic_unittest.cc',
- 'renderer/raster_worker_pool_unittest.cc',
'renderer/render_thread_impl_unittest.cc',
'renderer/render_widget_unittest.cc',
'renderer/scheduler/resource_dispatch_throttler_unittest.cc',
@@ -779,6 +784,7 @@
'renderer/media/audio_repetition_detector_unittest.cc',
'renderer/media/audio_track_recorder_unittest.cc',
'renderer/media/canvas_capture_handler_unittest.cc',
+ 'renderer/media/gpu/rtc_video_decoder_unittest.cc',
'renderer/media/html_video_element_capturer_source_unittest.cc',
'renderer/media/media_recorder_handler_unittest.cc',
'renderer/media/media_stream_audio_processor_unittest.cc',
@@ -798,7 +804,6 @@
'renderer/media/peer_connection_tracker_unittest.cc',
'renderer/media/rtc_data_channel_handler_unittest.cc',
'renderer/media/rtc_peer_connection_handler_unittest.cc',
- 'renderer/media/rtc_video_decoder_unittest.cc',
'renderer/media/speech_recognition_audio_sink_unittest.cc',
'renderer/media/user_media_client_impl_unittest.cc',
'renderer/media/video_track_recorder_unittest.cc',
@@ -842,10 +847,11 @@
'../components/components.gyp:display_compositor',
'../components/scheduler/scheduler.gyp:scheduler',
'../components/scheduler/scheduler.gyp:scheduler_test_support',
+ '../device/gamepad/gamepad.gyp:device_gamepad',
'../gpu/gpu.gyp:gpu_ipc_common',
'../gpu/gpu.gyp:gpu_ipc_service_test_support',
- '../ipc/mojo/ipc_mojo.gyp:ipc_mojo',
'../media/blink/media_blink.gyp:media_blink',
+ '../media/capture/capture.gyp:capture',
'../media/media.gyp:media',
'../media/midi/midi.gyp:midi',
'../mojo/mojo_edk.gyp:mojo_common_test_support',
@@ -979,6 +985,11 @@
'../third_party/libvpx/libvpx.gyp:libvpx',
],
}],
+ ['OS=="mac"', {
+ 'dependencies': [
+ '../ui/accelerated_widget_mac/accelerated_widget_mac.gyp:accelerated_widget_mac',
+ ],
+ }],
['OS=="android"', {
'dependencies': [
'../ui/android/ui_android.gyp:ui_android',
@@ -999,6 +1010,7 @@
'type': 'static_library',
'dependencies': [
'content.gyp:content_renderer',
+ '../device/nfc/nfc.gyp:device_nfc_mojo_bindings',
'test_support_content',
'../components/scheduler/scheduler.gyp:scheduler_test_support',
'../components/test_runner/test_runner.gyp:test_runner',
@@ -1048,6 +1060,7 @@
'../device/battery/battery.gyp:device_battery_mojo_bindings',
'../device/bluetooth/bluetooth.gyp:device_bluetooth',
'../device/bluetooth/bluetooth.gyp:device_bluetooth_mocks',
+ '../device/gamepad/gamepad.gyp:device_gamepad_test_helpers',
'../gin/gin.gyp:gin',
'../gpu/gpu.gyp:gpu',
'../gpu/gpu.gyp:gpu_unittest_utils',
@@ -1384,13 +1397,13 @@
'../base/base.gyp:test_support_base',
'../device/battery/battery.gyp:device_battery',
'../device/battery/battery.gyp:device_battery_mojo_bindings',
+ '../device/power_save_blocker/power_save_blocker.gyp:device_power_save_blocker',
'../device/vibration/vibration.gyp:device_vibration_mojo_bindings',
'../gin/gin.gyp:gin',
'../gpu/gpu.gyp:gpu',
'../ipc/ipc.gyp:test_support_ipc',
'../media/media.gyp:media_test_support',
'../media/media.gyp:shared_memory_support',
- '../mojo/mojo_base.gyp:mojo_test_support',
'../mojo/mojo_edk.gyp:mojo_common_test_support',
'../mojo/mojo_edk.gyp:mojo_system_impl',
'../mojo/mojo_public.gyp:mojo_cpp_bindings',
@@ -1827,6 +1840,7 @@
'../base/base.gyp:base_javatests',
'../base/base.gyp:base_java_test_support',
'../device/battery/battery.gyp:device_battery_javatests',
+ '../media/capture/capture.gyp:capture_java',
'../media/media.gyp:media_java',
'../media/media.gyp:media_test_support',
'../mojo/mojo_public.gyp:mojo_public_test_interfaces',
diff --git a/chromium/content/content_utility.gypi b/chromium/content/content_utility.gypi
index 0589e933c00..13f77149a79 100644
--- a/chromium/content/content_utility.gypi
+++ b/chromium/content/content_utility.gypi
@@ -5,11 +5,11 @@
{
'dependencies': [
'../base/base.gyp:base',
- '../courgette/courgette.gyp:courgette_lib',
'../mojo/mojo_base.gyp:mojo_common_lib',
'../mojo/mojo_public.gyp:mojo_cpp_bindings',
'../services/shell/shell.gyp:shell_lib',
'../services/shell/shell_public.gyp:shell_public',
+ '../third_party/WebKit/public/blink.gyp:blink',
'../url/url.gyp:url_lib',
],
'variables': {
diff --git a/chromium/content/gpu/gpu_child_thread.cc b/chromium/content/gpu/gpu_child_thread.cc
index cc97e948cf2..a81892212b9 100644
--- a/chromium/content/gpu/gpu_child_thread.cc
+++ b/chromium/content/gpu/gpu_child_thread.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_local.h"
@@ -97,8 +98,6 @@ class GpuMemoryBufferMessageFilter : public IPC::MessageFilter {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(GpuMemoryBufferMessageFilter, message)
IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer, OnCreateGpuMemoryBuffer)
- IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBufferFromHandle,
- OnCreateGpuMemoryBufferFromHandle)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -119,18 +118,6 @@ class GpuMemoryBufferMessageFilter : public IPC::MessageFilter {
params.client_id, params.surface_handle)));
}
- void OnCreateGpuMemoryBufferFromHandle(
- const GpuMsg_CreateGpuMemoryBufferFromHandle_Params& params) {
- TRACE_EVENT2(
- "gpu",
- "GpuMemoryBufferMessageFilter::OnCreateGpuMemoryBufferFromHandle", "id",
- params.id.id, "client_id", params.client_id);
- sender_->Send(new GpuHostMsg_GpuMemoryBufferCreated(
- gpu_memory_buffer_factory_->CreateGpuMemoryBufferFromHandle(
- params.handle, params.id, params.size, params.format,
- params.client_id)));
- }
-
gpu::GpuMemoryBufferFactory* const gpu_memory_buffer_factory_;
IPC::Sender* sender_;
};
@@ -234,13 +221,13 @@ void GpuChildThread::Init(const base::Time& process_start_time) {
// Only set once per process instance.
process_control_.reset(new GpuProcessControlImpl());
- // Use of base::Unretained(this) is safe here because |service_registry()|
- // will be destroyed before GpuChildThread is destructed.
- service_registry()->AddService(base::Bind(
- &GpuChildThread::BindProcessControlRequest, base::Unretained(this)));
-
if (GetContentClient()->gpu()) // NULL in tests.
- GetContentClient()->gpu()->RegisterMojoServices(service_registry());
+ GetContentClient()->gpu()->Initialize(this);
+}
+
+void GpuChildThread::OnFieldTrialGroupFinalized(const std::string& trial_name,
+ const std::string& group_name) {
+ Send(new GpuHostMsg_FieldTrialActivated(trial_name));
}
bool GpuChildThread::Send(IPC::Message* msg) {
@@ -303,6 +290,37 @@ bool GpuChildThread::OnMessageReceived(const IPC::Message& msg) {
return false;
}
+bool GpuChildThread::AcceptConnection(shell::Connection* connection) {
+ // Use of base::Unretained(this) is safe here because |service_registry()|
+ // will be destroyed before GpuChildThread is destructed.
+ connection->GetInterfaceRegistry()->AddInterface(base::Bind(
+ &GpuChildThread::BindProcessControlRequest, base::Unretained(this)));
+
+ if (GetContentClient()->gpu()) { // NULL in tests.
+ GetContentClient()->gpu()->ExposeInterfacesToBrowser(
+ connection->GetInterfaceRegistry());
+ }
+
+ // We don't want to process any incoming interface requests until
+ // OnInitialize().
+ if (!gpu_channel_manager_) {
+ connection->GetInterfaceRegistry()->PauseBinding();
+ resume_interface_bindings_callback_ = base::Bind(
+ &shell::InterfaceRegistry::ResumeBinding,
+ connection->GetInterfaceRegistry()->GetWeakPtr());
+ }
+
+ return true;
+}
+
+shell::InterfaceRegistry* GpuChildThread::GetInterfaceRegistryForConnection() {
+ return nullptr;
+}
+
+shell::InterfaceProvider* GpuChildThread::GetInterfaceProviderForConnection() {
+ return nullptr;
+}
+
void GpuChildThread::SetActiveURL(const GURL& url) {
GetContentClient()->SetActiveURL(url);
}
@@ -346,6 +364,9 @@ void GpuChildThread::StoreShaderToDisk(int32_t client_id,
}
void GpuChildThread::OnInitialize(const gpu::GpuPreferences& gpu_preferences) {
+ if (!resume_interface_bindings_callback_.is_null())
+ base::ResetAndReturn(&resume_interface_bindings_callback_).Run();
+
gpu_preferences_ = gpu_preferences;
gpu_info_.video_decode_accelerator_capabilities =
@@ -418,6 +439,9 @@ void GpuChildThread::StopWatchdog() {
}
void GpuChildThread::OnCollectGraphicsInfo() {
+ if (dead_on_arrival_)
+ return;
+
#if defined(OS_WIN)
// GPU full info collection should only happen on un-sandboxed GPU process
// or single process/in-process gpu mode on Windows.
@@ -507,7 +531,8 @@ void GpuChildThread::OnDisableWatchdog() {
void GpuChildThread::OnGpuSwitched() {
DVLOG(1) << "GPU: GPU has switched";
// Notify observers in the GPU process.
- ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
+ if (!in_browser_process_)
+ ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
}
void GpuChildThread::OnEstablishChannel(const EstablishChannelParams& params) {
diff --git a/chromium/content/gpu/gpu_child_thread.h b/chromium/content/gpu/gpu_child_thread.h
index 304798230a7..2141c7783e1 100644
--- a/chromium/content/gpu/gpu_child_thread.h
+++ b/chromium/content/gpu/gpu_child_thread.h
@@ -11,9 +11,11 @@
#include <queue>
#include <string>
+#include "base/callback.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/metrics/field_trial.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/child/child_thread_impl.h"
@@ -52,7 +54,8 @@ struct EstablishChannelParams;
// IPC messages to gpu::GpuChannelManager, which is responsible for issuing
// rendering commands to the GPU.
class GpuChildThread : public ChildThreadImpl,
- public gpu::GpuChannelManagerDelegate {
+ public gpu::GpuChannelManagerDelegate,
+ public base::FieldTrialList::Observer {
public:
typedef std::queue<IPC::Message*> DeferredMessages;
@@ -80,12 +83,15 @@ class GpuChildThread : public ChildThreadImpl,
gpu::GpuPreferences gpu_preferences() { return gpu_preferences_; }
private:
- // ChildThread overrides.
+ // ChildThreadImpl:.
bool Send(IPC::Message* msg) override;
bool OnControlMessageReceived(const IPC::Message& msg) override;
bool OnMessageReceived(const IPC::Message& msg) override;
+ bool AcceptConnection(shell::Connection* connection) override;
+ shell::InterfaceRegistry* GetInterfaceRegistryForConnection() override;
+ shell::InterfaceProvider* GetInterfaceProviderForConnection() override;
- // gpu::GpuChannelManagerDelegate implementation.
+ // gpu::GpuChannelManagerDelegate:
void SetActiveURL(const GURL& url) override;
void DidCreateOffscreenContext(const GURL& active_url) override;
void DidDestroyChannel(int client_id) override;
@@ -103,6 +109,10 @@ class GpuChildThread : public ChildThreadImpl,
const std::string& key,
const std::string& shader) override;
+ // base::FieldTrialList::Observer:
+ void OnFieldTrialGroupFinalized(const std::string& trial_name,
+ const std::string& group_name) override;
+
// Message handlers.
void OnInitialize(const gpu::GpuPreferences& gpu_preferences);
void OnFinalize();
@@ -169,6 +179,8 @@ class GpuChildThread : public ChildThreadImpl,
// Bindings to the mojom::ProcessControl impl.
mojo::BindingSet<mojom::ProcessControl> process_control_bindings_;
+ base::Closure resume_interface_bindings_callback_;
+
DISALLOW_COPY_AND_ASSIGN(GpuChildThread);
};
diff --git a/chromium/content/gpu/gpu_main.cc b/chromium/content/gpu/gpu_main.cc
index 33563a036cf..bc2ee1287f6 100644
--- a/chromium/content/gpu/gpu_main.cc
+++ b/chromium/content/gpu/gpu_main.cc
@@ -51,7 +51,7 @@
#if defined(OS_ANDROID)
#include "base/trace_event/memory_dump_manager.h"
-#include "components/tracing/graphics_memory_dump_provider_android.h"
+#include "components/tracing/common/graphics_memory_dump_provider_android.h"
#endif
#if defined(OS_WIN)
@@ -191,6 +191,7 @@ int GpuMain(const MainFunctionParams& parameters) {
#if defined(OS_WIN)
// Use a UI message loop because ANGLE and the desktop GL platform can
// create child windows to render to.
+ base::MessagePumpForGpu::InitFactory();
base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI);
#elif defined(OS_LINUX) && defined(USE_X11)
// We need a UI loop so that we can grab the Expose events. See GLSurfaceGLX
@@ -296,7 +297,7 @@ int GpuMain(const MainFunctionParams& parameters) {
// Load and initialize the GL implementation and locate the GL entry points.
bool gl_initialized =
gl_already_initialized
- ? gfx::GetGLImplementation() != gfx::kGLImplementationNone
+ ? gl::GetGLImplementation() != gl::kGLImplementationNone
: gl::init::InitializeGLOneOff();
if (gl_initialized) {
// We need to collect GL strings (VENDOR, RENDERER) for blacklisting
@@ -360,7 +361,7 @@ int GpuMain(const MainFunctionParams& parameters) {
// OSMesa is expected to run very slowly, so disable the watchdog in that
// case.
if (enable_watchdog &&
- gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL) {
+ gl::GetGLImplementation() == gl::kGLImplementationOSMesaGL) {
watchdog_thread->Stop();
watchdog_thread = NULL;
}
@@ -530,7 +531,7 @@ bool CanAccessNvidiaDeviceFile() {
#endif
void CreateDummyGlContext() {
- scoped_refptr<gfx::GLSurface> surface(
+ scoped_refptr<gl::GLSurface> surface(
gl::init::CreateOffscreenGLSurface(gfx::Size()));
if (!surface.get()) {
DVLOG(1) << "gl::init::CreateOffscreenGLSurface failed";
@@ -539,8 +540,8 @@ void CreateDummyGlContext() {
// On Linux, this is needed to make sure /dev/nvidiactl has
// been opened and its descriptor cached.
- scoped_refptr<gfx::GLContext> context(
- gl::init::CreateGLContext(NULL, surface.get(), gfx::PreferDiscreteGpu));
+ scoped_refptr<gl::GLContext> context(
+ gl::init::CreateGLContext(NULL, surface.get(), gl::PreferDiscreteGpu));
if (!context.get()) {
DVLOG(1) << "gl::init::CreateGLContext failed";
return;
@@ -550,7 +551,7 @@ void CreateDummyGlContext() {
if (context->MakeCurrent(surface.get())) {
context->ReleaseCurrent(surface.get());
} else {
- DVLOG(1) << "gfx::GLContext::MakeCurrent failed";
+ DVLOG(1) << "gl::GLContext::MakeCurrent failed";
}
}
diff --git a/chromium/content/gpu/gpu_watchdog_thread.cc b/chromium/content/gpu/gpu_watchdog_thread.cc
index dddb40945af..cb2e8b7d171 100644
--- a/chromium/content/gpu/gpu_watchdog_thread.cc
+++ b/chromium/content/gpu/gpu_watchdog_thread.cc
@@ -29,11 +29,9 @@
namespace content {
namespace {
-#if defined(OS_CHROMEOS)
+#if defined(USE_X11)
const base::FilePath::CharType
kTtyFilePath[] = FILE_PATH_LITERAL("/sys/class/tty/tty0/active");
-#endif
-#if defined(USE_X11)
const unsigned char text[20] = "check";
#endif
} // namespace
@@ -55,6 +53,7 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout)
display_(NULL),
window_(0),
atom_(None),
+ host_tty_(-1),
#endif
weak_factory_(this) {
DCHECK(timeout >= 0);
@@ -73,10 +72,8 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout)
DCHECK(result);
#endif
-#if defined(OS_CHROMEOS)
- tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r");
-#endif
#if defined(USE_X11)
+ tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r");
SetupXServer();
#endif
watched_message_loop_->AddTaskObserver(&task_observer_);
@@ -136,12 +133,9 @@ GpuWatchdogThread::~GpuWatchdogThread() {
if (power_monitor)
power_monitor->RemoveObserver(this);
-#if defined(OS_CHROMEOS)
+#if defined(USE_X11)
if (tty_file_)
fclose(tty_file_);
-#endif
-
-#if defined(USE_X11)
XDestroyWindow(display_, window_);
XCloseDisplay(display_);
#endif
@@ -325,17 +319,11 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
return;
#endif
-#if defined(OS_CHROMEOS)
- // Don't crash if we're not on tty1. This avoids noise in the GPU process
- // crashes caused by people who use VT2 but still enable crash reporting.
- char tty_string[8] = {0};
- if (tty_file_ &&
- !fseek(tty_file_, 0, SEEK_SET) &&
- fread(tty_string, 1, 7, tty_file_)) {
- int tty_number = -1;
- int num_res = sscanf(tty_string, "tty%d", &tty_number);
- if (num_res == 1 && tty_number != 1)
- return;
+#if defined(USE_X11)
+ // Don't crash if we're not on the TTY of our host X11 server.
+ int active_tty = GetActiveTTY();
+ if(host_tty_ != -1 && active_tty != -1 && host_tty_ != active_tty) {
+ return;
}
#endif
@@ -358,6 +346,10 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
bool using_high_res_timer = base::Time::IsHighResolutionTimerInUse();
base::debug::Alias(&using_high_res_timer);
+
+ bool message_pump_is_signaled =
+ watched_message_loop_->MessagePumpWasSignaled();
+ base::debug::Alias(&message_pump_is_signaled);
#endif
base::Time current_time = base::Time::Now();
@@ -380,6 +372,7 @@ void GpuWatchdogThread::SetupXServer() {
window_ = XCreateWindow(display_, DefaultRootWindow(display_), 0, 0, 1, 1, 0,
CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
atom_ = XInternAtom(display_, "CHECK", False);
+ host_tty_ = GetActiveTTY();
}
void GpuWatchdogThread::SetupXChangeProp() {
@@ -463,4 +456,18 @@ base::ThreadTicks GpuWatchdogThread::GetWatchedThreadTime() {
}
#endif
+#if defined(USE_X11)
+int GpuWatchdogThread::GetActiveTTY() const {
+ char tty_string[8] = {0};
+ if (tty_file_ && !fseek(tty_file_, 0, SEEK_SET) &&
+ fread(tty_string, 1, 7, tty_file_)) {
+ int tty_number;
+ size_t num_res = sscanf(tty_string, "tty%d\n", &tty_number);
+ if (num_res == 1)
+ return tty_number;
+ }
+ return -1;
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/gpu/gpu_watchdog_thread.h b/chromium/content/gpu/gpu_watchdog_thread.h
index c8e00952b26..68d3cd8cb8d 100644
--- a/chromium/content/gpu/gpu_watchdog_thread.h
+++ b/chromium/content/gpu/gpu_watchdog_thread.h
@@ -91,6 +91,10 @@ class GpuWatchdogThread : public base::Thread,
base::ThreadTicks GetWatchedThreadTime();
#endif
+#if defined(USE_X11)
+ int GetActiveTTY() const;
+#endif
+
base::MessageLoop* watched_message_loop_;
base::TimeDelta timeout_;
volatile bool armed_;
@@ -127,14 +131,12 @@ class GpuWatchdogThread : public base::Thread,
base::Time check_time_;
base::TimeTicks check_timeticks_;
-#if defined(OS_CHROMEOS)
- FILE* tty_file_;
-#endif
-
#if defined(USE_X11)
XDisplay* display_;
gfx::AcceleratedWidget window_;
XAtom atom_;
+ FILE* tty_file_;
+ int host_tty_;
#endif
base::WeakPtrFactory<GpuWatchdogThread> weak_factory_;
diff --git a/chromium/content/ppapi_plugin/BUILD.gn b/chromium/content/ppapi_plugin/BUILD.gn
index 8b141bf3331..2482a352a8a 100644
--- a/chromium/content/ppapi_plugin/BUILD.gn
+++ b/chromium/content/ppapi_plugin/BUILD.gn
@@ -48,9 +48,15 @@ source_set("ppapi_plugin_sources") {
deps = [
"//base",
"//content:export",
+ "//content/child",
"//content/public/child:child_sources",
"//content/public/common:common_sources",
+ "//gin",
+ "//ppapi/c",
+ "//ppapi/proxy",
"//ppapi/proxy:ipc",
+ "//ppapi/shared_impl",
+ "//sandbox",
"//services/shell/public/interfaces",
"//skia",
"//third_party/WebKit/public:blink",
@@ -59,4 +65,8 @@ source_set("ppapi_plugin_sources") {
"//ui/gfx",
"//ui/gfx/geometry",
]
+
+ if (is_win) {
+ deps += [ "//ui/display" ]
+ }
}
diff --git a/chromium/content/public/android/BUILD.gn b/chromium/content/public/android/BUILD.gn
index b83e6a6602d..ed6f39d24e0 100644
--- a/chromium/content/public/android/BUILD.gn
+++ b/chromium/content/public/android/BUILD.gn
@@ -35,9 +35,12 @@ android_library("content_java") {
"//device/battery:mojo_bindings_java",
"//device/battery/android:battery_monitor_android",
"//device/bluetooth:java",
+ "//device/gamepad:java",
+ "//device/power_save_blocker:java",
"//device/usb:java",
"//device/vibration:mojo_bindings_java",
"//device/vibration/android:vibration_manager_android",
+ "//device/vr:java",
"//media/base/android:media_java",
"//media/capture/video/android:capture_java",
"//media/midi:midi_java",
@@ -64,6 +67,7 @@ android_library("content_java") {
java_files = [
"java/src/org/chromium/content/app/ChildProcessService.java",
+ "java/src/org/chromium/content/app/ChildProcessServiceImpl.java",
"java/src/org/chromium/content/app/ChromiumLinkerParams.java",
"java/src/org/chromium/content/app/ContentApplication.java",
"java/src/org/chromium/content/app/ContentMain.java",
@@ -109,14 +113,11 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/ContentView.java",
"java/src/org/chromium/content/browser/ContentViewClient.java",
"java/src/org/chromium/content/browser/ContentViewCore.java",
- "java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java",
"java/src/org/chromium/content/browser/ContentViewRenderView.java",
"java/src/org/chromium/content/browser/ContentViewStatics.java",
"java/src/org/chromium/content/browser/ContextualSearchClient.java",
"java/src/org/chromium/content/browser/DeviceSensors.java",
"java/src/org/chromium/content/browser/DeviceUtils.java",
- "java/src/org/chromium/content/browser/DownloadController.java",
- "java/src/org/chromium/content/browser/DownloadInfo.java",
"java/src/org/chromium/content/browser/FileDescriptorInfo.java",
"java/src/org/chromium/content/browser/FloatingWebActionModeCallback.java",
"java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java",
@@ -131,7 +132,6 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/PepperPluginManager.java",
"java/src/org/chromium/content/browser/PopupZoomer.java",
"java/src/org/chromium/content/browser/PositionObserver.java",
- "java/src/org/chromium/content/browser/PowerSaveBlocker.java",
"java/src/org/chromium/content/browser/RenderCoordinates.java",
"java/src/org/chromium/content/browser/SPenSupport.java",
"java/src/org/chromium/content/browser/ScreenOrientationListener.java",
@@ -159,14 +159,10 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/crypto/CipherFactory.java",
"java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java",
"java/src/org/chromium/content/browser/input/AnimationIntervalProvider.java",
- "java/src/org/chromium/content/browser/input/CardboardVRDevice.java",
"java/src/org/chromium/content/browser/input/ChromiumBaseInputConnection.java",
"java/src/org/chromium/content/browser/input/CursorAnchorInfoController.java",
"java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java",
"java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java",
- "java/src/org/chromium/content/browser/input/GamepadDevice.java",
- "java/src/org/chromium/content/browser/input/GamepadList.java",
- "java/src/org/chromium/content/browser/input/GamepadMappings.java",
"java/src/org/chromium/content/browser/input/HandleViewResources.java",
"java/src/org/chromium/content/browser/input/ImeAdapter.java",
"java/src/org/chromium/content/browser/input/ImeUtils.java",
@@ -197,6 +193,7 @@ android_library("content_java") {
"java/src/org/chromium/content_public/browser/AccessibilitySnapshotNode.java",
"java/src/org/chromium/content_public/browser/ContentBitmapCallback.java",
"java/src/org/chromium/content_public/browser/GestureStateListener.java",
+ "java/src/org/chromium/content_public/browser/ImageDownloadCallback.java",
"java/src/org/chromium/content_public/browser/JavaScriptCallback.java",
"java/src/org/chromium/content_public/browser/LoadUrlParams.java",
"java/src/org/chromium/content_public/browser/NavigationController.java",
@@ -206,12 +203,9 @@ android_library("content_java") {
"java/src/org/chromium/content_public/browser/WebContentsObserver.java",
"java/src/org/chromium/content_public/common/MediaMetadata.java",
"java/src/org/chromium/content_public/common/Referrer.java",
+ "java/src/org/chromium/content_public/common/ResourceRequestBody.java",
"java/src/org/chromium/content_public/common/ScreenOrientationConstants.java",
]
-
- if (enable_webvr) {
- deps += [ "//third_party/cardboard-java:cardboard-java" ]
- }
}
java_strings_grd("content_strings_grd") {
@@ -270,7 +264,6 @@ java_cpp_enum("content_public_android_java_enums_srcjar") {
"//content/browser/android/gesture_event_type.h",
"//content/browser/device_sensors/device_sensors_consts.h",
"//content/browser/device_sensors/sensor_manager_android.h",
- "//content/browser/gamepad/gamepad_standard_mappings.h",
"//content/public/browser/invalidate_type.h",
"//content/public/browser/navigation_controller.h",
"//content/public/browser/readback_types.h",
@@ -293,13 +286,6 @@ generate_jar_jni("jar_jni") {
generate_jni("content_jni_headers") {
sources = rebase_path(content_jni_gypi_values.sources, "", "../..")
jni_package = "content"
-
- if (enable_webvr) {
- sources += [ "//content/public/android/java/src/org/chromium/content/browser/input/CardboardVRDevice.java" ]
- public_deps = [
- "//third_party/cardboard-java:cardboard-java",
- ]
- }
}
group("jni") {
@@ -318,7 +304,6 @@ android_library("content_javatests") {
"//content/public/test/android:content_java_test_support",
"//content/shell/android:content_shell_apk_java",
"//content/shell/android:content_shell_java",
- "//content/shell/android:content_shell_java_resources",
"//content/shell/android:content_shell_test_java",
"//device/vibration:mojo_bindings_java",
"//device/vibration/android:vibration_manager_android",
@@ -351,7 +336,6 @@ android_library("content_javatests") {
"javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java",
"javatests/src/org/chromium/content/browser/ContentViewZoomingTest.java",
"javatests/src/org/chromium/content/browser/DeviceSensorsTest.java",
- "javatests/src/org/chromium/content/browser/DownloadInfoTest.java",
"javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java",
"javatests/src/org/chromium/content/browser/EncodeHtmlDataUriTest.java",
"javatests/src/org/chromium/content/browser/GestureDetectorResetTest.java",
@@ -400,7 +384,9 @@ android_library("content_javatests") {
# GYP: //content/content_tests.gypi:content_junit_tests
junit_binary("content_junit_tests") {
java_files = [
- "junit/src/org/chromium/content/browser/input/GamepadMappingsTest.java",
+ "junit/src/org/chromium/content/browser/input/RangeTest.java",
+ "junit/src/org/chromium/content/browser/input/TextInputStateTest.java",
+ "junit/src/org/chromium/content/browser/input/ThreadedInputConnectionTest.java",
"junit/src/org/chromium/content/browser/BindingManagerImplTest.java",
]
deps = [
diff --git a/chromium/content/public/app/BUILD.gn b/chromium/content/public/app/BUILD.gn
index 0854ed23295..73e5d1e901c 100644
--- a/chromium/content/public/app/BUILD.gn
+++ b/chromium/content/public/app/BUILD.gn
@@ -156,8 +156,20 @@ mojo_application_manifest("browser_manifest") {
]
}
+mojo_application_manifest("gpu_manifest") {
+ type = "exe"
+ application_name = "content_gpu"
+ source = "mojo/content_gpu_manifest.json"
+}
+
mojo_application_manifest("renderer_manifest") {
type = "exe"
application_name = "content_renderer"
source = "mojo/content_renderer_manifest.json"
}
+
+mojo_application_manifest("utility_manifest") {
+ type = "exe"
+ application_name = "content_utility"
+ source = "mojo/content_utility_manifest.json"
+}
diff --git a/chromium/content/public/app/mojo/content_browser_manifest.json b/chromium/content/public/app/mojo/content_browser_manifest.json
index 923a0ffc223..5573da52cc6 100644
--- a/chromium/content/public/app/mojo/content_browser_manifest.json
+++ b/chromium/content/public/app/mojo/content_browser_manifest.json
@@ -6,6 +6,13 @@
"capabilities": {
"required": {
"*": { "classes": [ "app" ] },
+
+ // We allow the browser to connect to any interfaces exposed by its child
+ // processes.
+ "exe:content_renderer": { "classes": [ "all_interfaces" ] },
+ "exe:content_gpu": { "classes": [ "all_interfaces" ] },
+ "exe:content_utility": { "classes": [ "all_interfaces" ] },
+
"mojo:shell": {
"classes": [
"shell:client_process",
diff --git a/chromium/content/public/app/mojo/content_gpu_manifest.json b/chromium/content/public/app/mojo/content_gpu_manifest.json
new file mode 100644
index 00000000000..6946f12206a
--- /dev/null
+++ b/chromium/content/public/app/mojo/content_gpu_manifest.json
@@ -0,0 +1,10 @@
+{
+ "manifest_version": 1,
+ "name": "exe:content_gpu",
+ "display_name": "Content Gpu",
+ "capabilities": {
+ "provided": {
+ "all_interfaces": [ "*" ]
+ }
+ }
+}
diff --git a/chromium/content/public/app/mojo/content_renderer_manifest.json b/chromium/content/public/app/mojo/content_renderer_manifest.json
index faf008ebdd9..0c45ddb6026 100644
--- a/chromium/content/public/app/mojo/content_renderer_manifest.json
+++ b/chromium/content/public/app/mojo/content_renderer_manifest.json
@@ -3,9 +3,15 @@
"name": "exe:content_renderer",
"display_name": "Content Renderer",
"capabilities": {
+ "provided": {
+ "all_interfaces": [ "*" ]
+ },
"required": {
"mojo:mus": {
- "interfaces": [ "mus::mojom::Gpu" ]
+ "interfaces": [
+ "mus::mojom::Gpu",
+ "mus::mojom::GpuService"
+ ]
}
}
}
diff --git a/chromium/content/public/app/mojo/content_utility_manifest.json b/chromium/content/public/app/mojo/content_utility_manifest.json
new file mode 100644
index 00000000000..8995bd0ced8
--- /dev/null
+++ b/chromium/content/public/app/mojo/content_utility_manifest.json
@@ -0,0 +1,10 @@
+{
+ "manifest_version": 1,
+ "name": "exe:content_utility",
+ "display_name": "Content Utility",
+ "capabilities": {
+ "provided": {
+ "all_interfaces": [ "*" ]
+ }
+ }
+}
diff --git a/chromium/content/public/browser/BUILD.gn b/chromium/content/public/browser/BUILD.gn
index 6b1faf186aa..d36c55d0c78 100644
--- a/chromium/content/public/browser/BUILD.gn
+++ b/chromium/content/public/browser/BUILD.gn
@@ -28,12 +28,14 @@ source_set("browser_sources") {
configs += [
"//build/config:precompiled_headers",
+ "//build/config/compiler:wexit_time_destructors",
"//content:content_implementation",
]
public_deps = [
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
+ "//services/shell/public/cpp",
# We expose skia headers in the public API.
"//skia",
@@ -43,6 +45,7 @@ source_set("browser_sources") {
"//cc",
"//content/browser", # Must not be public_deps!
"//content/public/common:common_sources",
+ "//device/power_save_blocker",
"//gpu",
"//media",
"//net",
diff --git a/chromium/content/public/browser/android/download_controller_android.cc b/chromium/content/public/browser/android/download_controller_android.cc
deleted file mode 100644
index fc5f82e0172..00000000000
--- a/chromium/content/public/browser/android/download_controller_android.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/browser/android/download_controller_android.h"
-
-namespace content {
-
-// static
-DownloadControllerAndroid* DownloadControllerAndroid::download_controller_ =
- nullptr;
-
-} // namespace content
diff --git a/chromium/content/public/browser/android/download_controller_android.h b/chromium/content/public/browser/android/download_controller_android.h
index 59b7e1c5716..cbd829b4639 100644
--- a/chromium/content/public/browser/android/download_controller_android.h
+++ b/chromium/content/public/browser/android/download_controller_android.h
@@ -34,7 +34,6 @@ class CONTENT_EXPORT DownloadControllerAndroid : public DownloadItem::Observer {
CANCEL_REASON_NOTIFICATION_DISMISSED,
CANCEL_REASON_OVERWRITE_INFOBAR_DISMISSED,
CANCEL_REASON_NO_STORAGE_PERMISSION,
- CANCEL_REASON_DANGEROUS_DOWNLOAD_INFOBAR_DISMISSED,
CANCEL_REASON_MAX
};
static void RecordDownloadCancelReason(DownloadCancelReason reason);
diff --git a/chromium/content/public/browser/android/service_registry_android.h b/chromium/content/public/browser/android/service_registry_android.h
index e134b431ab7..7cb3270472d 100644
--- a/chromium/content/public/browser/android/service_registry_android.h
+++ b/chromium/content/public/browser/android/service_registry_android.h
@@ -11,9 +11,12 @@
#include "base/android/scoped_java_ref.h"
#include "content/common/content_export.h"
-namespace content {
+namespace shell {
+class InterfaceRegistry;
+class InterfaceProvider;
+}
-class ServiceRegistry;
+namespace content {
// Android wrapper over ServiceRegistry, allowing the browser services in Java
// to register with ServiceRegistry.java (and abstracting away the JNI calls).
@@ -23,7 +26,8 @@ class CONTENT_EXPORT ServiceRegistryAndroid {
// The |registry| parameter must outlive |ServiceRegistryAndroid|.
static std::unique_ptr<ServiceRegistryAndroid> Create(
- ServiceRegistry* registry);
+ shell::InterfaceRegistry* interface_registry,
+ shell::InterfaceProvider* remote_interfaces);
// Called from Java.
virtual void AddService(
diff --git a/chromium/content/public/browser/android/synchronous_compositor.h b/chromium/content/public/browser/android/synchronous_compositor.h
index 82b50b7968e..bc74f1f240f 100644
--- a/chromium/content/public/browser/android/synchronous_compositor.h
+++ b/chromium/content/public/browser/android/synchronous_compositor.h
@@ -90,11 +90,6 @@ class CONTENT_EXPORT SynchronousCompositor {
virtual void SynchronouslyZoomBy(float zoom_delta,
const gfx::Point& anchor) = 0;
- // Called by the embedder to notify that the compositor is active. The
- // compositor won't ask for vsyncs when it's inactive. NOTE: The compositor
- // starts off as inactive and needs a SetActive(true) call to begin.
- virtual void SetIsActive(bool is_active) = 0;
-
// Called by the embedder to notify that the OnComputeScroll step is happening
// and if any input animation is active, it should tick now.
virtual void OnComputeScroll(base::TimeTicks animation_time) = 0;
diff --git a/chromium/content/public/browser/android/synchronous_compositor_client.h b/chromium/content/public/browser/android/synchronous_compositor_client.h
index 0fbd2a782e5..fa28023348f 100644
--- a/chromium/content/public/browser/android/synchronous_compositor_client.h
+++ b/chromium/content/public/browser/android/synchronous_compositor_client.h
@@ -18,35 +18,37 @@ class SynchronousCompositor;
class SynchronousCompositorClient {
public:
// Indication to the client that |compositor| is now initialized on the
- // compositor thread, and open for business.
- virtual void DidInitializeCompositor(SynchronousCompositor* compositor) = 0;
+ // compositor thread, and open for business. |process_id| and |routing_id|
+ // belong to the RVH that owns the compositor.
+ virtual void DidInitializeCompositor(SynchronousCompositor* compositor,
+ int process_id,
+ int routing_id) = 0;
// Indication to the client that |compositor| is going out of scope, and
// must not be accessed within or after this call.
// NOTE if the client goes away before the compositor it must call
// SynchronousCompositor::SetClient(nullptr) to release the back pointer.
- virtual void DidDestroyCompositor(SynchronousCompositor* compositor) = 0;
-
- // Indication to the client that |compositor| just became the current one.
- // The compositor has to be initialized first. An initialized compositor may
- // not become current immediately.
- virtual void DidBecomeCurrent(SynchronousCompositor* compositor) = 0;
+ virtual void DidDestroyCompositor(SynchronousCompositor* compositor,
+ int process_id,
+ int routing_id) = 0;
// See LayerScrollOffsetDelegate for details.
- virtual void UpdateRootLayerState(const gfx::Vector2dF& total_scroll_offset,
+ virtual void UpdateRootLayerState(SynchronousCompositor* compositor,
+ const gfx::Vector2dF& total_scroll_offset,
const gfx::Vector2dF& max_scroll_offset,
const gfx::SizeF& scrollable_size,
float page_scale_factor,
float min_page_scale_factor,
float max_page_scale_factor) = 0;
- virtual void DidOverscroll(const gfx::Vector2dF& accumulated_overscroll,
+ virtual void DidOverscroll(SynchronousCompositor* compositor,
+ const gfx::Vector2dF& accumulated_overscroll,
const gfx::Vector2dF& latest_overscroll_delta,
const gfx::Vector2dF& current_fling_velocity) = 0;
- virtual void PostInvalidate() = 0;
+ virtual void PostInvalidate(SynchronousCompositor* compositor) = 0;
- virtual void DidUpdateContent() = 0;
+ virtual void DidUpdateContent(SynchronousCompositor* compositor) = 0;
protected:
SynchronousCompositorClient() {}
diff --git a/chromium/content/public/browser/browser_child_process_host.h b/chromium/content/public/browser/browser_child_process_host.h
index 07193afd0cd..2b82b5b4d8c 100644
--- a/chromium/content/public/browser/browser_child_process_host.h
+++ b/chromium/content/public/browser/browser_child_process_host.h
@@ -23,12 +23,16 @@ class CommandLine;
class FilePath;
}
+namespace shell {
+class InterfaceProvider;
+class InterfaceRegistry;
+}
+
namespace content {
class BrowserChildProcessHostDelegate;
class ChildProcessHost;
class SandboxedProcessLauncherDelegate;
-class ServiceRegistry;
struct ChildProcessData;
// This represents child processes of the browser process, i.e. plugins. They
@@ -42,6 +46,14 @@ class CONTENT_EXPORT BrowserChildProcessHost : public IPC::Sender {
content::ProcessType process_type,
BrowserChildProcessHostDelegate* delegate);
+ // Used to create a child process host, with a unique token to identify the
+ // child process to Mojo. |mojo_child_token| should be a unique string
+ // generated using mojo::edk::GenerateRandomToken().
+ static BrowserChildProcessHost* Create(
+ content::ProcessType process_type,
+ BrowserChildProcessHostDelegate* delegate,
+ const std::string& mojo_child_token);
+
// Returns the child process host with unique id |child_process_id|, or
// nullptr if it doesn't exist. |child_process_id| is NOT the process ID, but
// is the same unique ID as |ChildProcessData::id|.
@@ -81,9 +93,13 @@ class CONTENT_EXPORT BrowserChildProcessHost : public IPC::Sender {
// this object.
virtual void SetHandle(base::ProcessHandle handle) = 0;
- // Get the Mojo service registry connected to the child process. Returns
- // nullptr if no service registry exists.
- virtual ServiceRegistry* GetServiceRegistry() = 0;
+ // Returns the shell::InterfaceRegistry the browser process uses to expose
+ // interfaces to the child.
+ virtual shell::InterfaceRegistry* GetInterfaceRegistry() = 0;
+
+ // Returns the shell::InterfaceProvider the browser process can use to bind
+ // interfaces exposed to it from the child.
+ virtual shell::InterfaceProvider* GetRemoteInterfaces() = 0;
#if defined(OS_MACOSX)
// Returns a PortProvider used to get the task port for child processes.
diff --git a/chromium/content/public/browser/browser_child_process_host_delegate.cc b/chromium/content/public/browser/browser_child_process_host_delegate.cc
index 46d822dbbbb..50cd88a8aee 100644
--- a/chromium/content/public/browser/browser_child_process_host_delegate.cc
+++ b/chromium/content/public/browser/browser_child_process_host_delegate.cc
@@ -10,7 +10,13 @@ bool BrowserChildProcessHostDelegate::CanShutdown() {
return true;
}
-ServiceRegistry* BrowserChildProcessHostDelegate::GetServiceRegistry() {
+shell::InterfaceRegistry*
+BrowserChildProcessHostDelegate::GetInterfaceRegistry() {
+ return nullptr;
+}
+
+shell::InterfaceProvider*
+BrowserChildProcessHostDelegate::GetRemoteInterfaces() {
return nullptr;
}
diff --git a/chromium/content/public/browser/browser_child_process_host_delegate.h b/chromium/content/public/browser/browser_child_process_host_delegate.h
index 892ca25c9f9..3958bd3336b 100644
--- a/chromium/content/public/browser/browser_child_process_host_delegate.h
+++ b/chromium/content/public/browser/browser_child_process_host_delegate.h
@@ -8,9 +8,12 @@
#include "content/common/content_export.h"
#include "ipc/ipc_listener.h"
-namespace content {
+namespace shell {
+class InterfaceProvider;
+class InterfaceRegistry;
+}
-class ServiceRegistry;
+namespace content {
// Interface that all users of BrowserChildProcessHost need to provide.
class CONTENT_EXPORT BrowserChildProcessHostDelegate : public IPC::Listener {
@@ -35,8 +38,13 @@ class CONTENT_EXPORT BrowserChildProcessHostDelegate : public IPC::Listener {
// returned from GetExitCodeProcess()).
virtual void OnProcessCrashed(int exit_code) {}
- // Returns the ServiceRegistry for this child process.
- virtual ServiceRegistry* GetServiceRegistry();
+ // Returns the shell::InterfaceRegistry the browser process uses to expose
+ // interfaces to the child.
+ virtual shell::InterfaceRegistry* GetInterfaceRegistry();
+
+ // Returns the shell::InterfaceProvider the browser process can use to bind
+ // interfaces exposed to it from the child.
+ virtual shell::InterfaceProvider* GetRemoteInterfaces();
};
}; // namespace content
diff --git a/chromium/content/public/browser/browser_context.h b/chromium/content/public/browser/browser_context.h
index 55208d4b2da..05f80861400 100644
--- a/chromium/content/public/browser/browser_context.h
+++ b/chromium/content/public/browser/browser_context.h
@@ -151,14 +151,21 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
static void Initialize(BrowserContext* browser_context,
const base::FilePath& path);
- // Returns a Mojo User ID associated with this BrowserContext. This ID is not
+ // Returns a Shell User ID associated with this BrowserContext. This ID is not
// persistent across runs. See
- // services/shell/public/interfaces/connector.mojom.
- static const std::string& GetMojoUserIdFor(BrowserContext* browser_context);
+ // services/shell/public/interfaces/connector.mojom. By default, this user id
+ // is randomly generated when Initialize() is called.
+ static const std::string& GetShellUserIdFor(BrowserContext* browser_context);
+
+ // Returns the BrowserContext associated with |user_id|, or nullptr if no
+ // BrowserContext exists for that |user_id|.
+ static BrowserContext* GetBrowserContextForShellUserId(
+ const std::string& user_id);
// Returns a Connector associated with this BrowserContext, which can be used
- // to connect to Mojo application instances bound to a specific user.
- static shell::Connector* GetMojoConnectorFor(BrowserContext* browser_context);
+ // to connect to service instances bound as this user.
+ static shell::Connector* GetShellConnectorFor(
+ BrowserContext* browser_context);
~BrowserContext() override;
diff --git a/chromium/content/public/browser/browser_thread.h b/chromium/content/public/browser/browser_thread.h
index 90b955f452e..2fbc53e64db 100644
--- a/chromium/content/public/browser/browser_thread.h
+++ b/chromium/content/public/browser/browser_thread.h
@@ -188,6 +188,8 @@ class CONTENT_EXPORT BrowserThread {
// The order or execution of tasks posted here is unspecified even when
// posting to a SequencedTaskRunner and tasks are not guaranteed to be run
// prior to browser shutdown.
+ // When called after the browser startup is complete, will post |task|
+ // to |task_runner| immediately.
// Note: see related ContentBrowserClient::PostAfterStartupTask.
static void PostAfterStartupTask(
const tracked_objects::Location& from_here,
diff --git a/chromium/content/public/browser/content_browser_client.cc b/chromium/content/public/browser/content_browser_client.cc
index d8c321bcf31..153ad54607a 100644
--- a/chromium/content/public/browser/content_browser_client.cc
+++ b/chromium/content/public/browser/content_browser_client.cc
@@ -5,8 +5,11 @@
#include "content/public/browser/content_browser_client.h"
#include "base/files/file_path.h"
+#include "base/guid.h"
#include "build/build_config.h"
#include "content/public/browser/client_certificate_delegate.h"
+#include "content/public/browser/geolocation_delegate.h"
+#include "content/public/browser/vpn_service_proxy.h"
#include "content/public/common/sandbox_type.h"
#include "media/base/cdm_factory.h"
#include "storage/browser/quota/quota_manager.h"
@@ -305,7 +308,8 @@ net::NetLog* ContentBrowserClient::GetNetLog() {
return nullptr;
}
-AccessTokenStore* ContentBrowserClient::CreateAccessTokenStore() {
+GeolocationDelegate* ContentBrowserClient::CreateGeolocationDelegate() {
+ // We don't need to override anything, the default implementation is good.
return nullptr;
}
@@ -344,12 +348,13 @@ bool ContentBrowserClient::IsPepperVpnProviderAPIAllowed(
return false;
}
-ui::SelectFilePolicy* ContentBrowserClient::CreateSelectFilePolicy(
- WebContents* web_contents) {
+std::unique_ptr<VpnServiceProxy> ContentBrowserClient::GetVpnServiceProxy(
+ BrowserContext* browser_context) {
return nullptr;
}
-LocationProvider* ContentBrowserClient::OverrideSystemLocationProvider() {
+ui::SelectFilePolicy* ContentBrowserClient::CreateSelectFilePolicy(
+ WebContents* web_contents) {
return nullptr;
}
@@ -373,6 +378,11 @@ bool ContentBrowserClient::IsPluginAllowedToUseDevChannelAPIs(
return false;
}
+std::string ContentBrowserClient::GetShellUserIdForBrowserContext(
+ BrowserContext* browser_context) {
+ return base::GenerateGUID();
+}
+
PresentationServiceDelegate*
ContentBrowserClient::GetPresentationServiceDelegate(
WebContents* web_contents) {
@@ -417,10 +427,6 @@ bool ContentBrowserClient::IsWin32kLockdownEnabledForMimeType(
// is enabled by default in Chrome. See crbug.com/523278.
return false;
}
-
-bool ContentBrowserClient::ShouldUseWindowsPrefetchArgument() const {
- return true;
-}
#endif // defined(OS_WIN)
#if defined(VIDEO_HOLE)
diff --git a/chromium/content/public/browser/content_browser_client.h b/chromium/content/public/browser/content_browser_client.h
index 7fbfa6d0061..636147cc97e 100644
--- a/chromium/content/public/browser/content_browser_client.h
+++ b/chromium/content/public/browser/content_browser_client.h
@@ -61,6 +61,7 @@ class CdmFactory;
}
namespace shell {
+class InterfaceRegistry;
class ShellClient;
}
@@ -106,6 +107,7 @@ class BrowserURLHandler;
class ClientCertificateDelegate;
class DevToolsManagerDelegate;
class ExternalVideoSurfaceContainer;
+class GeolocationDelegate;
class LocationProvider;
class MediaObserver;
class NavigationHandle;
@@ -116,10 +118,10 @@ class RenderFrameHost;
class RenderProcessHost;
class RenderViewHost;
class ResourceContext;
-class ServiceRegistry;
class SiteInstance;
class SpeechRecognitionManagerDelegate;
class TracingDelegate;
+class VpnServiceProxy;
class WebContents;
class WebContentsViewDelegate;
struct MainFunctionParams;
@@ -214,11 +216,6 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual void GetAdditionalWebUISchemes(
std::vector<std::string>* additional_schemes) {}
- // Returns a list of webUI hosts to ignore the storage partition check in
- // URLRequestChromeJob::CheckStoragePartitionMatches.
- virtual void GetAdditionalWebUIHostsToIgnoreParititionCheck(
- std::vector<std::string>* hosts) {}
-
// Called when WebUI objects are created to get aggregate usage data (i.e. is
// chrome://downloads used more than chrome://bookmarks?). Only internal (e.g.
// chrome://) URLs are logged. Returns whether the URL was actually logged.
@@ -247,6 +244,10 @@ class CONTENT_EXPORT ContentBrowserClient {
// This also applies in cases where the new URL will open in another process.
virtual bool ShouldAllowOpenURL(SiteInstance* site_instance, const GURL& url);
+ // Allows the embedder to override OpenURLParams.
+ virtual void OverrideOpenURLParams(SiteInstance* site_instance,
+ OpenURLParams* params) {}
+
// Returns whether a new view for a given |site_url| can be launched in a
// given |process_host|.
virtual bool IsSuitableHost(RenderProcessHost* process_host,
@@ -534,8 +535,9 @@ class CONTENT_EXPORT ContentBrowserClient {
// Getters for common objects.
virtual net::NetLog* GetNetLog();
- // Creates a new AccessTokenStore for gelocation.
- virtual AccessTokenStore* CreateAccessTokenStore();
+ // Allows the embedder to provide a Delegate for Geolocation to override some
+ // functionality of the API (e.g. AccessTokenStore, LocationProvider).
+ virtual GeolocationDelegate* CreateGeolocationDelegate();
// Returns true if fast shutdown is possible.
virtual bool IsFastShutdownPossible();
@@ -592,6 +594,11 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual bool IsPepperVpnProviderAPIAllowed(BrowserContext* browser_context,
const GURL& url);
+ // Creates a new VpnServiceProxy. The caller owns the returned value. It's
+ // valid to return nullptr.
+ virtual std::unique_ptr<VpnServiceProxy> GetVpnServiceProxy(
+ BrowserContext* browser_context);
+
// Returns an implementation of a file selecition policy. Can return nullptr.
virtual ui::SelectFilePolicy* CreateSelectFilePolicy(
WebContents* web_contents);
@@ -620,13 +627,6 @@ class CONTENT_EXPORT ContentBrowserClient {
const base::FilePath& storage_partition_path,
ScopedVector<storage::FileSystemBackend>* additional_backends) {}
- // Allows an embedder to return its own LocationProvider implementation.
- // Return nullptr to use the default one for the platform to be created.
- // FYI: Used by an external project; please don't remove.
- // Contact Viatcheslav Ostapenko at sl.ostapenko@samsung.com for more
- // information.
- virtual LocationProvider* OverrideSystemLocationProvider();
-
// Creates a new DevToolsManagerDelegate. The caller owns the returned value.
// It's valid to return nullptr.
virtual DevToolsManagerDelegate* GetDevToolsManagerDelegate();
@@ -646,23 +646,27 @@ class CONTENT_EXPORT ContentBrowserClient {
BrowserContext* browser_context,
const GURL& url);
- // Allows the embedder to register MojoShellConnection::Listeners.
- virtual void AddMojoShellConnectionListeners() {}
+ // Generate a Shell user-id for the supplied browser context. Defaults to
+ // returning a random GUID.
+ virtual std::string GetShellUserIdForBrowserContext(
+ BrowserContext* browser_context);
- // Allows to register browser Mojo services exposed through the
+ // Allows to register browser Mojo interfaces exposed through the
// RenderProcessHost.
- virtual void RegisterRenderProcessMojoServices(ServiceRegistry* registry) {}
+ virtual void ExposeInterfacesToRenderer(
+ shell::InterfaceRegistry* registry,
+ RenderProcessHost* render_process_host) {}
- // Allows to register browser Mojo services exposed through the
+ // Allows to register browser Mojo interfaces exposed through the
// FrameMojoShell.
- virtual void RegisterFrameMojoShellServices(
- ServiceRegistry* registry,
+ virtual void RegisterFrameMojoShellInterfaces(
+ shell::InterfaceRegistry* registry,
RenderFrameHost* render_frame_host) {}
- // Allows to register browser Mojo services exposed through the
+ // Allows to register browser Mojo interfaces exposed through the
// RenderFrameHost.
- virtual void RegisterRenderFrameMojoServices(
- ServiceRegistry* registry,
+ virtual void RegisterRenderFrameMojoInterfaces(
+ shell::InterfaceRegistry* registry,
RenderFrameHost* render_frame_host) {}
using StaticMojoApplicationMap = std::map<std::string, MojoApplicationInfo>;
@@ -773,10 +777,6 @@ class CONTENT_EXPORT ContentBrowserClient {
// a process hosting a plugin with the specified |mime_type|.
virtual bool IsWin32kLockdownEnabledForMimeType(
const std::string& mime_type) const;
-
- // Returns true if processes should be launched with a /prefetch:# argument.
- // See the kPrefetchArgument* constants in content_switches.cc for details.
- virtual bool ShouldUseWindowsPrefetchArgument() const;
#endif
#if defined(VIDEO_HOLE)
diff --git a/chromium/content/public/browser/devtools_agent_host.h b/chromium/content/public/browser/devtools_agent_host.h
index 62b5a6e7ae2..f5ef494282c 100644
--- a/chromium/content/public/browser/devtools_agent_host.h
+++ b/chromium/content/public/browser/devtools_agent_host.h
@@ -108,17 +108,25 @@ class CONTENT_EXPORT DevToolsAgentHost
// Returns all possible DevToolsAgentHosts.
static List GetOrCreateAll();
- // Client attaches to this agent host to start debugging it.
- virtual void AttachClient(DevToolsAgentHostClient* client) = 0;
+ // Attaches |client| to this agent host to start debugging.
+ // Returns true iff attach succeeded.
+ virtual bool AttachClient(DevToolsAgentHostClient* client) = 0;
+
+ // Attaches |client| to this agent host to start debugging. Disconnects
+ // any existing clients.
+ virtual void ForceAttachClient(DevToolsAgentHostClient* client) = 0;
// Already attached client detaches from this agent host to stop debugging it.
- virtual void DetachClient() = 0;
+ // Returns true iff detach succeeded.
+ virtual bool DetachClient(DevToolsAgentHostClient* client) = 0;
// Returns true if there is a client attached.
virtual bool IsAttached() = 0;
- // Sends a message to the agent. Returns true if the message is handled.
- virtual bool DispatchProtocolMessage(const std::string& message) = 0;
+ // Sends |message| from |client| to the agent.
+ // Returns true if the message is dispatched and handled.
+ virtual bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
+ const std::string& message) = 0;
// Starts inspecting element at position (|x|, |y|) in the specified page.
virtual void InspectElement(int x, int y) = 0;
@@ -132,7 +140,7 @@ class CONTENT_EXPORT DevToolsAgentHost
// Returns related browser context instance if available.
virtual BrowserContext* GetBrowserContext() = 0;
- // Temporarily detaches render view host from this host. Must be followed by
+ // Temporarily detaches WebContents from this host. Must be followed by
// a call to ConnectWebContents (may leak the host instance otherwise).
virtual void DisconnectWebContents() = 0;
diff --git a/chromium/content/public/browser/download_manager_delegate.h b/chromium/content/public/browser/download_manager_delegate.h
index 13b395721c7..6acb96026e5 100644
--- a/chromium/content/public/browser/download_manager_delegate.h
+++ b/chromium/content/public/browser/download_manager_delegate.h
@@ -119,6 +119,18 @@ class CONTENT_EXPORT DownloadManagerDelegate {
const SavePackagePathPickedCallback& callback) {
}
+ // Sanitize a filename that's going to be used for saving a subresource of a
+ // SavePackage.
+ //
+ // If the delegate does nothing, the default filename already populated in
+ // |filename| will be used. Otherwise, the delegate can update |filename| to
+ // the desired filename.
+ //
+ // |filename| contains a basename with an extension, but without a path. This
+ // should be the case on return as well. I.e. |filename| cannot specify a
+ // relative path.
+ virtual void SanitizeSavePackageResourceName(base::FilePath* filename) {}
+
// Opens the file associated with this download.
virtual void OpenDownload(DownloadItem* download) {}
diff --git a/chromium/content/public/browser/download_url_parameters.cc b/chromium/content/public/browser/download_url_parameters.cc
index ed497a3e445..e38c34ebdb8 100644
--- a/chromium/content/public/browser/download_url_parameters.cc
+++ b/chromium/content/public/browser/download_url_parameters.cc
@@ -18,6 +18,12 @@ namespace content {
DownloadUrlParameters::DownloadUrlParameters(
const GURL& url,
+ net::URLRequestContextGetter* url_request_context_getter)
+ : DownloadUrlParameters(url, -1, -1, -1, url_request_context_getter) {
+}
+
+DownloadUrlParameters::DownloadUrlParameters(
+ const GURL& url,
int render_process_host_id,
int render_view_host_routing_id,
int render_frame_host_routing_id,
@@ -37,7 +43,8 @@ DownloadUrlParameters::~DownloadUrlParameters() {
}
// static
-std::unique_ptr<DownloadUrlParameters> DownloadUrlParameters::FromWebContents(
+std::unique_ptr<DownloadUrlParameters>
+DownloadUrlParameters::CreateForWebContentsMainFrame(
WebContents* web_contents,
const GURL& url) {
RenderFrameHost* render_frame_host = web_contents->GetMainFrame();
@@ -45,7 +52,7 @@ std::unique_ptr<DownloadUrlParameters> DownloadUrlParameters::FromWebContents(
web_contents->GetBrowserContext(), render_frame_host->GetSiteInstance());
return std::unique_ptr<DownloadUrlParameters>(new DownloadUrlParameters(
url, render_frame_host->GetProcess()->GetID(),
- web_contents->GetRenderViewHost()->GetRoutingID(),
+ render_frame_host->GetRenderViewHost()->GetRoutingID(),
render_frame_host->GetRoutingID(),
storage_partition->GetURLRequestContext()));
}
diff --git a/chromium/content/public/browser/download_url_parameters.h b/chromium/content/public/browser/download_url_parameters.h
index 7a580a3f9c7..b07f89a1445 100644
--- a/chromium/content/public/browser/download_url_parameters.h
+++ b/chromium/content/public/browser/download_url_parameters.h
@@ -61,31 +61,28 @@ class CONTENT_EXPORT DownloadUrlParameters {
typedef std::vector<RequestHeadersNameValuePair> RequestHeadersType;
// Construct DownloadUrlParameters for downloading the resource at |url| and
- // associating the download with |web_contents|.
- //
- // DEPRECATED: Using this method can cause the request to be associated with
- // the wrong site instance where multiple iframes are involved. Use the
- // DownloadUrlParameters constructor below and specify the process and frame
- // IDs explicitly.
- static std::unique_ptr<DownloadUrlParameters> FromWebContents(
+ // associating the download with the main frame of the given WebContents.
+ static std::unique_ptr<DownloadUrlParameters> CreateForWebContentsMainFrame(
WebContents* web_contents,
const GURL& url);
- // Construct DownloadUrlParameters for downloading the resource at |url| and
- // associating the download with the WebContents identified by
- // |render_process_host_id| and |render_view_host_routing_id|.
- //
- // If the download is not associated with a WebContents, then set the IDs to
- // -1.
+ // Constructs a download not associated with a frame.
//
- // NOTE: Initiating downloads that are not associated with a WebContents is
- // not safe and should only be done in a limited set of cases where the
- // download URL has been previously vetted. A download that's initiated
- // without associating it with a WebContents don't receive the same security
- // checks as a request that's associated with one. Hence, downloads that are
- // not associated with a WebContents should only be made for URLs that are
- // either trusted or URLs that have previously been successfully issued using
- // a non-privileged WebContents.
+ // It is not safe to have downloads not associated with a frame and
+ // this should only be done in a limited set of cases where the download URL
+ // has been previously vetted. A download that's initiated without
+ // associating it with a frame don't receive the same security checks
+ // as a request that's associated with one. Hence, downloads that are not
+ // associated with a frame should only be made for URLs that are either
+ // trusted or URLs that have previously been successfully issued using a
+ // non-privileged frame.
+ DownloadUrlParameters(
+ const GURL& url,
+ net::URLRequestContextGetter* url_request_context_getter);
+
+ // The RenderView routing ID must correspond to the RenderView of the
+ // RenderFrame, both of which share the same RenderProcess. This may be a
+ // different RenderView than the WebContents' main RenderView.
DownloadUrlParameters(
const GURL& url,
int render_process_host_id,
@@ -214,6 +211,9 @@ class CONTENT_EXPORT DownloadUrlParameters {
bool prefer_cache() const { return prefer_cache_; }
const Referrer& referrer() const { return referrer_; }
const std::string& referrer_encoding() const { return referrer_encoding_; }
+
+ // These will be -1 if the request is not associated with a frame. See
+ // the constructors for more.
int render_process_host_id() const { return render_process_host_id_; }
int render_view_host_routing_id() const {
return render_view_host_routing_id_;
@@ -221,6 +221,7 @@ class CONTENT_EXPORT DownloadUrlParameters {
int render_frame_host_routing_id() const {
return render_frame_host_routing_id_;
}
+
const RequestHeadersType& request_headers() const { return request_headers_; }
net::URLRequestContextGetter* url_request_context_getter() {
return url_request_context_getter_.get();
diff --git a/chromium/content/public/browser/geolocation_delegate.cc b/chromium/content/public/browser/geolocation_delegate.cc
new file mode 100644
index 00000000000..8975fed4025
--- /dev/null
+++ b/chromium/content/public/browser/geolocation_delegate.cc
@@ -0,0 +1,21 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/geolocation_delegate.h"
+
+namespace content {
+
+bool GeolocationDelegate::UseNetworkLocationProviders() {
+ return true;
+}
+
+AccessTokenStore* GeolocationDelegate::CreateAccessTokenStore() {
+ return nullptr;
+}
+
+LocationProvider* GeolocationDelegate::OverrideSystemLocationProvider() {
+ return nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/geolocation_delegate.h b/chromium/content/public/browser/geolocation_delegate.h
new file mode 100644
index 00000000000..2dc6047d120
--- /dev/null
+++ b/chromium/content/public/browser/geolocation_delegate.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_PUBLIC_BROWSER_GEOLOCATION_DELEGATE_H_
+#define CONTENT_PUBLIC_BROWSER_GEOLOCATION_DELEGATE_H_
+
+#include <memory>
+
+#include "content/common/content_export.h"
+
+namespace content {
+class AccessTokenStore;
+class LocationProvider;
+
+// An embedder of Geolocation may override these class' methods to provide
+// specific functionality.
+class CONTENT_EXPORT GeolocationDelegate {
+ public:
+ // Returns true if the location API should use network-based location
+ // approximation in addition to the system provider, if any.
+ virtual bool UseNetworkLocationProviders();
+ // Creates a new AccessTokenStore for geolocation. May return nullptr.
+ // TODO(mcasas): consider changing it return type to std::unique_ptr<> to
+ // clarify ownership, https://crbug.com/623114.
+ virtual AccessTokenStore* CreateAccessTokenStore();
+ // Allows an embedder to return its own LocationProvider implementation.
+ // Return nullptr to use the default one for the platform to be created.
+ // Caller takes ownership of the returned LocationProvider. FYI: Used by an
+ // external project; please don't remove. Contact Viatcheslav Ostapenko at
+ // sl.ostapenko@samsung.com for more information.
+ // TODO(mcasas): return std::unique_ptr<> instead, https://crbug.com/623132.
+ virtual LocationProvider* OverrideSystemLocationProvider();
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_GEOLOCATION_DELEGATE_H_
diff --git a/chromium/content/public/browser/gpu_service_registry.cc b/chromium/content/public/browser/gpu_service_registry.cc
index e6a2ba740d2..3747d90468c 100644
--- a/chromium/content/public/browser/gpu_service_registry.cc
+++ b/chromium/content/public/browser/gpu_service_registry.cc
@@ -8,11 +8,11 @@
namespace content {
-ServiceRegistry* GetGpuServiceRegistry() {
+shell::InterfaceProvider* GetGpuRemoteInterfaces() {
GpuProcessHost* host =
GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
CAUSE_FOR_GPU_LAUNCH_GET_GPU_SERVICE_REGISTRY);
- return host->GetServiceRegistry();
+ return host->GetRemoteInterfaces();
}
} // namespace content
diff --git a/chromium/content/public/browser/gpu_service_registry.h b/chromium/content/public/browser/gpu_service_registry.h
index 0e025ee986f..6f041807ea4 100644
--- a/chromium/content/public/browser/gpu_service_registry.h
+++ b/chromium/content/public/browser/gpu_service_registry.h
@@ -2,18 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_PUBLIC_BROWSER_GPU_SERVICE_REGISTRY_H_
-#define CONTENT_PUBLIC_BROWSER_GPU_SERVICE_REGISTRY_H_
+#ifndef CONTENT_PUBLIC_BROWSER_GPU_INTERFACE_REGISTRY_H_
+#define CONTENT_PUBLIC_BROWSER_GPU_INTERFACE_REGISTRY_H_
#include "content/common/content_export.h"
+namespace shell {
+class InterfaceProvider;
+}
+
namespace content {
-class ServiceRegistry;
-// Get ServiceRegistry registered via ContentGpuClient::RegisterMojoServices().
+// Get shell::InterfaceProvider that can be used to bind interfaces registered
+// via ContentGpuClient::ExposeInterfacesToBrowser().
// This must be called on IO thread.
-CONTENT_EXPORT ServiceRegistry* GetGpuServiceRegistry();
+CONTENT_EXPORT shell::InterfaceProvider* GetGpuRemoteInterfaces();
} // namespace content
-#endif // CONTENT_PUBLIC_BROWSER_GPU_SERVICE_REGISTRY_H_
+#endif // CONTENT_PUBLIC_BROWSER_GPU_INTERFACE_REGISTRY_H_
diff --git a/chromium/content/public/browser/gpu_utils.cc b/chromium/content/public/browser/gpu_utils.cc
index 40ac854fd6b..69acbbff2bc 100644
--- a/chromium/content/public/browser/gpu_utils.cc
+++ b/chromium/content/public/browser/gpu_utils.cc
@@ -52,6 +52,8 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
command_line->HasSwitch(switches::kEnableAcceleratedVpxDecode);
gpu_preferences.enable_zero_copy_dxgi_video =
command_line->HasSwitch(switches::kEnableZeroCopyDxgiVideo);
+ gpu_preferences.enable_nv12_dxgi_video =
+ !command_line->HasSwitch(switches::kDisableNv12DxgiVideo);
#endif
gpu_preferences.compile_shader_always_succeeds =
command_line->HasSwitch(switches::kCompileShaderAlwaysSucceeds);
@@ -97,6 +99,8 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
command_line->HasSwitch(switches::kEnableGPUServiceTracing);
gpu_preferences.enable_unsafe_es3_apis =
command_line->HasSwitch(switches::kEnableUnsafeES3APIs);
+ gpu_preferences.use_passthrough_cmd_decoder =
+ command_line->HasSwitch(switches::kUsePassthroughCmdDecoder);
return gpu_preferences;
}
diff --git a/chromium/content/public/browser/media_device_id.cc b/chromium/content/public/browser/media_device_id.cc
index d99d0f240c9..97faa1e1a40 100644
--- a/chromium/content/public/browser/media_device_id.cc
+++ b/chromium/content/public/browser/media_device_id.cc
@@ -8,23 +8,23 @@
namespace content {
-std::string GetHMACForMediaDeviceID(const ResourceContext::SaltCallback& sc,
+std::string GetHMACForMediaDeviceID(const std::string& salt,
const url::Origin& security_origin,
const std::string& raw_unique_id) {
- return MediaStreamManager::GetHMACForMediaDeviceID(sc, security_origin,
+ return MediaStreamManager::GetHMACForMediaDeviceID(salt, security_origin,
raw_unique_id);
}
-bool DoesMediaDeviceIDMatchHMAC(const ResourceContext::SaltCallback& sc,
+bool DoesMediaDeviceIDMatchHMAC(const std::string& salt,
const url::Origin& security_origin,
const std::string& device_guid,
const std::string& raw_unique_id) {
return MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
- sc, security_origin, device_guid, raw_unique_id);
+ salt, security_origin, device_guid, raw_unique_id);
}
bool GetMediaDeviceIDForHMAC(MediaStreamType stream_type,
- const ResourceContext::SaltCallback& rc,
+ const std::string& salt,
const url::Origin& security_origin,
const std::string& source_id,
std::string* device_id) {
@@ -32,10 +32,7 @@ bool GetMediaDeviceIDForHMAC(MediaStreamType stream_type,
content::BrowserMainLoop::GetInstance()->media_stream_manager();
return manager->TranslateSourceIdToDeviceId(
- content::MEDIA_DEVICE_VIDEO_CAPTURE,
- rc,
- security_origin,
- source_id,
+ content::MEDIA_DEVICE_VIDEO_CAPTURE, salt, security_origin, source_id,
device_id);
}
diff --git a/chromium/content/public/browser/media_device_id.h b/chromium/content/public/browser/media_device_id.h
index 579d995f5b4..a08320ca272 100644
--- a/chromium/content/public/browser/media_device_id.h
+++ b/chromium/content/public/browser/media_device_id.h
@@ -22,24 +22,23 @@ namespace content {
// Generates a one-way hash of a device's unique ID usable by one
// particular security origin.
CONTENT_EXPORT std::string GetHMACForMediaDeviceID(
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
const url::Origin& security_origin,
const std::string& raw_unique_id);
// Convenience method to check if |device_guid| is an HMAC of
// |raw_device_id| for |security_origin|.
CONTENT_EXPORT bool DoesMediaDeviceIDMatchHMAC(
- const ResourceContext::SaltCallback& sc,
+ const std::string& salt,
const url::Origin& security_origin,
const std::string& device_guid,
const std::string& raw_unique_id);
-CONTENT_EXPORT bool GetMediaDeviceIDForHMAC(
- MediaStreamType stream_type,
- const ResourceContext::SaltCallback& rc,
- const url::Origin& security_origin,
- const std::string& source_id,
- std::string* device_id);
+CONTENT_EXPORT bool GetMediaDeviceIDForHMAC(MediaStreamType stream_type,
+ const std::string& salt,
+ const url::Origin& security_origin,
+ const std::string& source_id,
+ std::string* device_id);
} // namespace content
diff --git a/chromium/content/public/browser/mojo_app_connection.h b/chromium/content/public/browser/mojo_app_connection.h
deleted file mode 100644
index d093fdfeec0..00000000000
--- a/chromium/content/public/browser/mojo_app_connection.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_PUBLIC_BROWSER_MOJO_APP_CONNECTION_H_
-#define CONTENT_PUBLIC_BROWSER_MOJO_APP_CONNECTION_H_
-
-#include <memory>
-#include <string>
-
-#include "content/common/content_export.h"
-#include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-
-namespace content {
-
-// A virtual app URL identifying the browser itself. This should be used for
-// a connection's |requestor_url| when connecting from browser code to apps that
-// don't require a more specific request context.
-CONTENT_EXPORT extern const char kBrowserMojoAppUrl[];
-
-// This provides a way for arbitrary browser code to connect to Mojo apps. These
-// objects are not thread-safe but may be constructed and used on any single
-// thread.
-class CONTENT_EXPORT MojoAppConnection {
- public:
- virtual ~MojoAppConnection() {}
-
- // Creates a new connection to the application at |name| using
- // |requestor_name| to identify the requestor and |context|'s mojo userid to
- // specify a profile specific application instantiation. This may be called
- // from any thread.
- static std::unique_ptr<MojoAppConnection> Create(
- const std::string& user_id,
- const std::string& name,
- const std::string& requestor_name);
-
- // Connects to a service within the application.
- template <typename Interface>
- void GetInterface(mojo::InterfacePtr<Interface>* proxy) {
- GetInterface(Interface::Name_, mojo::GetProxy(proxy).PassMessagePipe());
- }
-
- virtual void GetInterface(const std::string& interface_name,
- mojo::ScopedMessagePipeHandle handle) = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_MOJO_APP_CONNECTION_H_
diff --git a/chromium/content/public/browser/native_web_keyboard_event.h b/chromium/content/public/browser/native_web_keyboard_event.h
index 7f593dff287..0e305a62391 100644
--- a/chromium/content/public/browser/native_web_keyboard_event.h
+++ b/chromium/content/public/browser/native_web_keyboard_event.h
@@ -69,13 +69,6 @@ struct CONTENT_EXPORT NativeWebKeyboardEvent :
// it is hit in ime mode.
// Currently, it's only used by Linux and Mac ports.
bool skip_in_browser;
-
-#if defined(USE_AURA)
- // True if the key event matches an edit command. In order to ensure the edit
- // command always work in web page, the browser should not pre-handle this key
- // event as a reserved accelerator. See http://crbug.com/54573
- bool match_edit_command;
-#endif
};
} // namespace content
diff --git a/chromium/content/public/browser/navigation_controller.cc b/chromium/content/public/browser/navigation_controller.cc
index f8ab05f4221..ae63046ba07 100644
--- a/chromium/content/public/browser/navigation_controller.cc
+++ b/chromium/content/public/browser/navigation_controller.cc
@@ -16,7 +16,7 @@ NavigationController::LoadURLParams::LoadURLParams(const GURL& url)
frame_tree_node_id(-1),
is_renderer_initiated(false),
override_user_agent(UA_OVERRIDE_INHERIT),
- browser_initiated_post_data(nullptr),
+ post_data(nullptr),
can_load_local_resources(false),
should_replace_current_entry(false),
#if defined(OS_ANDROID)
@@ -42,7 +42,7 @@ NavigationController::LoadURLParams::LoadURLParams(
transferred_global_request_id(other.transferred_global_request_id),
base_url_for_data_url(other.base_url_for_data_url),
virtual_url_for_data_url(other.virtual_url_for_data_url),
- browser_initiated_post_data(other.browser_initiated_post_data),
+ post_data(other.post_data),
should_replace_current_entry(false),
#if defined(OS_ANDROID)
intent_received_timestamp(other.intent_received_timestamp),
@@ -66,7 +66,7 @@ NavigationController::LoadURLParams::operator=(
transferred_global_request_id = other.transferred_global_request_id;
base_url_for_data_url = other.base_url_for_data_url;
virtual_url_for_data_url = other.virtual_url_for_data_url;
- browser_initiated_post_data = other.browser_initiated_post_data;
+ post_data = other.post_data;
should_replace_current_entry = other.should_replace_current_entry;
should_clear_history_list = other.should_clear_history_list;
#if defined(OS_ANDROID)
diff --git a/chromium/content/public/browser/navigation_controller.h b/chromium/content/public/browser/navigation_controller.h
index e3673d12309..88760153286 100644
--- a/chromium/content/public/browser/navigation_controller.h
+++ b/chromium/content/public/browser/navigation_controller.h
@@ -20,12 +20,12 @@
#include "content/public/browser/session_storage_namespace.h"
#include "content/public/browser/site_instance.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/resource_request_body.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
namespace base {
-class RefCountedMemory;
class RefCountedString;
} // namespace base
@@ -65,9 +65,8 @@ class NavigationController {
// For loads that do not fall into any types below.
LOAD_TYPE_DEFAULT,
- // An http post load request initiated from browser side.
- // The post data is passed in |browser_initiated_post_data|.
- LOAD_TYPE_BROWSER_INITIATED_HTTP_POST,
+ // An http post load request. The post data is passed in |post_data|.
+ LOAD_TYPE_HTTP_POST,
// Loads a 'data:' scheme URL with specified base URL and a history entry
// URL. This is only safe to be used for browser-initiated data: URL
@@ -178,10 +177,10 @@ class NavigationController {
scoped_refptr<base::RefCountedString> data_url_as_string;
#endif
- // Used in LOAD_TYPE_BROWSER_INITIATED_HTTP_POST loads only. Carries the
- // post data of the load. Ownership is transferred to NavigationController
- // after LoadURLWithParams call.
- scoped_refptr<base::RefCountedMemory> browser_initiated_post_data;
+ // Used in LOAD_TYPE_HTTP_POST loads only. Carries the post data of the
+ // load. Ownership is transferred to NavigationController after
+ // LoadURLWithParams call.
+ scoped_refptr<ResourceRequestBody> post_data;
// True if this URL should be able to access local resources.
bool can_load_local_resources;
@@ -231,9 +230,8 @@ class NavigationController {
// nullptr.
virtual WebContents* GetWebContents() const = 0;
- // Get/set the browser context for this controller. It can never be nullptr.
+ // Get the browser context for this controller. It can never be nullptr.
virtual BrowserContext* GetBrowserContext() const = 0;
- virtual void SetBrowserContext(BrowserContext* browser_context) = 0;
// Initializes this NavigationController with the given saved navigations,
// using |selected_navigation| as the currently loaded entry. Before this call
diff --git a/chromium/content/public/browser/navigation_entry.h b/chromium/content/public/browser/navigation_entry.h
index a68e66151ba..92f020f9448 100644
--- a/chromium/content/public/browser/navigation_entry.h
+++ b/chromium/content/public/browser/navigation_entry.h
@@ -17,6 +17,7 @@
#include "content/common/content_export.h"
#include "content/public/common/page_type.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/resource_request_body.h"
#include "ui/base/page_transition_types.h"
class GURL;
@@ -139,8 +140,8 @@ class NavigationEntry {
// whether the page had post data.
//
// The actual post data is stored either in
- // 1) browser_initiated_post_data when a new post data request is started.
- // 2) content_state when a post request has started and is extracted by
+ // 1) post_data when a new post data request is started.
+ // 2) PageState when a post request has started and is extracted by
// WebKit to actually make the request.
virtual void SetHasPostData(bool has_post_data) = 0;
virtual bool GetHasPostData() const = 0;
@@ -149,16 +150,15 @@ class NavigationEntry {
virtual void SetPostID(int64_t post_id) = 0;
virtual int64_t GetPostID() const = 0;
- // Holds the raw post data of a browser initiated post request.
- // For efficiency, this should be cleared when content_state is populated
+ // Holds the raw post data of a post request.
+ // For efficiency, this should be cleared when PageState is populated
// since the data is duplicated.
// Note, this field:
// 1) is not persisted in session restore.
// 2) is shallow copied with the static copy Create method above.
// 3) may be nullptr so check before use.
- virtual void SetBrowserInitiatedPostData(
- const base::RefCountedMemory* data) = 0;
- virtual const base::RefCountedMemory* GetBrowserInitiatedPostData() const = 0;
+ virtual void SetPostData(const scoped_refptr<ResourceRequestBody>& data) = 0;
+ virtual scoped_refptr<ResourceRequestBody> GetPostData() const = 0;
// The favicon data and tracking information. See content::FaviconStatus.
virtual const FaviconStatus& GetFavicon() const = 0;
diff --git a/chromium/content/public/browser/navigation_handle.h b/chromium/content/public/browser/navigation_handle.h
index 7f1e8ab7111..54924a4ec63 100644
--- a/chromium/content/public/browser/navigation_handle.h
+++ b/chromium/content/public/browser/navigation_handle.h
@@ -38,6 +38,10 @@ class CONTENT_EXPORT NavigationHandle {
// The URL the frame is navigating to. This may change during the navigation
// when encountering a server redirect.
+ // This URL may not be the same as the virtual URL returned from
+ // WebContents::GetVisibleURL and WebContents::GetLastCommittedURL. For
+ // example, viewing a page's source navigates to the URL of the page, but the
+ // virtual URL is prefixed with "view-source:".
virtual const GURL& GetURL() = 0;
// Whether the navigation is taking place in the main frame or in a subframe.
@@ -89,8 +93,13 @@ class CONTENT_EXPORT NavigationHandle {
// This corresponds to NavigationThrottle::WillSendRequest. They should not
// be queried before that.
- // Whether the navigation is a POST or a GET. This may change during the
- // navigation when encountering a server redirect.
+ // Whether the navigation is done using HTTP POST method. This may change
+ // during the navigation (e.g. after encountering a server redirect).
+ //
+ // Note: page and frame navigations can only be done using HTTP POST or HTTP
+ // GET methods (and using other, scheme-specific protocols for non-http(s) URI
+ // schemes like data: or file:). Therefore //content public API exposes only
+ // |bool IsPost()| as opposed to |const std::string& GetMethod()| method.
virtual bool IsPost() = 0;
// Returns a sanitized version of the referrer for this request.
@@ -116,7 +125,12 @@ class CONTENT_EXPORT NavigationHandle {
virtual net::Error GetNetErrorCode() = 0;
// Returns the RenderFrameHost this navigation is taking place in. This can
- // only be accessed after the navigation is ready to commit.
+ // only be accessed after a response has been delivered for processing.
+ //
+ // If PlzNavigate is active, the RenderFrameHost returned will be the final
+ // host for the navigation. If PlzNavigate is inactive, the navigation may
+ // transfer to a new host up until the point that DidFinishNavigation is
+ // called.
virtual RenderFrameHost* GetRenderFrameHost() = 0;
// Whether the navigation happened in the same page. This is only known
diff --git a/chromium/content/public/browser/navigation_throttle.h b/chromium/content/public/browser/navigation_throttle.h
index 5876343db0d..4706111c055 100644
--- a/chromium/content/public/browser/navigation_throttle.h
+++ b/chromium/content/public/browser/navigation_throttle.h
@@ -32,6 +32,12 @@ class CONTENT_EXPORT NavigationThrottle {
// Cancels the navigation and makes the requester of the navigation acts
// like the request was never made.
CANCEL_AND_IGNORE,
+
+ // Blocks a navigation due to rules asserted before the request is made.
+ // This can only be returned from WillStartRequest. This will result in an
+ // error page for net::ERR_BLOCKED_BY_CLIENT being loaded in the frame that
+ // is navigated.
+ BLOCK_REQUEST,
};
NavigationThrottle(NavigationHandle* navigation_handle);
diff --git a/chromium/content/public/browser/page_navigator.h b/chromium/content/public/browser/page_navigator.h
index 51f02349648..fa7cebd2e6b 100644
--- a/chromium/content/public/browser/page_navigator.h
+++ b/chromium/content/public/browser/page_navigator.h
@@ -12,11 +12,11 @@
#include <string>
#include "base/memory/ref_counted.h"
-#include "base/memory/ref_counted_memory.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/site_instance.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/resource_request_body.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"
@@ -52,13 +52,10 @@ struct CONTENT_EXPORT OpenURLParams {
std::vector<GURL> redirect_chain;
// Indicates whether this navigation will be sent using POST.
- // The POST method is limited support for basic POST data by leveraging
- // NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST.
- // It is not for things like file uploads.
bool uses_post;
// The post data when the navigation uses POST.
- scoped_refptr<base::RefCountedMemory> browser_initiated_post_data;
+ scoped_refptr<ResourceRequestBody> post_data;
// Extra headers to add to the request for this page. Headers are
// represented as "<name>: <value>" and separated by \r\n. The entire string
diff --git a/chromium/content/public/browser/pepper_vpn_provider_resource_host_proxy.h b/chromium/content/public/browser/pepper_vpn_provider_resource_host_proxy.h
new file mode 100644
index 00000000000..ec96c29d4ac
--- /dev/null
+++ b/chromium/content/public/browser/pepper_vpn_provider_resource_host_proxy.h
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_PEPPER_VPN_PROVIDER_RESOURCE_HOST_PROXY_H_
+#define CONTENT_PUBLIC_BROWSER_PEPPER_VPN_PROVIDER_RESOURCE_HOST_PROXY_H_
+
+#include <vector>
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Describes interface for communication with the VpnProviderResouceHost.
+class CONTENT_EXPORT PepperVpnProviderResourceHostProxy {
+ public:
+ virtual ~PepperVpnProviderResourceHostProxy() {}
+
+ // Passes an Unbind event to the VpnProviderResouceHost.
+ virtual void SendOnUnbind() = 0;
+
+ // Sends an IP packet to the VpnProviderResouceHost.
+ virtual void SendOnPacketReceived(const std::vector<char>& data) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_PEPPER_VPN_PROVIDER_RESOURCE_HOST_PROXY_H_
diff --git a/chromium/content/public/browser/power_save_blocker.h b/chromium/content/public/browser/power_save_blocker.h
deleted file mode 100644
index 7b553e7f54e..00000000000
--- a/chromium/content/public/browser/power_save_blocker.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_BROWSER_POWER_SAVE_BLOCKER_H_
-#define CONTENT_PUBLIC_BROWSER_POWER_SAVE_BLOCKER_H_
-
-#include <memory>
-#include <string>
-
-#include "content/common/content_export.h"
-
-namespace content {
-
-// A RAII-style class to block the system from entering low-power (sleep) mode.
-// This class is thread-safe; it may be constructed and deleted on any thread.
-class CONTENT_EXPORT PowerSaveBlocker {
- public:
- enum PowerSaveBlockerType {
- // Prevent the application from being suspended. On some platforms, apps may
- // be suspended when they are not visible to the user. This type of block
- // requests that the app continue to run in that case, and on all platforms
- // prevents the system from sleeping.
- // Example use cases: downloading a file, playing audio.
- kPowerSaveBlockPreventAppSuspension,
-
- // Prevent the display from going to sleep. This also has the side effect of
- // preventing the system from sleeping, but does not necessarily prevent the
- // app from being suspended on some platforms if the user hides it.
- // Example use case: playing video.
- kPowerSaveBlockPreventDisplaySleep,
- };
-
- // Reasons why power-saving features may be blocked.
- enum Reason {
- // Audio is being played.
- kReasonAudioPlayback,
- // Video is being played.
- kReasonVideoPlayback,
- // Power-saving is blocked for some other reason.
- kReasonOther,
- };
-
- virtual ~PowerSaveBlocker() = 0;
-
- // Pass in the type of power save blocking desired. If multiple types of
- // blocking are desired, instantiate one PowerSaveBlocker for each type.
- // |reason| and |description| (a more-verbose, human-readable justification of
- // the blocking) may be provided to the underlying system APIs on some
- // platforms.
- static std::unique_ptr<PowerSaveBlocker> Create(
- PowerSaveBlockerType type,
- Reason reason,
- const std::string& description);
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_POWER_SAVE_BLOCKER_H_
diff --git a/chromium/content/public/browser/render_frame_host.h b/chromium/content/public/browser/render_frame_host.h
index c49e9cb005c..2fcb9cf1514 100644
--- a/chromium/content/public/browser/render_frame_host.h
+++ b/chromium/content/public/browser/render_frame_host.h
@@ -11,6 +11,7 @@
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/common/console_message_level.h"
+#include "content/public/common/file_chooser_params.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
@@ -23,12 +24,17 @@ namespace base {
class Value;
}
+namespace shell {
+class InterfaceRegistry;
+class InterfaceProvider;
+}
+
namespace content {
class RenderProcessHost;
class RenderViewHost;
class RenderWidgetHostView;
-class ServiceRegistry;
class SiteInstance;
+struct FileChooserFileInfo;
// The interface provides a communication conduit with a frame in the renderer.
class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
@@ -163,11 +169,27 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
virtual void InsertVisualStateCallback(
const VisualStateCallback& callback) = 0;
- // Temporary until we get rid of RenderViewHost.
+ // Copies the image at the location in viewport coordinates (not frame
+ // coordinates) to the clipboard. If there is no image at that location, does
+ // nothing.
+ virtual void CopyImageAt(int x, int y) = 0;
+
+ // Requests to save the image at the location in viewport coordinates (not
+ // frame coordinates). If there is an image at the location, the renderer
+ // will post back the appropriate download message to trigger the save UI.
+ // If there is no image at that location, does nothing.
+ virtual void SaveImageAt(int x, int y) = 0;
+
+ // RenderViewHost for this frame.
virtual RenderViewHost* GetRenderViewHost() = 0;
- // Returns the ServiceRegistry for this frame.
- virtual ServiceRegistry* GetServiceRegistry() = 0;
+ // Returns the InterfaceRegistry that this process uses to expose interfaces
+ // to the application running in this frame.
+ virtual shell::InterfaceRegistry* GetInterfaceRegistry() = 0;
+
+ // Returns the InterfaceProvider that this process can use to bind
+ // interfaces exposed to it by the application running in this frame.
+ virtual shell::InterfaceProvider* GetRemoteInterfaces() = 0;
// Returns the visibility state of the frame. The different visibility states
// of a frame are defined in Blink.
@@ -181,6 +203,13 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// use by resource metrics.
virtual int GetProxyCount() = 0;
+ // Notifies the Listener that one or more files have been chosen by the user
+ // from a file chooser dialog for the form. |permissions| is the file
+ // selection mode in which the chooser dialog was created.
+ virtual void FilesSelectedInChooser(
+ const std::vector<content::FileChooserFileInfo>& files,
+ FileChooserParams::Mode permissions) = 0;
+
private:
// This interface should only be implemented inside content.
friend class RenderFrameHostImpl;
diff --git a/chromium/content/public/browser/render_process_host.h b/chromium/content/public/browser/render_process_host.h
index 67fc03f27d9..cb4418c0600 100644
--- a/chromium/content/public/browser/render_process_host.h
+++ b/chromium/content/public/browser/render_process_host.h
@@ -33,6 +33,8 @@ class MediaKeys;
namespace shell {
class Connection;
+class InterfaceProvider;
+class InterfaceRegistry;
}
namespace content {
@@ -40,7 +42,6 @@ class BrowserContext;
class BrowserMessageFilter;
class RenderProcessHostObserver;
class RenderWidgetHost;
-class ServiceRegistry;
class StoragePartition;
struct GlobalRequestID;
@@ -254,8 +255,13 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// have changed.
virtual void NotifyTimezoneChange(const std::string& zone_id) = 0;
- // Returns the ServiceRegistry for this process.
- virtual ServiceRegistry* GetServiceRegistry() = 0;
+ // Returns the shell::InterfaceRegistry the browser process uses to expose
+ // interfaces to the renderer.
+ virtual shell::InterfaceRegistry* GetInterfaceRegistry() = 0;
+
+ // Returns the shell::InterfaceProvider the browser process can use to bind
+ // interfaces exposed to it from the renderer.
+ virtual shell::InterfaceProvider* GetRemoteInterfaces() = 0;
// Returns the shell connection for this process.
virtual shell::Connection* GetChildConnection() = 0;
diff --git a/chromium/content/public/browser/render_view_host.h b/chromium/content/public/browser/render_view_host.h
index ba928c5c346..1e0020b432a 100644
--- a/chromium/content/public/browser/render_view_host.h
+++ b/chromium/content/public/browser/render_view_host.h
@@ -6,9 +6,10 @@
#define CONTENT_PUBLIC_BROWSER_RENDER_VIEW_HOST_H_
#include "base/callback_forward.h"
+#include "base/files/file_path.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
-#include "content/public/common/file_chooser_params.h"
+#include "content/public/common/drop_data.h"
#include "content/public/common/page_zoom.h"
#include "ipc/ipc_sender.h"
#include "mojo/public/cpp/system/core.h"
@@ -40,8 +41,6 @@ class RenderViewHostDelegate;
class RenderWidgetHost;
class SessionStorageNamespace;
class SiteInstance;
-struct DropData;
-struct FileChooserFileInfo;
struct WebPreferences;
// A RenderViewHost is responsible for creating and talking to a RenderView
@@ -102,14 +101,6 @@ class CONTENT_EXPORT RenderViewHost : public IPC::Sender {
// Returns true if the current focused element is editable.
virtual bool IsFocusedElementEditable() = 0;
- // Copies the image at location x, y to the clipboard (if there indeed is an
- // image at that location).
- virtual void CopyImageAt(int x, int y) = 0;
-
- // Saves the image at location x, y to the disk (if there indeed is an
- // image at that location).
- virtual void SaveImageAt(int x, int y) = 0;
-
// Notifies the listener that a directory enumeration is complete.
virtual void DirectoryEnumerationFinished(
int request_id,
@@ -136,15 +127,23 @@ class CONTENT_EXPORT RenderViewHost : public IPC::Sender {
const gfx::Point& screen_pt,
blink::WebDragOperationsMask operations_allowed,
int key_modifiers) = 0;
+ virtual 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) = 0;
virtual void DragTargetDragOver(
const gfx::Point& client_pt,
const gfx::Point& screen_pt,
blink::WebDragOperationsMask operations_allowed,
int key_modifiers) = 0;
virtual void DragTargetDragLeave() = 0;
- virtual void DragTargetDrop(const gfx::Point& client_pt,
+ virtual void DragTargetDrop(const DropData& drop_data,
+ const gfx::Point& client_pt,
const gfx::Point& screen_pt,
int key_modifiers) = 0;
+ virtual void FilterDropData(DropData* drop_data) = 0;
// Instructs the RenderView to automatically resize and send back updates
// for the new size.
@@ -168,13 +167,6 @@ class CONTENT_EXPORT RenderViewHost : public IPC::Sender {
virtual void ExecutePluginActionAtLocation(
const gfx::Point& location, const blink::WebPluginAction& action) = 0;
- // Notifies the Listener that one or more files have been chosen by the user
- // from a file chooser dialog for the form. |permissions| is the file
- // selection mode in which the chooser dialog was created.
- virtual void FilesSelectedInChooser(
- const std::vector<content::FileChooserFileInfo>& files,
- FileChooserParams::Mode permissions) = 0;
-
virtual RenderViewHostDelegate* GetDelegate() const = 0;
// Returns a bitwise OR of bindings types that have been enabled for this
diff --git a/chromium/content/public/browser/render_widget_host.h b/chromium/content/public/browser/render_widget_host.h
index 216d13d005a..f5b81c13955 100644
--- a/chromium/content/public/browser/render_widget_host.h
+++ b/chromium/content/public/browser/render_widget_host.h
@@ -218,6 +218,11 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// warning too soon.
virtual void RestartHangMonitorTimeout() = 0;
+ // Stops and disables hang monitor. This avoids flakiness in tests that need
+ // to observe things like beforeunload dialogs, which could fail if the
+ // timeout skips the dialog.
+ virtual void DisableHangMonitorForTesting() = 0;
+
virtual void SetIgnoreInputEvents(bool ignore_input_events) = 0;
// Called to notify the RenderWidget that it has been resized.
@@ -253,8 +258,6 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// Get the screen info corresponding to this render widget.
virtual void GetWebScreenInfo(blink::WebScreenInfo* result) = 0;
- // Get the color profile corresponding to this render widget.
- virtual bool GetScreenColorProfile(std::vector<char>* color_profile) = 0;
// Sends a compositor proto to the render widget.
virtual void HandleCompositorProto(const std::vector<uint8_t>& proto) = 0;
diff --git a/chromium/content/public/browser/render_widget_host_view.h b/chromium/content/public/browser/render_widget_host_view.h
index b9022881a5f..5ef49e449d9 100644
--- a/chromium/content/public/browser/render_widget_host_view.h
+++ b/chromium/content/public/browser/render_widget_host_view.h
@@ -11,14 +11,13 @@
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkRegion.h"
#include "ui/gfx/native_widget_types.h"
class GURL;
namespace gfx {
+class Point;
class Rect;
class Size;
}
@@ -160,6 +159,14 @@ class CONTENT_EXPORT RenderWidgetHostView {
// deleted after this call.
virtual void EndFrameSubscription() = 0;
+ // Notification that a node was touched.
+ // The |location_dips_screen| parameter contains the location where the touch
+ // occurred in DIPs in screen coordinates.
+ // The |editable| parameter indicates if the node is editable, for e.g.
+ // an input field, etc.
+ virtual void FocusedNodeTouched(const gfx::Point& location_dips_screen,
+ bool editable) = 0;
+
#if defined(OS_MACOSX)
// Return the accelerated widget which hosts the CALayers that draw the
// content of the view in GetNativeView. This may be null.
diff --git a/chromium/content/public/browser/resource_context.h b/chromium/content/public/browser/resource_context.h
index 039ad94006d..41eb18e585e 100644
--- a/chromium/content/public/browser/resource_context.h
+++ b/chromium/content/public/browser/resource_context.h
@@ -18,7 +18,6 @@
class GURL;
namespace net {
-class ClientCertStore;
class HostResolver;
class KeygenHandler;
class URLRequestContext;
@@ -42,9 +41,6 @@ class CONTENT_EXPORT ResourceContext : public base::SupportsUserData {
// with a BrowsingContext.
virtual net::URLRequestContext* GetRequestContext() = 0;
- // Get platform ClientCertStore. May return nullptr.
- virtual std::unique_ptr<net::ClientCertStore> CreateClientCertStore();
-
// Create a platform KeygenHandler and pass it to |callback|. The |callback|
// may be run synchronously.
virtual void CreateKeygenHandler(
@@ -54,29 +50,17 @@ class CONTENT_EXPORT ResourceContext : public base::SupportsUserData {
const base::Callback<void(std::unique_ptr<net::KeygenHandler>)>&
callback);
- // Returns a callback that can be invoked to get a random salt
- // string that is used for creating media device IDs. The salt
- // should be stored in the current user profile and should be reset
- // if cookies are cleared. The default is an empty string.
- //
- // It is safe to hold on to the callback returned and use it without
- // regard to the lifetime of ResourceContext, although in general
- // you should not use it long after the profile has been destroyed.
- //
- // TODO(joi): We don't think it should be unnecessary to use this
- // after ResourceContext goes away. There is likely an underying bug
- // in the lifetime of ProfileIOData vs. ResourceProcessHost, where
- // sometimes ProfileIOData has gone away before RPH has finished
- // being torn down (on the IO thread). The current interface that
- // allows using the salt object after ResourceContext has gone away
- // was put in place to fix http://crbug.com/341211 but I intend to
- // try to figure out how the lifetime should be fixed properly. The
- // original interface was just a method that returns a string.
- //
- // TODO(perkj): Make this method pure virtual when crbug/315022 is
- // fixed.
- typedef base::Callback<std::string()> SaltCallback;
- virtual SaltCallback GetMediaDeviceIDSalt();
+ // Returns a random salt string that is used for creating media device IDs.
+ // Returns a random string by default.
+ virtual std::string GetMediaDeviceIDSalt();
+
+ // Utility function useful for embedders. Only needs to be called if
+ // 1) The embedder needs to use a new salt, and
+ // 2) The embedder saves its salt across restarts.
+ static std::string CreateRandomMediaDeviceIDSalt();
+
+ private:
+ const std::string media_device_id_salt_;
};
} // namespace content
diff --git a/chromium/content/public/browser/resource_dispatcher_host_delegate.cc b/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
index 6b57b792a25..26b2dcc6755 100644
--- a/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
+++ b/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
@@ -7,6 +7,7 @@
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/stream_info.h"
+#include "net/ssl/client_cert_store.h"
namespace content {
@@ -31,7 +32,6 @@ void ResourceDispatcherHostDelegate::DownloadStarting(
ResourceContext* resource_context,
int child_id,
int route_id,
- int request_id,
bool is_content_initiated,
bool must_download,
ScopedVector<ResourceThrottle>* throttles) {
@@ -50,7 +50,8 @@ bool ResourceDispatcherHostDelegate::HandleExternalProtocol(
const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
bool is_main_frame,
ui::PageTransition page_transition,
- bool has_user_gesture) {
+ bool has_user_gesture,
+ ResourceContext* resource_context) {
return true;
}
@@ -102,7 +103,10 @@ NavigationData* ResourceDispatcherHostDelegate::GetNavigationData(
return nullptr;
}
-ResourceDispatcherHostDelegate::ResourceDispatcherHostDelegate() {
+std::unique_ptr<net::ClientCertStore>
+ResourceDispatcherHostDelegate::CreateClientCertStore(
+ ResourceContext* resource_context) {
+ return std::unique_ptr<net::ClientCertStore>();
}
ResourceDispatcherHostDelegate::~ResourceDispatcherHostDelegate() {
diff --git a/chromium/content/public/browser/resource_dispatcher_host_delegate.h b/chromium/content/public/browser/resource_dispatcher_host_delegate.h
index b8ebbd33d02..18681a07484 100644
--- a/chromium/content/public/browser/resource_dispatcher_host_delegate.h
+++ b/chromium/content/public/browser/resource_dispatcher_host_delegate.h
@@ -23,6 +23,7 @@ class Sender;
namespace net {
class AuthChallengeInfo;
+class ClientCertStore;
class URLRequest;
}
@@ -61,7 +62,6 @@ class CONTENT_EXPORT ResourceDispatcherHostDelegate {
ResourceContext* resource_context,
int child_id,
int route_id,
- int request_id,
bool is_content_initiated,
bool must_download,
ScopedVector<ResourceThrottle>* throttles);
@@ -81,7 +81,8 @@ class CONTENT_EXPORT ResourceDispatcherHostDelegate {
const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
bool is_main_frame,
ui::PageTransition page_transition,
- bool has_user_gesture);
+ bool has_user_gesture,
+ ResourceContext* resource_context);
// Returns true if we should force the given resource to be downloaded.
// Otherwise, the content layer decides.
@@ -135,8 +136,11 @@ class CONTENT_EXPORT ResourceDispatcherHostDelegate {
// called for navigation requests.
virtual NavigationData* GetNavigationData(net::URLRequest* request) const;
+ // Get platform ClientCertStore. May return nullptr.
+ virtual std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
+ ResourceContext* resource_context);
+
protected:
- ResourceDispatcherHostDelegate();
virtual ~ResourceDispatcherHostDelegate();
};
diff --git a/chromium/content/public/browser/resource_hints.h b/chromium/content/public/browser/resource_hints.h
index 94355aef455..fdb77783745 100644
--- a/chromium/content/public/browser/resource_hints.h
+++ b/chromium/content/public/browser/resource_hints.h
@@ -6,13 +6,14 @@
#define CONTENT_PUBLIC_BROWSER_RESOURCE_HINTS_H_
#include "content/common/content_export.h"
+#include "net/base/completion_callback.h"
#include "net/http/http_request_info.h"
#include "url/gurl.h"
class GURL;
-namespace net {
-class URLRequestContextGetter;
+namespace content {
+class ResourceContext;
}
namespace content {
@@ -27,13 +28,19 @@ namespace content {
// Note: This should only be called on the IO thread, with a valid
// URLRequestContextGetter.
CONTENT_EXPORT void PreconnectUrl(
- net::URLRequestContextGetter* getter,
+ content::ResourceContext* resource_context,
const GURL& url,
const GURL& first_party_for_cookies,
int count,
bool allow_credentials,
net::HttpRequestInfo::RequestMotivation motivation);
+// Issues a DNS request to |url|. Note that these requests are sent to the host
+// resolver with priority net::IDLE.
+CONTENT_EXPORT int PreresolveUrl(content::ResourceContext* resource_context,
+ const GURL& url,
+ const net::CompletionCallback& callback);
+
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_RESOURCE_HINTS_H_
diff --git a/chromium/content/public/browser/resource_request_info.h b/chromium/content/public/browser/resource_request_info.h
index 68c32fbdb94..37a8c8ef8fd 100644
--- a/chromium/content/public/browser/resource_request_info.h
+++ b/chromium/content/public/browser/resource_request_info.h
@@ -30,6 +30,12 @@ class ResourceRequestInfo {
// Allocates a new, dummy ResourceRequestInfo and associates it with the
// given URLRequest.
+ //
+ // The RenderView routing ID must correspond to the RenderView of the
+ // RenderFrame, both of which share the same RenderProcess. This may be a
+ // different RenderView than the WebContents' main RenderView. If the
+ // download is not associated with a frame, the IDs can be all -1.
+ //
// NOTE: Add more parameters if you need to initialize other fields.
CONTENT_EXPORT static void AllocateForTesting(net::URLRequest* request,
ResourceType resource_type,
diff --git a/chromium/content/public/browser/screen_orientation_provider.cc b/chromium/content/public/browser/screen_orientation_provider.cc
index e50be45c7e0..f932cf4196f 100644
--- a/chromium/content/public/browser/screen_orientation_provider.cc
+++ b/chromium/content/public/browser/screen_orientation_provider.cc
@@ -52,7 +52,7 @@ void ScreenOrientationProvider::LockOrientation(int request_id,
return;
}
if (!static_cast<WebContentsImpl*>(web_contents())
- ->IsFullscreenForCurrentTab(rvhi->GetWidget())) {
+ ->IsFullscreenForCurrentTab()) {
dispatcher_->NotifyLockError(request_id,
blink::WebLockOrientationErrorFullScreenRequired);
return;
diff --git a/chromium/content/public/browser/security_style_explanations.cc b/chromium/content/public/browser/security_style_explanations.cc
index e88f5e0d487..b80631ee926 100644
--- a/chromium/content/public/browser/security_style_explanations.cc
+++ b/chromium/content/public/browser/security_style_explanations.cc
@@ -11,7 +11,8 @@ SecurityStyleExplanations::SecurityStyleExplanations()
displayed_insecure_content(false),
ran_insecure_content_style(SECURITY_STYLE_UNKNOWN),
displayed_insecure_content_style(SECURITY_STYLE_UNKNOWN),
- scheme_is_cryptographic(false) {}
+ scheme_is_cryptographic(false),
+ pkp_bypassed(false) {}
SecurityStyleExplanations::~SecurityStyleExplanations() {
}
diff --git a/chromium/content/public/browser/security_style_explanations.h b/chromium/content/public/browser/security_style_explanations.h
index 7dc88254bd8..adba598e702 100644
--- a/chromium/content/public/browser/security_style_explanations.h
+++ b/chromium/content/public/browser/security_style_explanations.h
@@ -46,6 +46,9 @@ struct SecurityStyleExplanations {
bool scheme_is_cryptographic;
+ // True if PKP was bypassed due to a local trust anchor.
+ bool pkp_bypassed;
+
std::vector<SecurityStyleExplanation> secure_explanations;
std::vector<SecurityStyleExplanation> unauthenticated_explanations;
std::vector<SecurityStyleExplanation> broken_explanations;
diff --git a/chromium/content/public/browser/site_instance.h b/chromium/content/public/browser/site_instance.h
index 1ab1b5c3c03..708da824c29 100644
--- a/chromium/content/public/browser/site_instance.h
+++ b/chromium/content/public/browser/site_instance.h
@@ -43,7 +43,8 @@ class RenderProcessHost;
// (which uses the same BrowsingInstance). If the user navigates within a site,
// the same SiteInstance is used. Caveat: we currently allow renderer-initiated
// cross-site navigations to stay in the same SiteInstance, to preserve
-// compatibility in cases like cross-site iframes that open popups.
+// compatibility in cases like cross-site iframes that open popups. This means
+// that most SiteInstances will contain pages from multiple sites.
//
// SITE PER PROCESS (currently experimental): is the most granular process
// model and is made possible by our support for out-of-process iframes. A
@@ -61,7 +62,9 @@ class RenderProcessHost;
//
// PROCESS PER SITE: We consolidate all SiteInstances for a given site into the
// same process, throughout the entire browser context. This ensures that only
-// one process will be used for each site.
+// one process will be used for each site. Note that there is no strict process
+// isolation of sites in this mode, so a given SiteInstance can still contain
+// pages from multiple sites.
//
// Each NavigationEntry for a WebContents points to the SiteInstance that
// rendered it. Each RenderFrameHost also points to the SiteInstance that it is
@@ -84,12 +87,12 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
// Returns the current RenderProcessHost being used to render pages for this
// SiteInstance. If there is no RenderProcessHost (because either none has
// yet been created or there was one but it was cleanly destroyed (e.g. when
- // it is not actively being used)), then this method will create a new
+ // it is not actively being used), then this method will create a new
// RenderProcessHost (and a new ID). Note that renderer process crashes leave
// the current RenderProcessHost (and ID) in place.
//
// For sites that require process-per-site mode (e.g., WebUI), this will
- // ensure only one RenderProcessHost for the site exists/ within the
+ // ensure only one RenderProcessHost for the site exists within the
// BrowserContext.
virtual content::RenderProcessHost* GetProcess() = 0;
@@ -97,8 +100,14 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
// SiteInstances) belongs.
virtual content::BrowserContext* GetBrowserContext() const = 0;
- // Get the web site that this SiteInstance is rendering pages for.
- // This includes the scheme and registered domain, but not the port.
+ // Get the web site that this SiteInstance is rendering pages for. This
+ // includes the scheme and registered domain, but not the port.
+ //
+ // NOTE: In most cases, this value should not be considered authoritative
+ // because a SiteInstance can usually host pages from multiple sites. It is
+ // only an accurate representation of the pages within the SiteInstance in
+ // the "site per process" process model, or for sites that require process
+ // isolation (e.g., WebUI, extensions).
virtual const GURL& GetSiteURL() const = 0;
// Gets a SiteInstance for the given URL that shares the current
diff --git a/chromium/content/public/browser/storage_partition.h b/chromium/content/public/browser/storage_partition.h
index 937e3ab7e05..6943bf5d4f2 100644
--- a/chromium/content/public/browser/storage_partition.h
+++ b/chromium/content/public/browser/storage_partition.h
@@ -86,6 +86,7 @@ class CONTENT_EXPORT StoragePartition {
REMOVE_DATA_MASK_WEBRTC_IDENTITY = 1 << 7,
REMOVE_DATA_MASK_SERVICE_WORKERS = 1 << 8,
REMOVE_DATA_MASK_CACHE_STORAGE = 1 << 9,
+ REMOVE_DATA_MASK_PLUGIN_PRIVATE_DATA = 1 << 10,
REMOVE_DATA_MASK_ALL = 0xFFFFFFFF,
// Corresponds to storage::kStorageTypeTemporary.
diff --git a/chromium/content/public/browser/url_data_source.cc b/chromium/content/public/browser/url_data_source.cc
index 0c76c50afd0..894c6e2dc72 100644
--- a/chromium/content/public/browser/url_data_source.cc
+++ b/chromium/content/public/browser/url_data_source.cc
@@ -33,12 +33,27 @@ bool URLDataSource::ShouldAddContentSecurityPolicy() const {
return true;
}
+std::string URLDataSource::GetContentSecurityPolicyScriptSrc() const {
+ // Specific resources require unsafe-eval in the Content Security Policy.
+ // TODO(tsepez,mfoltz): Remove 'unsafe-eval' when tests have been fixed to
+ // not use eval()/new Function(). http://crbug.com/525224
+ return "script-src chrome://resources 'self' 'unsafe-eval';";
+}
+
std::string URLDataSource::GetContentSecurityPolicyObjectSrc() const {
return "object-src 'none';";
}
-std::string URLDataSource::GetContentSecurityPolicyFrameSrc() const {
- return "frame-src 'none';";
+std::string URLDataSource::GetContentSecurityPolicyChildSrc() const {
+ return "child-src 'none';";
+}
+
+std::string URLDataSource::GetContentSecurityPolicyStyleSrc() const {
+ return std::string();
+}
+
+std::string URLDataSource::GetContentSecurityPolicyImgSrc() const {
+ return std::string();
}
bool URLDataSource::ShouldDenyXFrameOptions() const {
diff --git a/chromium/content/public/browser/url_data_source.h b/chromium/content/public/browser/url_data_source.h
index 565b0ff291a..111cc20cb11 100644
--- a/chromium/content/public/browser/url_data_source.h
+++ b/chromium/content/public/browser/url_data_source.h
@@ -86,22 +86,33 @@ class CONTENT_EXPORT URLDataSource {
// Returns true if responses from this URLDataSource can be cached.
virtual bool AllowCaching() const;
- // If you are overriding this, then you have a bug.
+ // If you are overriding the following two methods, then you have a bug.
// It is not acceptable to disable content-security-policy on chrome:// pages
// to permit functionality excluded by CSP, such as inline script.
// Instead, you must go back and change your WebUI page so that it is
// compliant with the policy. This typically involves ensuring that all script
- // is delivered through the data manager backend. Talk to tsepez for more
- // info.
+ // is delivered through the data manager backend. Do not disable CSP on your
+ // page without first contacting the chrome security team.
virtual bool ShouldAddContentSecurityPolicy() const;
-
- // It is OK to override the following two methods to a custom CSP directive
+ // For pre-existing code, enabling CSP with relaxed script-src attributes
+ // may be marginally better than disabling CSP outright.
+ // Do not override this method without first contacting the chrome security
+ // team.
+ // By default, "script-src chrome://resources 'self' 'unsafe-eval';" is added
+ // to CSP. Override to change this.
+ virtual std::string GetContentSecurityPolicyScriptSrc() const;
+
+ // It is OK to override the following methods to a custom CSP directive
// thereby slightly reducing the protection applied to the page.
// By default, "object-src 'none';" is added to CSP. Override to change this.
virtual std::string GetContentSecurityPolicyObjectSrc() const;
- // By default, "frame-src 'none';" is added to CSP. Override to change this.
- virtual std::string GetContentSecurityPolicyFrameSrc() const;
+ // By default, "child-src 'none';" is added to CSP. Override to change this.
+ virtual std::string GetContentSecurityPolicyChildSrc() const;
+ // By default empty. Override to change this.
+ virtual std::string GetContentSecurityPolicyStyleSrc() const;
+ // By default empty. Override to change this.
+ virtual std::string GetContentSecurityPolicyImgSrc() const;
// By default, the "X-Frame-Options: DENY" header is sent. To stop this from
// happening, return false. It is OK to return false as needed.
diff --git a/chromium/content/public/browser/utility_process_host.h b/chromium/content/public/browser/utility_process_host.h
index 98cca9b3bbc..6fa815a91c7 100644
--- a/chromium/content/public/browser/utility_process_host.h
+++ b/chromium/content/public/browser/utility_process_host.h
@@ -17,8 +17,12 @@ class FilePath;
class SequencedTaskRunner;
}
+namespace shell {
+class InterfaceProvider;
+class InterfaceRegistry;
+}
+
namespace content {
-class ServiceRegistry;
class UtilityProcessHostClient;
struct ChildProcessData;
@@ -29,9 +33,9 @@ struct ChildProcessData;
// If you need multiple batches of work to be done in the process, use
// StartBatchMode(), then multiple calls to StartFooBar(p), then finish with
// EndBatchMode().
-// If you need to call Mojo services, use Start() to start the child
-// process and GetServiceRegistry() to get the service registry to connect to
-// the child's Mojo services.
+// If you need to bind Mojo interfaces, use Start() to start the child
+// process and GetRemoteInterfaces() to get the utility process'
+// shell::InterfaceProvider.
//
// Note: If your class keeps a ptr to an object of this type, grab a weak ptr to
// avoid a use after free since this object is deleted synchronously but the
@@ -79,8 +83,13 @@ class UtilityProcessHost : public IPC::Sender {
// Starts the utility process.
virtual bool Start() = 0;
- // Returns the ServiceRegistry for this process. Will never return nullptr.
- virtual ServiceRegistry* GetServiceRegistry() = 0;
+ // Returns the shell::InterfaceRegistry the browser process uses to expose
+ // interfaces to the utility process.
+ virtual shell::InterfaceRegistry* GetInterfaceRegistry() = 0;
+
+ // Returns the shell::InterfaceProvider the browser process can use to bind
+ // interfaces exposed to it from the utility process.
+ virtual shell::InterfaceProvider* GetRemoteInterfaces() = 0;
// Set the name of the process to appear in the task manager.
virtual void SetName(const base::string16& name) = 0;
diff --git a/chromium/content/public/browser/utility_process_mojo_client.h b/chromium/content/public/browser/utility_process_mojo_client.h
new file mode 100644
index 00000000000..09bf76c6080
--- /dev/null
+++ b/chromium/content/public/browser/utility_process_mojo_client.h
@@ -0,0 +1,143 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_UTILITY_PROCESS_MOJO_CLIENT_H_
+#define CONTENT_PUBLIC_BROWSER_UTILITY_PROCESS_MOJO_CLIENT_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "base/threading/thread_checker.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/utility_process_host.h"
+#include "content/public/browser/utility_process_host_client.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "services/shell/public/cpp/interface_provider.h"
+
+namespace content {
+
+// Implements a client to a Mojo service running on a utility process. Takes
+// care of starting the utility process and connecting to the remote Mojo
+// service. The utility process is terminated in the destructor.
+// Note: This class is not thread-safe. It is bound to the
+// SingleThreadTaskRunner it is created on.
+template <class MojoInterface>
+class UtilityProcessMojoClient {
+ public:
+ explicit UtilityProcessMojoClient(const base::string16& process_name) {
+ helper_.reset(new Helper(process_name));
+ }
+
+ ~UtilityProcessMojoClient() {
+ BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, helper_.release());
+ }
+
+ // Sets the error callback. A valid callback must be set before calling
+ // Start().
+ void set_error_callback(const base::Closure& on_error_callback) {
+ on_error_callback_ = on_error_callback;
+ }
+
+ // Disables the sandbox in the utility process.
+ void set_disable_sandbox() {
+ DCHECK(!start_called_);
+ helper_->set_disable_sandbox();
+ }
+
+ // Starts the utility process and connect to the remote Mojo service.
+ void Start() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!on_error_callback_.is_null());
+ DCHECK(!start_called_);
+
+ start_called_ = true;
+
+ mojo::InterfaceRequest<MojoInterface> req = mojo::GetProxy(&service_);
+ service_.set_connection_error_handler(on_error_callback_);
+ helper_->Start(MojoInterface::Name_, req.PassMessagePipe());
+ }
+
+ // Returns the Mojo service used to make calls to the utility process.
+ MojoInterface* service() WARN_UNUSED_RESULT {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(start_called_);
+
+ return service_.get();
+ }
+
+ private:
+ // Helper class that takes care of managing the lifetime of the utility
+ // process on the IO thread.
+ class Helper {
+ public:
+ explicit Helper(const base::string16& process_name)
+ : process_name_(process_name) {}
+
+ ~Helper() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // |utility_host_| manages its own lifetime but this forces the process to
+ // terminate if it's still alive.
+ delete utility_host_.get();
+ }
+
+ // Starts the utility process on the IO thread.
+ void Start(const std::string& mojo_interface_name,
+ mojo::ScopedMessagePipeHandle interface_pipe) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&Helper::StartOnIOThread, base::Unretained(this),
+ mojo_interface_name, base::Passed(&interface_pipe)));
+ }
+
+ void set_disable_sandbox() { disable_sandbox_ = true; }
+
+ private:
+ // Starts the utility process and connects to the remote Mojo service.
+ void StartOnIOThread(const std::string& mojo_interface_name,
+ mojo::ScopedMessagePipeHandle interface_pipe) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ utility_host_ = UtilityProcessHost::Create(nullptr, nullptr)->AsWeakPtr();
+ utility_host_->SetName(process_name_);
+ if (disable_sandbox_)
+ utility_host_->DisableSandbox();
+
+ utility_host_->Start();
+
+ utility_host_->GetRemoteInterfaces()->GetInterface(
+ mojo_interface_name, std::move(interface_pipe));
+ }
+
+ // Properties of the utility process.
+ base::string16 process_name_;
+ bool disable_sandbox_ = false;
+
+ // Must only be accessed on the IO thread.
+ base::WeakPtr<UtilityProcessHost> utility_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(Helper);
+ };
+
+ std::unique_ptr<Helper> helper_;
+
+ // Called when a connection error happens or if the process didn't start.
+ base::Closure on_error_callback_;
+
+ mojo::InterfacePtr<MojoInterface> service_;
+
+ // Enforce calling Start() before getting the service.
+ bool start_called_ = false;
+
+ // Checks that this class is always accessed from the same thread.
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(UtilityProcessMojoClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_UTILITY_PROCESS_MOJO_CLIENT_H_
diff --git a/chromium/content/public/browser/vpn_service_proxy.h b/chromium/content/public/browser/vpn_service_proxy.h
new file mode 100644
index 00000000000..86646af69d7
--- /dev/null
+++ b/chromium/content/public/browser/vpn_service_proxy.h
@@ -0,0 +1,47 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_VPN_SERVICE_PROXY_H_
+#define CONTENT_PUBLIC_BROWSER_VPN_SERVICE_PROXY_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+
+namespace content {
+class PepperVpnProviderResourceHostProxy;
+
+// Describes interface for communication with an external VpnService.
+// All the methods below can only be called on the UI thread.
+class CONTENT_EXPORT VpnServiceProxy {
+ public:
+ using SuccessCallback = base::Closure;
+ using FailureCallback =
+ base::Callback<void(const std::string& error_name,
+ const std::string& error_message)>;
+
+ virtual ~VpnServiceProxy() {}
+
+ // Binds an existing VPN connection in the VpnService. Registers with the
+ // VpnService the Resource host back-end.
+ virtual void Bind(const std::string& host_id,
+ const std::string& configuration_id,
+ const std::string& configuration_name,
+ const SuccessCallback& success,
+ const FailureCallback& failure,
+ std::unique_ptr<PepperVpnProviderResourceHostProxy>
+ pepper_vpn_provider_proxy) = 0;
+
+ // Sends an IP packet to the VpnService.
+ virtual void SendPacket(const std::string& host_id,
+ const std::vector<char>& data,
+ const SuccessCallback& success,
+ const FailureCallback& failure) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_VPN_SERVICE_PROXY_H_
diff --git a/chromium/content/public/browser/web_contents.cc b/chromium/content/public/browser/web_contents.cc
index 69190cfd6d0..fa0afb545df 100644
--- a/chromium/content/public/browser/web_contents.cc
+++ b/chromium/content/public/browser/web_contents.cc
@@ -28,7 +28,9 @@ WebContents::CreateParams::CreateParams(BrowserContext* context,
initially_hidden(false),
guest_delegate(nullptr),
context(nullptr),
- renderer_initiated_creation(false) {}
+ renderer_initiated_creation(false),
+ initialize_renderer(false) {
+}
WebContents::CreateParams::CreateParams(const CreateParams& other) = default;
diff --git a/chromium/content/public/browser/web_contents.h b/chromium/content/public/browser/web_contents.h
index 6aa00e66ac6..9ccb6fea4c4 100644
--- a/chromium/content/public/browser/web_contents.h
+++ b/chromium/content/public/browser/web_contents.h
@@ -149,6 +149,14 @@ class WebContents : public PageNavigator,
// RenderFrame, have already been created on the renderer side, and
// WebContents construction should take this into account.
bool renderer_initiated_creation;
+
+ // True if the WebContents should create its renderer process and main
+ // RenderFrame before the first navigation. This is useful to reduce
+ // the latency of the first navigation in cases where it might
+ // not happen right away.
+ // Note that the pre-created renderer process may not be used if the first
+ // navigation requires a dedicated or privileged process, such as a WebUI.
+ bool initialize_renderer;
};
// Creates a new WebContents.
@@ -195,16 +203,20 @@ class WebContents : public PageNavigator,
// |GetLastCommittedURL| as appropriate.
virtual const GURL& GetURL() const = 0;
- // Gets the URL currently being displayed in the URL bar, if there is one.
- // This URL might be a pending navigation that hasn't committed yet, so it is
- // not guaranteed to match the current page in this WebContents. A typical
- // example of this is interstitials, which show the URL of the new/loading
- // page (active) but the security context is of the old page (last committed).
+ // Gets the virtual URL currently being displayed in the URL bar, if there is
+ // one. This URL might be a pending navigation that hasn't committed yet, so
+ // it is not guaranteed to match the current page in this WebContents. A
+ // typical example of this is interstitials, which show the URL of the
+ // new/loading page (active) but the security context is of the old page (last
+ // committed).
virtual const GURL& GetVisibleURL() const = 0;
- // Gets the last committed URL. It represents the current page that is
- // displayed in this WebContents. It represents the current security
- // context.
+ // Gets the virtual URL of the last committed page in this WebContents.
+ // Virtual URLs are meant to be displayed to the user (e.g., they include the
+ // "view-source:" prefix for view source URLs, unlike NavigationEntry::GetURL
+ // and NavigationHandle::GetURL). The last committed page is the current
+ // security context and the content that is actually displayed within the tab.
+ // See also GetVisibleURL above, which may differ from this URL.
virtual const GURL& GetLastCommittedURL() const = 0;
// Return the currently active RenderProcessHost and RenderViewHost. Each of
diff --git a/chromium/content/public/browser/web_contents_delegate.h b/chromium/content/public/browser/web_contents_delegate.h
index 74b56e15f70..2816c4da06c 100644
--- a/chromium/content/public/browser/web_contents_delegate.h
+++ b/chromium/content/public/browser/web_contents_delegate.h
@@ -341,7 +341,7 @@ class CONTENT_EXPORT WebContentsDelegate {
const std::vector<ColorSuggestion>& suggestions);
// Called when a file selection is to be done.
- virtual void RunFileChooser(WebContents* web_contents,
+ virtual void RunFileChooser(RenderFrameHost* render_frame_host,
const FileChooserParams& params) {}
// Request to enumerate a directory. This is equivalent to running the file
diff --git a/chromium/content/public/browser/web_contents_observer.h b/chromium/content/public/browser/web_contents_observer.h
index 1b8f1996095..d01c9a30c26 100644
--- a/chromium/content/public/browser/web_contents_observer.h
+++ b/chromium/content/public/browser/web_contents_observer.h
@@ -57,6 +57,8 @@ struct SecurityStyleExplanations;
class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
public IPC::Sender {
public:
+ // Frames and Views ----------------------------------------------------------
+
// Called when a RenderFrame for |render_frame_host| is created in the
// renderer process. Use |RenderFrameDeleted| to listen for when this
// RenderFrame goes away.
@@ -127,7 +129,7 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// RenderFrameHost becomes unresponsive.
virtual void OnRendererUnresponsive(RenderWidgetHost* render_widget_host) {}
- // Navigation related events ------------------------------------------------
+ // Navigation ----------------------------------------------------------------
// Called when a navigation started in the WebContents. |navigation_handle|
// is unique to a specific navigation. The same |navigation_handle| will be
@@ -178,50 +180,18 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// so do not keep a reference to it afterward.
virtual void DidFinishNavigation(NavigationHandle* navigation_handle) {}
- // Document load events ------------------------------------------------------
-
- // These two methods correspond to the points in time when the spinner of the
- // tab starts and stops spinning.
- virtual void DidStartLoading() {}
- virtual void DidStopLoading() {}
-
- // This method is invoked once the window.document object of the main frame
- // was created.
- virtual void DocumentAvailableInMainFrame() {}
-
- // This method is invoked once the onload handler of the main frame has
- // completed.
- virtual void DocumentOnLoadCompletedInMainFrame() {}
-
- // This method is invoked when the document in the given frame finished
- // loading. At this point, scripts marked as defer were executed, and
- // content scripts marked "document_end" get injected into the frame.
- virtual void DocumentLoadedInFrame(RenderFrameHost* render_frame_host) {}
-
- // This method is invoked when the navigation is done, i.e. the spinner of
- // the tab will stop spinning, and the onload event was dispatched.
- //
- // If the WebContents is displaying replacement content, e.g. network error
- // pages, DidFinishLoad is invoked for frames that were not sending
- // navigational events before. It is safe to ignore these events.
- virtual void DidFinishLoad(RenderFrameHost* render_frame_host,
- const GURL& validated_url) {}
-
- // This method is like DidFinishLoad, but when the load failed or was
- // cancelled, e.g. window.stop() is invoked.
- virtual void DidFailLoad(RenderFrameHost* render_frame_host,
- const GURL& validated_url,
- int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) {}
-
- // ---------------------------------------------------------------------------
+ // Navigation (obsolete and deprecated) --------------------------------------
// This method is invoked after the browser process starts a navigation to a
// pending NavigationEntry. It is not called for renderer-initiated
// navigations unless they are sent to the browser process via OpenURL. It may
// be called multiple times for a given navigation, such as a typed URL
// followed by a cross-process client or server redirect.
+ //
+ // SOON TO BE DEPRECATED. Use DidStartNavigation instead in PlzNavigate. In
+ // default mode, it is still necessary to override this function to be
+ // notified about a navigation earlier than DidStartProvisionalLoad. This
+ // function will be removed when PlzNavigate is enabled.
virtual void DidStartNavigationToPendingEntry(
const GURL& url,
NavigationController::ReloadType reload_type) {}
@@ -235,6 +205,8 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
//
// Note that during a cross-process navigation, several provisional loads
// can be on-going in parallel.
+ //
+ // DEPRECATED. Use DidStartNavigation instead in all cases.
virtual void DidStartProvisionalLoadForFrame(
RenderFrameHost* render_frame_host,
const GURL& validated_url,
@@ -247,12 +219,16 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// If the navigation only changed the reference fragment, or was triggered
// using the history API (e.g. window.history.replaceState), we will receive
// this signal without a prior DidStartProvisionalLoadForFrame signal.
+ //
+ // DEPRECATED. Use DidFinishNavigation instead in all cases.
virtual void DidCommitProvisionalLoadForFrame(
RenderFrameHost* render_frame_host,
const GURL& url,
ui::PageTransition transition_type) {}
// This method is invoked when the provisional load failed.
+ //
+ // DEPRECATED. Use DidFinishNavigation instead in all cases.
virtual void DidFailProvisionalLoad(
RenderFrameHost* render_frame_host,
const GURL& validated_url,
@@ -262,17 +238,58 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// If the provisional load corresponded to the main frame, this method is
// invoked in addition to DidCommitProvisionalLoadForFrame.
+ //
+ // DEPRECATED. Use DidFinishNavigation instead in all cases.
virtual void DidNavigateMainFrame(
const LoadCommittedDetails& details,
const FrameNavigateParams& params) {}
// And regardless of what frame navigated, this method is invoked after
// DidCommitProvisionalLoadForFrame was invoked.
+ //
+ // DEPRECATED. Use DidFinishNavigation instead in all cases.
virtual void DidNavigateAnyFrame(
RenderFrameHost* render_frame_host,
const LoadCommittedDetails& details,
const FrameNavigateParams& params) {}
+ // Document load events ------------------------------------------------------
+
+ // These two methods correspond to the points in time when the spinner of the
+ // tab starts and stops spinning.
+ virtual void DidStartLoading() {}
+ virtual void DidStopLoading() {}
+
+ // This method is invoked once the window.document object of the main frame
+ // was created.
+ virtual void DocumentAvailableInMainFrame() {}
+
+ // This method is invoked once the onload handler of the main frame has
+ // completed.
+ virtual void DocumentOnLoadCompletedInMainFrame() {}
+
+ // This method is invoked when the document in the given frame finished
+ // loading. At this point, scripts marked as defer were executed, and
+ // content scripts marked "document_end" get injected into the frame.
+ virtual void DocumentLoadedInFrame(RenderFrameHost* render_frame_host) {}
+
+ // This method is invoked when the load is done, i.e. the spinner of the tab
+ // will stop spinning, and the onload event was dispatched.
+ //
+ // If the WebContents is displaying replacement content, e.g. network error
+ // pages, DidFinishLoad is invoked for frames that were not sending
+ // navigational events before. It is safe to ignore these events.
+ virtual void DidFinishLoad(RenderFrameHost* render_frame_host,
+ const GURL& validated_url) {}
+
+ // This method is like DidFinishLoad, but when the load failed or was
+ // cancelled, e.g. window.stop() is invoked.
+ virtual void DidFailLoad(RenderFrameHost* render_frame_host,
+ const GURL& validated_url,
+ int error_code,
+ const base::string16& error_description,
+ bool was_ignored_by_handler) {}
+
// This method is invoked when the SecurityStyle of the WebContents changes.
// |security_style| is the new SecurityStyle. |security_style_explanations|
// contains human-readable strings explaining why the SecurityStyle of the
@@ -290,8 +307,8 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
virtual void DidGetResourceResponseStart(
const ResourceRequestDetails& details) {}
- // This method is invoked when a redirect was received while requesting a
- // resource.
+ // This method is invoked when a redirect has been received for a resource
+ // request.
virtual void DidGetRedirectForResourceRequest(
RenderFrameHost* render_frame_host,
const ResourceRedirectDetails& details) {}
@@ -318,6 +335,10 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// paint after a non-empty layout.
virtual void DidFirstVisuallyNonEmptyPaint() {}
+ // This method is invoked when the main frame in the renderer process performs
+ // the first paint after a navigation.
+ virtual void DidFirstPaintAfterLoad(RenderWidgetHost* render_widget_host) {}
+
// When WebContents::Stop() is called, the WebContents stops loading and then
// invokes this method. If there are ongoing navigations, their respective
// failure methods will also be invoked.
diff --git a/chromium/content/public/browser/web_ui.h b/chromium/content/public/browser/web_ui.h
index 8d45e28b8bd..bdb216f0431 100644
--- a/chromium/content/public/browser/web_ui.h
+++ b/chromium/content/public/browser/web_ui.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/memory/scoped_vector.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
#include "ui/base/page_transition_types.h"
@@ -105,24 +106,28 @@ class CONTENT_EXPORT WebUI {
//
// All function names in WebUI must consist of only ASCII characters.
// There are variants for calls with more arguments.
- virtual void CallJavascriptFunction(const std::string& function_name) = 0;
- virtual void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg) = 0;
- virtual void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2) = 0;
- virtual void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2,
- const base::Value& arg3) = 0;
- virtual void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2,
- const base::Value& arg3,
- const base::Value& arg4) = 0;
- virtual void CallJavascriptFunction(
+ virtual void CallJavascriptFunctionUnsafe(
+ const std::string& function_name) = 0;
+ virtual void CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg) = 0;
+ virtual void CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2) = 0;
+ virtual void CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2,
+ const base::Value& arg3) = 0;
+ virtual void CallJavascriptFunctionUnsafe(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2,
+ const base::Value& arg3,
+ const base::Value& arg4) = 0;
+ virtual void CallJavascriptFunctionUnsafe(
const std::string& function_name,
const std::vector<const base::Value*>& args) = 0;
+
+ // Allows mutable access to this WebUI's message handlers for testing.
+ virtual ScopedVector<WebUIMessageHandler>* GetHandlersForTesting() = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/web_ui_data_source.h b/chromium/content/public/browser/web_ui_data_source.h
index 3b174c443f8..515146bd20c 100644
--- a/chromium/content/public/browser/web_ui_data_source.h
+++ b/chromium/content/public/browser/web_ui_data_source.h
@@ -82,7 +82,7 @@ class WebUIDataSource {
virtual void DisableContentSecurityPolicy() = 0;
virtual void OverrideContentSecurityPolicyObjectSrc(
const std::string& data) = 0;
- virtual void OverrideContentSecurityPolicyFrameSrc(
+ virtual void OverrideContentSecurityPolicyChildSrc(
const std::string& data) = 0;
virtual void DisableDenyXFrameOptions() = 0;
};
diff --git a/chromium/content/public/browser/web_ui_message_handler.h b/chromium/content/public/browser/web_ui_message_handler.h
index ed0117931f5..3dc9808f885 100644
--- a/chromium/content/public/browser/web_ui_message_handler.h
+++ b/chromium/content/public/browser/web_ui_message_handler.h
@@ -35,6 +35,15 @@ class CONTENT_EXPORT WebUIMessageHandler {
WebUIMessageHandler() : javascript_allowed_(false), web_ui_(nullptr) {}
virtual ~WebUIMessageHandler() {}
+ // Call this when a page should not receive JavaScript messages.
+ void DisallowJavascript();
+
+ // Called from tests to toggle JavaScript to catch bugs. If AllowJavascript()
+ // is needed from production code, just publicize AllowJavascript() instead.
+ void AllowJavascriptForTesting();
+
+ bool IsJavascriptAllowed() const;
+
protected:
FRIEND_TEST_ALL_PREFIXES(WebUIMessageHandlerTest, ExtractIntegerValue);
FRIEND_TEST_ALL_PREFIXES(WebUIMessageHandlerTest, ExtractDoubleValue);
@@ -44,11 +53,6 @@ class CONTENT_EXPORT WebUIMessageHandler {
// from this handler.
void AllowJavascript();
- // Call this when a page should not receive JavaScript messages.
- void DisallowJavascript();
-
- bool IsJavascriptAllowed() const;
-
// Helper methods:
// Extract an integer value from a list Value.
@@ -77,6 +81,18 @@ class CONTENT_EXPORT WebUIMessageHandler {
// to deregister or disabled observers that push JavaScript calls to the page.
virtual void OnJavascriptDisallowed() {}
+ // Helper method for responding to Javascript requests initiated with
+ // cr.sendWithPromise() (defined in cr.js) for the case where the returned
+ // promise should be resolved (request succeeded).
+ void ResolveJavascriptCallback(const base::Value& callback_id,
+ const base::Value& response);
+
+ // Helper method for responding to Javascript requests initiated with
+ // cr.sendWithPromise() (defined in cr.js), for the case where the returned
+ // promise should be rejected (request failed).
+ void RejectJavascriptCallback(const base::Value& callback_id,
+ const base::Value& response);
+
// Call a Javascript function by sending its name and arguments down to
// the renderer. This is asynchronous; there's no way to get the result
// of the call, and should be thought of more like sending a message to
@@ -88,7 +104,9 @@ class CONTENT_EXPORT WebUIMessageHandler {
const Values&... values) {
CHECK(IsJavascriptAllowed()) << "Cannot CallJavascriptFunction before "
"explicitly allowing JavaScript.";
- web_ui()->CallJavascriptFunction(function_name, values...);
+
+ // The CHECK above makes this call safe.
+ web_ui()->CallJavascriptFunctionUnsafe(function_name, values...);
}
// Returns the attached WebUI for this handler.
@@ -103,9 +121,6 @@ class CONTENT_EXPORT WebUIMessageHandler {
friend class WebUIImpl;
friend class ::WebUIBrowserTest;
- // Called when a RenderView is reused to display a page (i.e. reload).
- void RenderViewReused();
-
// TODO(dbeam): disallow JavaScript when a renderer process crashes.
// http://crbug.com/610450
diff --git a/chromium/content/public/child/BUILD.gn b/chromium/content/public/child/BUILD.gn
index a6e14152987..00bdfa3a1f9 100644
--- a/chromium/content/public/child/BUILD.gn
+++ b/chromium/content/public/child/BUILD.gn
@@ -31,7 +31,10 @@ source_set("child_sources") {
".",
"//content")
- configs += [ "//content:content_implementation" ]
+ configs += [
+ "//build/config/compiler:wexit_time_destructors",
+ "//content:content_implementation",
+ ]
deps = [
"//content/child", # Must not be public_deps!
diff --git a/chromium/content/public/child/child_thread.h b/chromium/content/public/child/child_thread.h
index 94eb3212a03..d3ad0cec617 100644
--- a/chromium/content/public/child/child_thread.h
+++ b/chromium/content/public/child/child_thread.h
@@ -20,8 +20,15 @@ namespace base {
struct UserMetricsAction;
}
+namespace shell {
+class InterfaceProvider;
+class InterfaceRegistry;
+}
+
namespace content {
+ class MojoShellConnection;
+
// An abstract base class that contains logic shared between most child
// processes of the embedder.
class CONTENT_EXPORT ChildThread : public IPC::Sender {
@@ -59,6 +66,18 @@ class CONTENT_EXPORT ChildThread : public IPC::Sender {
// When you use this you need to also update the rules for extracting known
// actions in chrome/tools/extract_actions.py.
virtual void RecordComputedAction(const std::string& action) = 0;
+
+ // Returns the MojoShellConnection for the thread (from which a
+ // shell::Connector can be obtained).
+ virtual MojoShellConnection* GetMojoShellConnection() = 0;
+
+ // Returns the InterfaceRegistry that this process uses to expose interfaces
+ // to the browser.
+ virtual shell::InterfaceRegistry* GetInterfaceRegistry() = 0;
+
+ // Returns the InterfaceProvider that this process can use to bind
+ // interfaces exposed to it by the browser.
+ virtual shell::InterfaceProvider* GetRemoteInterfaces() = 0;
};
} // namespace content
diff --git a/chromium/content/public/child/v8_value_converter.h b/chromium/content/public/child/v8_value_converter.h
index a7a0e8946f0..aeb38c9a829 100644
--- a/chromium/content/public/child/v8_value_converter.h
+++ b/chromium/content/public/child/v8_value_converter.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_PUBLIC_CHILD_V8_VALUE_CONVERTER_H_
#define CONTENT_PUBLIC_CHILD_V8_VALUE_CONVERTER_H_
+#include <memory>
+
#include "base/callback.h"
#include "content/common/content_export.h"
#include "v8/include/v8.h"
@@ -28,8 +30,9 @@ class CONTENT_EXPORT V8ValueConverter {
// Extends the default behaviour of V8ValueConverter.
class CONTENT_EXPORT Strategy {
public:
- typedef base::Callback<base::Value*(
- v8::Local<v8::Value>, v8::Isolate* isolate)> FromV8ValueCallback;
+ typedef base::Callback<std::unique_ptr<base::Value>(v8::Local<v8::Value>,
+ v8::Isolate* isolate)>
+ FromV8ValueCallback;
virtual ~Strategy() {}
@@ -38,7 +41,7 @@ class CONTENT_EXPORT V8ValueConverter {
// Use |callback| to convert any child values, as this will retain
// the ValueConverter's internal checks for depth and cycles.
virtual bool FromV8Object(v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const;
@@ -47,7 +50,7 @@ class CONTENT_EXPORT V8ValueConverter {
// Use |callback| to convert any child values, as this will retain
// the ValueConverter's internal checks for depth and cycles.
virtual bool FromV8Array(v8::Local<v8::Array> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const;
@@ -55,18 +58,18 @@ class CONTENT_EXPORT V8ValueConverter {
// behavior. v8::Object is passed as ArrayBuffer and ArrayBufferView
// classes are siblings.
virtual bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate) const;
// If false is returned, V8ValueConverter proceeds with the default
// behavior. This allows to intercept "non-finite" values and do something
// with them.
virtual bool FromV8Number(v8::Local<v8::Number> value,
- base::Value** out) const;
+ std::unique_ptr<base::Value>* out) const;
// If false is returned, V8ValueConverter proceeds with the default
// behavior.
- virtual bool FromV8Undefined(base::Value** out) const;
+ virtual bool FromV8Undefined(std::unique_ptr<base::Value>* out) const;
};
static V8ValueConverter* create();
@@ -105,6 +108,7 @@ class CONTENT_EXPORT V8ValueConverter {
// Unsupported types are replaced with null. If an array or object throws
// while setting a value, that property or item is skipped, leaving a hole in
// the case of arrays.
+ // TODO(dcheng): This should just take a const reference.
virtual v8::Local<v8::Value> ToV8Value(
const base::Value* value,
v8::Local<v8::Context> context) const = 0;
@@ -118,8 +122,9 @@ class CONTENT_EXPORT V8ValueConverter {
// Likewise, if an object throws while converting a property it will not be
// converted, whereas if an array throws while converting an item it will be
// converted to Value(TYPE_NULL).
- virtual base::Value* FromV8Value(v8::Local<v8::Value> value,
- v8::Local<v8::Context> context) const = 0;
+ virtual std::unique_ptr<base::Value> FromV8Value(
+ v8::Local<v8::Value> value,
+ v8::Local<v8::Context> context) const = 0;
};
} // namespace content
diff --git a/chromium/content/public/common/BUILD.gn b/chromium/content/public/common/BUILD.gn
index a3c06bcadd7..9432838d266 100644
--- a/chromium/content/public/common/BUILD.gn
+++ b/chromium/content/public/common/BUILD.gn
@@ -96,12 +96,12 @@ source_set("common_sources") {
"//content/common",
"//mojo/public/cpp/bindings",
"//services/shell/public/interfaces",
+ "//third_party/WebKit/public:blink_headers",
"//ui/accessibility",
"//url/ipc:url_ipc",
]
deps = [
"//ipc",
- "//ipc/mojo",
"//media",
"//mojo/common",
"//net",
@@ -109,7 +109,6 @@ source_set("common_sources") {
"//services/shell/public/cpp",
"//skia",
"//storage/common",
- "//third_party/WebKit/public:blink_headers",
"//third_party/icu",
"//ui/accessibility",
"//ui/base",
diff --git a/chromium/content/public/common/OWNERS b/chromium/content/public/common/OWNERS
index 14a5a142980..d278610bb73 100644
--- a/chromium/content/public/common/OWNERS
+++ b/chromium/content/public/common/OWNERS
@@ -1,20 +1,8 @@
-per-file *param_traits*.*=set noparent
-per-file *param_traits*.*=dcheng@chromium.org
-per-file *param_traits*.*=inferno@chromium.org
-per-file *param_traits*.*=jln@chromium.org
-per-file *param_traits*.*=jschuh@chromium.org
-per-file *param_traits*.*=kenrb@chromium.org
-per-file *param_traits*.*=mkwst@chromium.org
-per-file *param_traits*.*=nasko@chromium.org
-per-file *param_traits*.*=palmer@chromium.org
-per-file *param_traits*.*=tsepez@chromium.org
-per-file *param_traits*.*=wfh@chromium.org
+per-file *_param_traits*.*=set noparent
+per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
# DirectWrite
per-file dwrite_font_platform_win.h=scottmg@chromium.org
-# Changes to Mojo interfaces require a security review to avoid
-# introducing new sandbox escapes.
per-file *.mojom=set noparent
-per-file *.mojom=palmer@chromium.org
-per-file *.mojom=tsepez@chromium.org
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/public/common/child_process_host.h b/chromium/content/public/common/child_process_host.h
index 9975faf762b..7fbac4c8f6f 100644
--- a/chromium/content/public/common/child_process_host.h
+++ b/chromium/content/public/common/child_process_host.h
@@ -81,6 +81,10 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Sender {
// empty string otherwise
virtual std::string CreateChannel() = 0;
+ // Creates the IPC channel on top of Mojo. Returns the Mojo channel token if
+ // succeeded, or an empty string on failure.
+ virtual std::string CreateChannelMojo(const std::string& child_token) = 0;
+
// Returns true iff the IPC channel is currently being opened;
virtual bool IsChannelOpening() = 0;
diff --git a/chromium/content/public/common/common_param_traits_macros.h b/chromium/content/public/common/common_param_traits_macros.h
index 3a1b8fbe997..da2c4d1db66 100644
--- a/chromium/content/public/common/common_param_traits_macros.h
+++ b/chromium/content/public/common/common_param_traits_macros.h
@@ -10,7 +10,6 @@
#include "build/build_config.h"
#include "content/public/common/console_message_level.h"
-#include "content/public/common/mhtml_generation_params.h"
#include "content/public/common/referrer.h"
#include "content/public/common/security_style.h"
#include "content/public/common/ssl_status.h"
@@ -24,6 +23,7 @@
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
+#include "third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h"
#include "third_party/WebKit/public/web/WebWindowFeatures.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_update.h"
@@ -44,10 +44,10 @@ IPC_ENUM_TRAITS_MAX_VALUE(net::NetworkChangeNotifier::ConnectionType,
net::NetworkChangeNotifier::CONNECTION_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(content::ConsoleMessageLevel,
content::CONSOLE_MESSAGE_LEVEL_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(content::MHTMLCacheControlPolicy,
- content::MHTMLCacheControlPolicy::LAST)
IPC_ENUM_TRAITS_MAX_VALUE(content::SecurityStyle,
content::SECURITY_STYLE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebFrameSerializerCacheControlPolicy,
+ blink::WebFrameSerializerCacheControlPolicy::Last)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebReferrerPolicy,
blink::WebReferrerPolicyLast)
IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::PermissionStatus,
@@ -59,6 +59,10 @@ IPC_ENUM_TRAITS_MAX_VALUE(WindowOpenDisposition,
IPC_ENUM_TRAITS_MAX_VALUE(net::RequestPriority, net::MAXIMUM_PRIORITY)
IPC_ENUM_TRAITS_MAX_VALUE(content::V8CacheOptions,
content::V8_CACHE_OPTIONS_LAST)
+#if defined(OS_ANDROID)
+IPC_ENUM_TRAITS_MAX_VALUE(content::ProgressBarCompletion,
+ content::ProgressBarCompletion::LAST)
+#endif
IPC_ENUM_TRAITS_MIN_MAX_VALUE(ui::PointerType,
ui::POINTER_TYPE_FIRST,
ui::POINTER_TYPE_LAST)
@@ -203,6 +207,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(supports_multiple_windows)
IPC_STRUCT_TRAITS_MEMBER(viewport_enabled)
IPC_STRUCT_TRAITS_MEMBER(viewport_meta_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(shrinks_viewport_contents_to_fit)
IPC_STRUCT_TRAITS_MEMBER(viewport_style)
IPC_STRUCT_TRAITS_MEMBER(main_frame_resizes_are_orientation_changes)
IPC_STRUCT_TRAITS_MEMBER(initialize_at_minimum_page_scale)
@@ -237,6 +242,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(ignore_main_frame_overflow_hidden_quirk)
IPC_STRUCT_TRAITS_MEMBER(report_screen_size_in_physical_pixels_quirk)
IPC_STRUCT_TRAITS_MEMBER(resue_global_for_unowned_main_frame)
+ IPC_STRUCT_TRAITS_MEMBER(autoplay_muted_videos_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(progress_bar_completion)
#endif
IPC_STRUCT_TRAITS_MEMBER(autoplay_experiment_mode)
IPC_STRUCT_TRAITS_MEMBER(default_minimum_page_scale_factor)
diff --git a/chromium/content/public/common/content_client.cc b/chromium/content/public/common/content_client.cc
index 43463d54809..43cede30c6a 100644
--- a/chromium/content/public/common/content_client.cc
+++ b/chromium/content/public/common/content_client.cc
@@ -92,9 +92,9 @@ base::StringPiece ContentClient::GetDataResource(
return base::StringPiece();
}
-base::RefCountedStaticMemory* ContentClient::GetDataResourceBytes(
+base::RefCountedMemory* ContentClient::GetDataResourceBytes(
int resource_id) const {
- return NULL;
+ return nullptr;
}
gfx::Image& ContentClient::GetNativeImageNamed(int resource_id) const {
@@ -119,8 +119,13 @@ bool ContentClient::IsSupplementarySiteIsolationModeEnabled() {
return false;
}
-base::StringPiece ContentClient::GetOriginTrialPublicKey() {
- return base::StringPiece();
+OriginTrialPolicy* ContentClient::GetOriginTrialPolicy() {
+ return nullptr;
+}
+
+bool ContentClient::AllowScriptExtensionForServiceWorker(
+ const GURL& script_url) {
+ return false;
}
#if defined(OS_ANDROID)
diff --git a/chromium/content/public/common/content_client.h b/chromium/content/public/common/content_client.h
index dace907b95e..5141bf8c153 100644
--- a/chromium/content/public/common/content_client.h
+++ b/chromium/content/public/common/content_client.h
@@ -19,7 +19,7 @@
class GURL;
namespace base {
-class RefCountedStaticMemory;
+class RefCountedMemory;
}
namespace IPC {
@@ -49,6 +49,7 @@ class ContentClient;
class ContentGpuClient;
class ContentRendererClient;
class ContentUtilityClient;
+class OriginTrialPolicy;
struct CdmInfo;
struct PepperPluginInfo;
@@ -123,7 +124,7 @@ class CONTENT_EXPORT ContentClient {
ui::ScaleFactor scale_factor) const;
// Returns the raw bytes of a scale independent data resource.
- virtual base::RefCountedStaticMemory* GetDataResourceBytes(
+ virtual base::RefCountedMemory* GetDataResourceBytes(
int resource_id) const;
// Returns a native image given its id.
@@ -157,6 +158,10 @@ class CONTENT_EXPORT ContentClient {
// trustworthy schemes should be added.
virtual void AddServiceWorkerSchemes(std::set<std::string>* schemes) {}
+ // Returns whether or not V8 script extensions should be allowed for a
+ // service worker.
+ virtual bool AllowScriptExtensionForServiceWorker(const GURL& script_url);
+
// Returns true if the embedder wishes to supplement the site isolation policy
// used by the content layer. Returning true enables the infrastructure for
// out-of-process iframes, and causes the content layer to consult
@@ -164,9 +169,9 @@ class CONTENT_EXPORT ContentClient {
// model decisions.
virtual bool IsSupplementarySiteIsolationModeEnabled();
- // Returns the public key to be used for origin trials, or an empty string if
- // origin trials are not enabled in this context.
- virtual base::StringPiece GetOriginTrialPublicKey();
+ // Returns the origin trial policy, or nullptr if origin trials are not
+ // supported by the embedder.
+ virtual OriginTrialPolicy* GetOriginTrialPolicy();
#if defined(OS_ANDROID)
// Returns true for clients like Android WebView that uses synchronous
diff --git a/chromium/content/public/common/content_descriptors.h b/chromium/content/public/common/content_descriptors.h
index ff282ae4be2..fa67a0fc994 100644
--- a/chromium/content/public/common/content_descriptors.h
+++ b/chromium/content/public/common/content_descriptors.h
@@ -16,13 +16,11 @@ enum {
kMojoIPCChannel,
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
+ kV8NativesDataDescriptor,
#if defined(OS_ANDROID)
- kV8NativesDataDescriptor32,
kV8SnapshotDataDescriptor32,
- kV8NativesDataDescriptor64,
kV8SnapshotDataDescriptor64,
#else
- kV8NativesDataDescriptor,
kV8SnapshotDataDescriptor,
#endif
#endif
diff --git a/chromium/content/public/common/content_features.cc b/chromium/content/public/common/content_features.cc
index 39eb2b8c177..b7b005b8f45 100644
--- a/chromium/content/public/common/content_features.cc
+++ b/chromium/content/public/common/content_features.cc
@@ -14,6 +14,11 @@ namespace features {
const base::Feature kBrotliEncoding{"brotli-encoding",
base::FEATURE_ENABLED_BY_DEFAULT};
+// If Canvas2D Image Chromium is allowed, this feature controls whether it is
+// enabled.
+const base::Feature kCanvas2DImageChromium{"Canvas2DImageChromium",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// Enables the credential management API:
// https://w3c.github.io/webappsec-credential-management/
const base::Feature kCredentialManagementAPI{"CredentialManagementAPI",
@@ -24,10 +29,9 @@ const base::Feature kCredentialManagementAPI{"CredentialManagementAPI",
const base::Feature kDefaultEnableGpuRasterization{
"DefaultEnableGpuRasterization", base::FEATURE_DISABLED_BY_DEFAULT};
-// Downloads resumption will be controllable via a flag until it's enabled
-// permanently. See https://crbug.com/7648
-const base::Feature kDownloadResumption{"DownloadResumption",
- base::FEATURE_ENABLED_BY_DEFAULT};
+// Do not call SharedBuffer::unlock() (https://crbug.com/603791).
+const base::Feature kDoNotUnlockSharedBuffer{"DoNotUnlockSharedBuffer",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Speculatively pre-evaluate Javascript which will likely use document.write to
// load an external script. The feature extracts the written markup and sends it
@@ -35,6 +39,11 @@ const base::Feature kDownloadResumption{"DownloadResumption",
const base::Feature kDocumentWriteEvaluator{"DocumentWriteEvaluator",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables a blink::FontCache optimization that reuses a font to serve different
+// size of font.
+const base::Feature kFontCacheScaling{"FontCacheScaling",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Can main thread be pipelined with activation. Always disabled for devices
// with fewer than 4 cores irrespective of this flag. Can also be overridden by
// --enable(disable)-main-frame-before-activation command line flag.
@@ -79,6 +88,10 @@ const base::Feature kOriginTrials{"OriginTrials",
const base::Feature kPaintOptimizations{"PaintOptimizations",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Whether the lookahead parser in Blink runs on the main thread.
+const base::Feature kParseHTMLOnMainThread{"ParseHTMLOnMainThread",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Partial support for pointer event feature.
const base::Feature kPointerEvents{"PointerEvent",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -102,9 +115,14 @@ const base::Feature kStaleWhileRevalidate{"StaleWhileRevalidate2",
const base::Feature kTokenBinding{"token-binding",
base::FEATURE_DISABLED_BY_DEFAULT};
-// An experimental User Agent Intervention on WebFonts loading.
-const base::Feature kWebFontsInterventionV2{"WebFontsInterventionV2",
- base::FEATURE_DISABLED_BY_DEFAULT};
+// Weak MemoryCache (https://crbug.com/603462).
+const base::Feature kWeakMemoryCache{"WeakMemoryCache",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// If WebGL Image Chromium is allowed, this feature controls whether it is
+// enabled.
+const base::Feature kWebGLImageChromium{"WebGLImageChromium",
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Makes WebRTC use ECDSA certs by default (i.e., when no cert type was
// specified in JS).
@@ -116,6 +134,10 @@ const base::Feature kWebRtcEcdsaDefault {"WebRTC-EnableWebRtcEcdsa",
const base::Feature kWebUsb{"WebUSB", base::FEATURE_ENABLED_BY_DEFAULT};
#if defined(OS_ANDROID)
+// Allow videos to autoplay without a user gesture if muted.
+const base::Feature kAutoplayMutedVideos{"AutoplayMutedVideos",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// Use IME's own thread instead of using main UI thread. It also means that
// we will not use replica editor and do a round trip to renderer to synchronize
// with Blink data.
@@ -124,6 +146,18 @@ const base::Feature kImeThread{"ImeThread", base::FEATURE_DISABLED_BY_DEFAULT};
// FeatureList definition for the Seccomp field trial.
const base::Feature kSeccompSandboxAndroid{"SeccompSandboxAndroid",
base::FEATURE_DISABLED_BY_DEFAULT};
+
+// The JavaScript API for payments on the web.
+const base::Feature kWebPayments{"WebPayments",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+#endif
+
+#if defined(OS_WIN)
+// Emergency "off switch" for new Windows sandbox security mitigation,
+// sandbox::MITIGATION_EXTENSION_POINT_DISABLE.
+const base::Feature kWinSboxDisableExtensionPoints{
+ "WinSboxDisableExtensionPoint", base::FEATURE_ENABLED_BY_DEFAULT};
#endif
} // namespace features
diff --git a/chromium/content/public/common/content_features.h b/chromium/content/public/common/content_features.h
index 6b432ea6067..134a1c62dd2 100644
--- a/chromium/content/public/common/content_features.h
+++ b/chromium/content/public/common/content_features.h
@@ -17,10 +17,12 @@ namespace features {
// All features in alphabetical order. The features should be documented
// alongside the definition of their values in the .cc file.
CONTENT_EXPORT extern const base::Feature kBrotliEncoding;
+CONTENT_EXPORT extern const base::Feature kCanvas2DImageChromium;
CONTENT_EXPORT extern const base::Feature kCredentialManagementAPI;
CONTENT_EXPORT extern const base::Feature kDefaultEnableGpuRasterization;
-CONTENT_EXPORT extern const base::Feature kDownloadResumption;
+CONTENT_EXPORT extern const base::Feature kDoNotUnlockSharedBuffer;
CONTENT_EXPORT extern const base::Feature kDocumentWriteEvaluator;
+CONTENT_EXPORT extern const base::Feature kFontCacheScaling;
CONTENT_EXPORT extern const base::Feature kMainFrameBeforeActivation;
CONTENT_EXPORT extern const base::Feature kMediaDocumentDownloadButton;
CONTENT_EXPORT extern const base::Feature kNewMediaPlaybackUi;
@@ -29,20 +31,28 @@ CONTENT_EXPORT extern const base::Feature kNonValidatingReloadOnRefreshContent;
CONTENT_EXPORT extern const base::Feature kOptimizeLoadingIPCForSmallResources;
CONTENT_EXPORT extern const base::Feature kOriginTrials;
CONTENT_EXPORT extern const base::Feature kPaintOptimizations;
+CONTENT_EXPORT extern const base::Feature kParseHTMLOnMainThread;
CONTENT_EXPORT extern const base::Feature kPointerEvents;
CONTENT_EXPORT extern const base::Feature kRenderingPipelineThrottling;
CONTENT_EXPORT extern const base::Feature kScrollAnchoring;
CONTENT_EXPORT extern const base::Feature kStaleWhileRevalidate;
CONTENT_EXPORT extern const base::Feature kTokenBinding;
-CONTENT_EXPORT extern const base::Feature kWebFontsInterventionV2;
+CONTENT_EXPORT extern const base::Feature kWeakMemoryCache;
+CONTENT_EXPORT extern const base::Feature kWebGLImageChromium;
CONTENT_EXPORT extern const base::Feature kWebRtcEcdsaDefault;
CONTENT_EXPORT extern const base::Feature kWebUsb;
#if defined(OS_ANDROID)
+CONTENT_EXPORT extern const base::Feature kAutoplayMutedVideos;
CONTENT_EXPORT extern const base::Feature kImeThread;
CONTENT_EXPORT extern const base::Feature kSeccompSandboxAndroid;
+CONTENT_EXPORT extern const base::Feature kWebPayments;
#endif // defined(OS_ANDROID)
+#if defined(OS_WIN)
+CONTENT_EXPORT extern const base::Feature kWinSboxDisableExtensionPoints;
+#endif // defined(OS_WIN)
+
// DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
// alphabetical order, or in one of the ifdefs (also in order in each section).
diff --git a/chromium/content/public/common/content_switches.cc b/chromium/content/public/common/content_switches.cc
index 244e371a54a..4383bb36f8b 100644
--- a/chromium/content/public/common/content_switches.cc
+++ b/chromium/content/public/common/content_switches.cc
@@ -305,9 +305,6 @@ const char kDisableWebSecurity[] = "disable-web-security";
// Disables Blink's XSSAuditor. The XSSAuditor mitigates reflective XSS.
const char kDisableXSSAuditor[] = "disable-xss-auditor";
-// Disable gesture generation for wheel events.
-const char kDisableWheelGestures[] = "disable-wheel-gestures";
-
// Disable rasterizer that writes directly to GPU memory associated with tiles.
const char kDisableZeroCopy[] = "disable-zero-copy";
@@ -371,6 +368,14 @@ const char kEnableFeatures[] = "enable-features";
// Enable Web Bluetooth.
const char kEnableWebBluetooth[] = "enable-web-bluetooth";
+// WebFonts intervention v2 flag and values.
+const char kEnableWebFontsInterventionV2[] = "enable-webfonts-intervention-v2";
+const char kEnableWebFontsInterventionV2SwitchValueEnabledWith2G[] =
+ "enabled-2g";
+const char kEnableWebFontsInterventionV2SwitchValueEnabledWithSlow2G[] =
+ "enabled-slow2g";
+const char kEnableWebFontsInterventionV2SwitchValueDisabled[] = "disabled";
+
// Makes the GL worker context run asynchronously by using a separate stream.
const char kEnableGpuAsyncWorkerContext[] = "enable-gpu-async-worker-context";
@@ -404,6 +409,9 @@ const char kEnableMemoryBenchmarking[] = "enable-memory-benchmarking";
// Enables the network information API.
const char kEnableNetworkInformation[] = "enable-network-information";
+// Disables the video decoder from drawing to an NV12 textures instead of ARGB.
+const char kDisableNv12DxgiVideo[] = "disable-nv12-dxgi-video";
+
// Enables compositor-accelerated touch-screen pinch gestures.
const char kEnablePinch[] = "enable-pinch";
@@ -508,9 +516,6 @@ const char kEnableWebGLImageChromium[] = "enable-webgl-image-chromium";
// Enables interaction with virtual reality devices.
const char kEnableWebVR[] = "enable-webvr";
-// Enables gesture generation for wheel events.
-const char kEnableWheelGestures[] = "enable-wheel-gestures";
-
// Enable rasterizer that writes directly to GPU memory associated with tiles.
const char kEnableZeroCopy[] = "enable-zero-copy";
@@ -583,9 +588,6 @@ const char kGpuVendorID[] = "gpu-vendor-id";
// These mappings only apply to the host resolver.
const char kHostResolverRules[] = "host-resolver-rules";
-// Ignores certificate-related errors.
-const char kIgnoreCertificateErrors[] = "ignore-certificate-errors";
-
// Ignores GPU blacklist.
const char kIgnoreGpuBlacklist[] = "ignore-gpu-blacklist";
@@ -635,6 +637,13 @@ const char kMaxUntiledLayerWidth[] = "max-untiled-layer-width";
// Renderer.Memory histogram. Used in memory tests.
const char kMemoryMetrics[] = "memory-metrics";
+// Sets options for MHTML generator to skip no-store resources:
+// "skip-nostore-main" - fails to save a page if main frame is 'no-store'
+// "skip-nostore-all" - also skips no-store subresources.
+const char kMHTMLGeneratorOption[] = "mhtml-generator-option";
+const char kMHTMLSkipNostoreMain[] = "skip-nostore-main";
+const char kMHTMLSkipNostoreAll[] = "skip-nostore-all";
+
// Use a Mojo-based LocalStorage implementation.
const char kMojoLocalStorage[] = "mojo-local-storage";
@@ -814,10 +823,6 @@ const char kStartFullscreen[] = "start-fullscreen";
const char kStatsCollectionController[] =
"enable-stats-collection-bindings";
-// Allows for forcing socket connections to http/https to use fixed ports.
-const char kTestingFixedHttpPort[] = "testing-fixed-http-port";
-const char kTestingFixedHttpsPort[] = "testing-fixed-https-port";
-
// Type of the current test harness ("browser" or "ui").
const char kTestType[] = "test-type";
@@ -942,6 +947,10 @@ const char kEnableLongpressDragSelection[] = "enable-longpress-drag-selection";
// The telephony region (ISO country code) to use in phone number detection.
const char kNetworkCountryIso[] = "network-country-iso";
+// When blink should declare a load "done" for the purpose of the
+// progress bar.
+const char kProgressBarCompletion[] = "progress-bar-completion";
+
// Enables remote debug over HTTP on the specified socket name.
const char kRemoteDebuggingSocketName[] = "remote-debugging-socket-name";
@@ -949,12 +958,6 @@ const char kRemoteDebuggingSocketName[] = "remote-debugging-socket-name";
// Java debugger is attached.
const char kRendererWaitForJavaDebugger[] = "renderer-wait-for-java-debugger";
-// Use synchronous input code path for IPC-synchronous compositing. This is the
-// legacy input code path used by the in-process synchronous compositor.
-// Maintaining this code path in case there are compatibility bugs with the
-// standard async input path. Remove tracked as part of crbug.com/545628.
-const char kSyncInputForSyncCompositor[] = "sync-input-for-sync-compositor";
-
// Enables overscrolling for the OSK on Android.
const char kEnableOSKOverscroll[] = "enable-osk-overscroll";
#endif
@@ -1046,6 +1049,15 @@ const char kMemoryPressureThresholdsMb[] = "memory-pressure-thresholds-mb";
const char kTraceExportEventsToETW[] = "trace-export-events-to-etw";
#endif
+#if defined(ENABLE_IPC_FUZZER)
+// Dumps IPC messages sent from renderer processes to the browser process to
+// the given directory. Used primarily to gather samples for IPC fuzzing.
+const char kIpcDumpDirectory[] = "ipc-dump-directory";
+
+// Specifies the testcase used by the IPC fuzzer.
+const char kIpcFuzzerTestcase[] = "ipc-fuzzer-testcase";
+#endif
+
// Don't dump stuff here, follow the same order as the header.
} // namespace switches
diff --git a/chromium/content/public/common/content_switches.h b/chromium/content/public/common/content_switches.h
index be5cc9e4901..75cc46970b5 100644
--- a/chromium/content/public/common/content_switches.h
+++ b/chromium/content/public/common/content_switches.h
@@ -99,7 +99,6 @@ extern const char kDisableV8IdleTasks[];
CONTENT_EXPORT extern const char kDisableWebGLImageChromium[];
CONTENT_EXPORT extern const char kDisableWebSecurity[];
extern const char kDisableXSSAuditor[];
-CONTENT_EXPORT extern const char kDisableWheelGestures[];
CONTENT_EXPORT extern const char kDisableZeroCopy[];
CONTENT_EXPORT extern const char kDomAutomationController[];
CONTENT_EXPORT extern const char kDownloadProcess[];
@@ -115,6 +114,13 @@ CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[];
CONTENT_EXPORT extern const char kEnableFeatures[];
CONTENT_EXPORT extern const char kEnableWasm[];
CONTENT_EXPORT extern const char kEnableWebBluetooth[];
+CONTENT_EXPORT extern const char kEnableWebFontsInterventionV2[];
+CONTENT_EXPORT extern const char
+ kEnableWebFontsInterventionV2SwitchValueEnabledWith2G[];
+CONTENT_EXPORT extern const char
+ kEnableWebFontsInterventionV2SwitchValueEnabledWithSlow2G[];
+CONTENT_EXPORT extern const char
+ kEnableWebFontsInterventionV2SwitchValueDisabled[];
CONTENT_EXPORT extern const char kEnableGpuAsyncWorkerContext[];
CONTENT_EXPORT extern const char kEnableGpuMemoryBufferCompositorResources[];
CONTENT_EXPORT extern const char kEnableGpuMemoryBufferVideoFrames[];
@@ -126,6 +132,7 @@ CONTENT_EXPORT extern const char kEnableLCDText[];
CONTENT_EXPORT extern const char kEnableLogging[];
extern const char kEnableMemoryBenchmarking[];
CONTENT_EXPORT extern const char kEnableNetworkInformation[];
+CONTENT_EXPORT extern const char kDisableNv12DxgiVideo[];
CONTENT_EXPORT extern const char kEnablePinch[];
CONTENT_EXPORT extern const char kEnablePluginPlaceholderTesting[];
CONTENT_EXPORT extern const char kEnablePreciseMemoryInfo[];
@@ -151,7 +158,6 @@ CONTENT_EXPORT extern const char kEnableWebFontsInterventionTrigger[];
CONTENT_EXPORT extern const char kEnableWebGLDraftExtensions[];
CONTENT_EXPORT extern const char kEnableWebGLImageChromium[];
CONTENT_EXPORT extern const char kEnableWebVR[];
-CONTENT_EXPORT extern const char kEnableWheelGestures[];
CONTENT_EXPORT extern const char kEnableZeroCopy[];
CONTENT_EXPORT extern const char kEnableZeroCopyDxgiVideo[];
CONTENT_EXPORT extern const char kExplicitlyAllowedPorts[];
@@ -172,7 +178,6 @@ CONTENT_EXPORT extern const char kGpuSandboxStartEarly[];
CONTENT_EXPORT extern const char kGpuStartupDialog[];
extern const char kGpuVendorID[];
CONTENT_EXPORT extern const char kHostResolverRules[];
-CONTENT_EXPORT extern const char kIgnoreCertificateErrors[];
CONTENT_EXPORT extern const char kIgnoreGpuBlacklist[];
CONTENT_EXPORT extern const char kInertVisualViewport[];
CONTENT_EXPORT extern const char kInProcessGPU[];
@@ -186,6 +191,9 @@ CONTENT_EXPORT extern const char kMainFrameResizesAreOrientationChanges[];
extern const char kMaxUntiledLayerHeight[];
extern const char kMaxUntiledLayerWidth[];
extern const char kMemoryMetrics[];
+CONTENT_EXPORT extern const char kMHTMLGeneratorOption[];
+CONTENT_EXPORT extern const char kMHTMLSkipNostoreMain[];
+CONTENT_EXPORT extern const char kMHTMLSkipNostoreAll[];
CONTENT_EXPORT extern const char kMojoLocalStorage[];
CONTENT_EXPORT extern const char kMuteAudio[];
CONTENT_EXPORT extern const char kNoReferrers[];
@@ -223,8 +231,6 @@ CONTENT_EXPORT extern const char kSkipGpuDataLoading[];
extern const char kSkipReencodingOnSKPCapture[];
CONTENT_EXPORT extern const char kStartFullscreen[];
CONTENT_EXPORT extern const char kStatsCollectionController[];
-CONTENT_EXPORT extern const char kTestingFixedHttpPort[];
-CONTENT_EXPORT extern const char kTestingFixedHttpsPort[];
CONTENT_EXPORT extern const char kTestType[];
CONTENT_EXPORT extern const char kTopDocumentIsolation[];
CONTENT_EXPORT extern const char kTouchTextSelectionStrategy[];
@@ -270,9 +276,9 @@ CONTENT_EXPORT extern const char kEnableAdaptiveSelectionHandleOrientation[];
CONTENT_EXPORT extern const char kEnableLongpressDragSelection[];
CONTENT_EXPORT extern const char kHideScrollbars[];
extern const char kNetworkCountryIso[];
+CONTENT_EXPORT extern const char kProgressBarCompletion[];
CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[];
-CONTENT_EXPORT extern const char kSyncInputForSyncCompositor[];
CONTENT_EXPORT extern const char kEnableOSKOverscroll[];
#endif
@@ -305,6 +311,11 @@ CONTENT_EXPORT extern const char kMemoryPressureThresholdsMb[];
CONTENT_EXPORT extern const char kTraceExportEventsToETW[];
#endif
+#if defined(ENABLE_IPC_FUZZER)
+extern const char kIpcDumpDirectory[];
+extern const char kIpcFuzzerTestcase[];
+#endif
+
// DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
// alphabetical order, or in one of the ifdefs (also in order in each section).
diff --git a/chromium/content/public/common/drop_data.cc b/chromium/content/public/common/drop_data.cc
index c8a24c85bab..ef881ccfa45 100644
--- a/chromium/content/public/common/drop_data.cc
+++ b/chromium/content/public/common/drop_data.cc
@@ -16,4 +16,38 @@ DropData::DropData(const DropData& other) = default;
DropData::~DropData() {
}
+DropData::Metadata::Metadata() {}
+
+// static
+DropData::Metadata DropData::Metadata::CreateForMimeType(
+ const Kind& kind,
+ const base::string16& mime_type) {
+ Metadata metadata;
+ metadata.kind = kind;
+ metadata.mime_type = mime_type;
+ return metadata;
+}
+
+// static
+DropData::Metadata DropData::Metadata::CreateForFilePath(
+ const base::FilePath& filename) {
+ Metadata metadata;
+ metadata.kind = Kind::FILENAME;
+ metadata.filename = filename;
+ return metadata;
+}
+
+// static
+DropData::Metadata DropData::Metadata::CreateForFileSystemUrl(
+ const GURL& file_system_url) {
+ Metadata metadata;
+ metadata.kind = Kind::FILESYSTEMFILE;
+ metadata.file_system_url = file_system_url;
+ return metadata;
+}
+
+DropData::Metadata::Metadata(const DropData::Metadata& other) = default;
+
+DropData::Metadata::~Metadata() {}
+
} // namespace content
diff --git a/chromium/content/public/common/drop_data.h b/chromium/content/public/common/drop_data.h
index 53a76de75a1..f131b814558 100644
--- a/chromium/content/public/common/drop_data.h
+++ b/chromium/content/public/common/drop_data.h
@@ -17,6 +17,7 @@
#include "base/strings/nullable_string16.h"
#include "content/common/content_export.h"
+#include "ipc/ipc_message.h"
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
#include "ui/base/dragdrop/file_info.h"
#include "url/gurl.h"
@@ -32,10 +33,34 @@ struct CONTENT_EXPORT DropData {
int64_t size;
};
+ enum class Kind {
+ STRING = 0,
+ FILENAME,
+ FILESYSTEMFILE,
+ LAST = FILESYSTEMFILE
+ };
+
+ struct Metadata {
+ Metadata();
+ static Metadata CreateForMimeType(const Kind& kind,
+ const base::string16& mime_type);
+ static Metadata CreateForFilePath(const base::FilePath& filename);
+ static Metadata CreateForFileSystemUrl(const GURL& file_system_url);
+ Metadata(const Metadata& other);
+ ~Metadata();
+
+ Kind kind;
+ base::string16 mime_type;
+ base::FilePath filename;
+ GURL file_system_url;
+ };
+
DropData();
DropData(const DropData& other);
~DropData();
+ int view_id = MSG_ROUTING_NONE;
+
// Whether this drag originated from a renderer.
bool did_originate_from_renderer;
@@ -54,6 +79,8 @@ struct CONTENT_EXPORT DropData {
// populated if the drag is not renderer tainted, as this allows File access
// from web content.
std::vector<ui::FileInfo> filenames;
+ // The mime types of dragged files.
+ std::vector<base::string16> file_mime_types;
// Isolated filesystem ID for the files being dragged on the webview.
base::string16 filesystem_id;
diff --git a/chromium/content/public/common/manifest.cc b/chromium/content/public/common/manifest.cc
index 86a6d41d4c3..cde3498f1b8 100644
--- a/chromium/content/public/common/manifest.cc
+++ b/chromium/content/public/common/manifest.cc
@@ -51,7 +51,8 @@ bool Manifest::IsEmpty() const {
!prefer_related_applications &&
theme_color == Manifest::kInvalidOrMissingColor &&
background_color == Manifest::kInvalidOrMissingColor &&
- gcm_sender_id.is_null();
+ gcm_sender_id.is_null() &&
+ scope.is_empty();
}
} // namespace content
diff --git a/chromium/content/public/common/manifest.h b/chromium/content/public/common/manifest.h
index df693f7cb6c..2fba5d4e605 100644
--- a/chromium/content/public/common/manifest.h
+++ b/chromium/content/public/common/manifest.h
@@ -123,6 +123,9 @@ struct CONTENT_EXPORT Manifest {
// Null if parsing failed or the field was not present.
base::NullableString16 gcm_sender_id;
+ // Empty if the parsing failed or the field was not present.
+ GURL scope;
+
// Maximum length for all the strings inside the Manifest when it is sent over
// IPC. The renderer process should truncate the strings before sending the
// Manifest and the browser process must do the same when receiving it.
diff --git a/chromium/content/public/common/mhtml_generation_params.cc b/chromium/content/public/common/mhtml_generation_params.cc
index f5011aadae8..8d48664fdae 100644
--- a/chromium/content/public/common/mhtml_generation_params.cc
+++ b/chromium/content/public/common/mhtml_generation_params.cc
@@ -4,11 +4,27 @@
#include "content/public/common/mhtml_generation_params.h"
+#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "content/public/common/content_switches.h"
namespace content {
MHTMLGenerationParams::MHTMLGenerationParams(const base::FilePath& file_path)
- : file_path(file_path) {}
+ : file_path(file_path) {
+ // Check which variant of MHTML generation is required.
+ std::string mhtmlGeneratorOptionFlag =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kMHTMLGeneratorOption);
+ if (mhtmlGeneratorOptionFlag == switches::kMHTMLSkipNostoreMain) {
+ cache_control_policy =
+ blink::WebFrameSerializerCacheControlPolicy::
+ FailForNoStoreMainFrame;
+ } else if (mhtmlGeneratorOptionFlag == switches::kMHTMLSkipNostoreAll) {
+ cache_control_policy =
+ blink::WebFrameSerializerCacheControlPolicy::
+ SkipAnyFrameOrResourceMarkedNoStore;
+ }
+}
} // namespace content
diff --git a/chromium/content/public/common/mhtml_generation_params.h b/chromium/content/public/common/mhtml_generation_params.h
index c61879f0f18..32825e49ddc 100644
--- a/chromium/content/public/common/mhtml_generation_params.h
+++ b/chromium/content/public/common/mhtml_generation_params.h
@@ -7,21 +7,10 @@
#include "base/files/file_path.h"
#include "content/common/content_export.h"
+#include "third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h"
namespace content {
-// Options for changing serialization behavior based on the CacheControl header
-// of each subresource.
-enum class MHTMLCacheControlPolicy {
- NONE = 0,
- FAIL_FOR_NO_STORE_MAIN_FRAME,
-
- // |LAST| is used in content/public/common/common_param_traits_macros.h with
- // IPC_ENUM_TRAITS_MAX_VALUE macro. Keep the value up to date. Otherwise
- // a new value can not be passed to the renderer.
- LAST = FAIL_FOR_NO_STORE_MAIN_FRAME
-};
-
struct CONTENT_EXPORT MHTMLGenerationParams {
MHTMLGenerationParams(const base::FilePath& file_path);
~MHTMLGenerationParams() = default;
@@ -37,7 +26,8 @@ struct CONTENT_EXPORT MHTMLGenerationParams {
// By default, MHTML includes all subresources. This flag can be used to
// cause the generator to fail or silently ignore resources if the
// Cache-Control header is used.
- MHTMLCacheControlPolicy cache_control_policy = MHTMLCacheControlPolicy::NONE;
+ blink::WebFrameSerializerCacheControlPolicy cache_control_policy =
+ blink::WebFrameSerializerCacheControlPolicy::None;
};
} // namespace content
diff --git a/chromium/content/public/common/mojo_channel_switches.cc b/chromium/content/public/common/mojo_channel_switches.cc
index d1ed7b89bf7..dd3d86cfde6 100644
--- a/chromium/content/public/common/mojo_channel_switches.cc
+++ b/chromium/content/public/common/mojo_channel_switches.cc
@@ -4,8 +4,6 @@
#include "content/public/common/mojo_channel_switches.h"
-#include "ipc/mojo/ipc_channel_mojo.h"
-
namespace switches {
// The token to use to construct the message pipe on which to layer ChannelMojo.
diff --git a/chromium/content/public/common/mojo_shell_connection.h b/chromium/content/public/common/mojo_shell_connection.h
index fc5e47a6bbb..1fbe2439a4a 100644
--- a/chromium/content/public/common/mojo_shell_connection.h
+++ b/chromium/content/public/common/mojo_shell_connection.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// 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.
@@ -9,75 +9,96 @@
#include "base/callback_forward.h"
#include "content/common/content_export.h"
+#include "content/public/common/mojo_application_info.h"
#include "services/shell/public/cpp/identity.h"
#include "services/shell/public/interfaces/shell_client.mojom.h"
namespace shell {
class Connection;
class Connector;
+class ShellConnection;
}
namespace content {
-// Encapsulates a connection to a spawning external Mojo shell.
-// Access an instance by calling Get(), on the thread the Shell connection is
-// bound. Clients can implement Listener, which allows them to register services
-// to expose to inbound connections. Clients should call this any time after
-// the main message loop is created but not yet run (e.g. in the browser process
-// this object is created in PreMainMessageLoopRun(), so the BrowserMainParts
-// impl can access this in its implementation of that same method.
+// Encapsulates a connection to a //services/shell.
+// Access a global instance on the thread the ShellConnection was bound by
+// calling Holder::Get().
+// Clients can add shell::ShellClient implementations whose exposed interfaces
+// will be exposed to inbound connections to this object's ShellClient.
+// Alternatively clients can define named services that will be constructed when
+// requests for those service names are received.
+// Clients must call any of the registration methods when receiving
+// ContentBrowserClient::RegisterInProcessMojoApplications().
class CONTENT_EXPORT MojoShellConnection {
public:
- // Override to add additional services to inbound connections.
- // TODO(beng): This should just be ShellClient.
- class Listener {
- public:
- virtual bool AcceptConnection(shell::Connection* connection) = 0;
+ using ShellClientRequestHandler =
+ base::Callback<void(shell::mojom::ShellClientRequest)>;
+ using Factory = base::Callback<std::unique_ptr<MojoShellConnection>(void)>;
- virtual ~Listener() {}
- };
+ // Stores an instance of |connection| in TLS for the current process. Must be
+ // called on the thread the connection was created on.
+ static void SetForProcess(std::unique_ptr<MojoShellConnection> connection);
+
+ // Returns the per-process instance, or nullptr if the Shell connection has
+ // not yet been bound. Must be called on the thread the connection was created
+ // on.
+ static MojoShellConnection* GetForProcess();
+
+ // Destroys the per-process instance. Must be called on the thread the
+ // connection was created on.
+ static void DestroyForProcess();
+
+ virtual ~MojoShellConnection();
- using Factory = base::Closure;
// Sets the factory used to create the MojoShellConnection. This must be
// called before the MojoShellConnection has been created.
static void SetFactoryForTest(Factory* factory);
- // Will return null if no connection has been established (either because it
- // hasn't happened yet or the application was not spawned from the external
- // Mojo shell.
- static MojoShellConnection* Get();
+ // Creates a MojoShellConnection from |request|.
+ static std::unique_ptr<MojoShellConnection> Create(
+ shell::mojom::ShellClientRequest request);
- // Destroys the connection. Must be called on the thread the connection was
- // created on.
- static void Destroy();
-
- // Creates the appropriate MojoShellConnection from |request|. See
- // UsingExternalShell() for details of |is_external|.
- static void Create(shell::mojom::ShellClientRequest request,
- bool is_external);
+ // Returns the bound shell::ShellConnection object.
+ // TODO(rockot): remove.
+ virtual shell::ShellConnection* GetShellConnection() = 0;
+ // Returns the shell::Connector received via this connection's ShellClient
+ // implementation. Use this to initiate connections as this object's Identity.
virtual shell::Connector* GetConnector() = 0;
+ // Returns this connection's identity with the shell. Connections initiated
+ // via the shell::Connector returned by GetConnector() will use this.
virtual const shell::Identity& GetIdentity() const = 0;
- // Indicates whether the shell connection is to an external shell (true) or
- // a shell embedded in the browser process (false).
- virtual bool UsingExternalShell() const = 0;
-
// Sets a closure that is called when the connection is lost. Note that
// connection may already have been closed, in which case |closure| will be
// run immediately before returning from this function.
virtual void SetConnectionLostClosure(const base::Closure& closure) = 0;
- // [De]Register an impl of Listener that will be consulted when the wrapped
- // ShellConnection exposes services to inbound connections.
- // Registered listeners are owned by this MojoShellConnection. If a listener
- // is removed, then the ownership is transferred back to the caller.
- virtual void AddListener(std::unique_ptr<Listener> listener) = 0;
- virtual std::unique_ptr<Listener> RemoveListener(Listener* listener) = 0;
-
- protected:
- virtual ~MojoShellConnection();
+ // Allows the caller to expose interfaces to the caller using the identity of
+ // this object's ShellClient. As distinct from AddEmbeddedService() and
+ // AddShellClientRequestHandler() which specify unique identities for the
+ // registered services.
+ virtual void AddEmbeddedShellClient(
+ std::unique_ptr<shell::ShellClient> shell_client) = 0;
+ virtual void AddEmbeddedShellClient(shell::ShellClient* shell_client) = 0;
+
+ // Adds an embedded service to this connection's ShellClientFactory.
+ // |info| provides details on how to construct new instances of the
+ // service when an incoming connection is made to |name|.
+ virtual void AddEmbeddedService(const std::string& name,
+ const MojoApplicationInfo& info) = 0;
+
+ // Adds a generic ShellClientRequestHandler for a given service name. This
+ // will be used to satisfy any incoming calls to CreateShellClient() which
+ // reference the given name.
+ //
+ // For in-process services, it is preferable to use |AddEmbeddedService()| as
+ // defined above.
+ virtual void AddShellClientRequestHandler(
+ const std::string& name,
+ const ShellClientRequestHandler& handler) = 0;
};
} // namespace content
diff --git a/chromium/content/public/common/origin_trial_policy.h b/chromium/content/public/common/origin_trial_policy.h
new file mode 100644
index 00000000000..69f93a532d7
--- /dev/null
+++ b/chromium/content/public/common/origin_trial_policy.h
@@ -0,0 +1,24 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_COMMON_ORIGIN_TRIAL_POLICY_H_
+#define CONTENT_PUBLIC_COMMON_ORIGIN_TRIAL_POLICY_H_
+
+#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class CONTENT_EXPORT OriginTrialPolicy {
+ public:
+ virtual ~OriginTrialPolicy() = default;
+
+ virtual void Initialize() {}
+ virtual base::StringPiece GetPublicKey() const = 0;
+ virtual bool IsFeatureDisabled(base::StringPiece feature) const = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_ORIGIN_TRIAL_POLICY_H_
diff --git a/chromium/content/public/common/page_state.cc b/chromium/content/public/common/page_state.cc
index 01240db9859..b082d54c91d 100644
--- a/chromium/content/public/common/page_state.cc
+++ b/chromium/content/public/common/page_state.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "base/files/file_path.h"
+#include "base/strings/nullable_string16.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/page_state_serialization.h"
@@ -84,20 +85,20 @@ PageState PageState::CreateForTesting(
state.top.url_string = ToNullableString16(url.possibly_invalid_spec());
if (optional_body_data || optional_body_file_path) {
- state.top.http_body.is_null = false;
if (optional_body_data) {
- ExplodedHttpBodyElement element;
- element.type = blink::WebHTTPBody::Element::TypeData;
- element.data = optional_body_data;
- state.top.http_body.elements.push_back(element);
+ std::string body_data(optional_body_data);
+ state.top.http_body.request_body = new ResourceRequestBodyImpl();
+ state.top.http_body.request_body->AppendBytes(body_data.data(),
+ body_data.size());
}
if (optional_body_file_path) {
- ExplodedHttpBodyElement element;
- element.type = blink::WebHTTPBody::Element::TypeFile;
- element.file_path =
- ToNullableString16(optional_body_file_path->AsUTF8Unsafe());
- state.top.http_body.elements.push_back(element);
- state.referenced_files.push_back(element.file_path);
+ state.top.http_body.request_body = new ResourceRequestBodyImpl();
+ state.top.http_body.request_body->AppendFileRange(
+ *optional_body_file_path,
+ 0, std::numeric_limits<uint64_t>::max(),
+ base::Time());
+ state.referenced_files.push_back(base::NullableString16(
+ optional_body_file_path->AsUTF16Unsafe(), false));
}
state.top.http_body.contains_passwords =
body_contains_password_data;
diff --git a/chromium/content/public/common/resource_request_body.cc b/chromium/content/public/common/resource_request_body.cc
new file mode 100644
index 00000000000..e273b9e2a4f
--- /dev/null
+++ b/chromium/content/public/common/resource_request_body.cc
@@ -0,0 +1,43 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/common/resource_request_body.h"
+
+#include "content/common/resource_request_body_impl.h"
+
+#if defined(OS_ANDROID)
+#include "content/common/android/resource_request_body_android.h"
+#endif
+
+namespace content {
+
+ResourceRequestBody::ResourceRequestBody() {}
+
+ResourceRequestBody::~ResourceRequestBody() {}
+
+// static
+scoped_refptr<ResourceRequestBody> ResourceRequestBody::CreateFromBytes(
+ const char* bytes,
+ size_t length) {
+ scoped_refptr<ResourceRequestBodyImpl> result = new ResourceRequestBodyImpl();
+ result->AppendBytes(bytes, length);
+ return result;
+}
+
+#if defined(OS_ANDROID)
+base::android::ScopedJavaLocalRef<jobject> ResourceRequestBody::ToJavaObject(
+ JNIEnv* env) {
+ return ConvertResourceRequestBodyToJavaObject(
+ env, static_cast<ResourceRequestBodyImpl*>(this));
+}
+
+// static
+scoped_refptr<ResourceRequestBody> ResourceRequestBody::FromJavaObject(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& java_object) {
+ return ExtractResourceRequestBodyFromJavaObject(env, java_object);
+}
+#endif
+
+} // namespace content
diff --git a/chromium/content/public/common/resource_request_body.h b/chromium/content/public/common/resource_request_body.h
new file mode 100644
index 00000000000..606c31994c8
--- /dev/null
+++ b/chromium/content/public/common/resource_request_body.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_PUBLIC_COMMON_RESOURCE_REQUEST_BODY_H_
+#define CONTENT_PUBLIC_COMMON_RESOURCE_REQUEST_BODY_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "build/build_config.h"
+#include "content/common/content_export.h"
+
+#if defined(OS_ANDROID)
+#include <jni.h>
+#include "base/android/scoped_java_ref.h"
+#endif
+
+namespace content {
+
+// ResourceRequestBody represents body (i.e. upload data) of a HTTP request.
+//
+// This class is intentionally opaque:
+// *) Embedders cannot inspect the payload of ResourceRequestBody. Only the
+// //content layer can decompose ResourceRequestBody into references to file
+// ranges, byte vectors, blob uris, etc.
+// *) Embedders can get instances of ResourceRequestBody only by
+// - receiving an instance created inside //content layer (e.g. receiving it
+// via content::OpenURLParams),
+// - calling CreateFromBytes with a vector of bytes (e.g. to support
+// Android's WebView::postUrl API, to support DoSearchByImageInNewTab and
+// to support test code).
+// *) Embedders typically end up passing ResourceRequestBody back into the
+// //content layer via content::NavigationController::LoadUrlParams.
+class CONTENT_EXPORT ResourceRequestBody
+ : public base::RefCountedThreadSafe<ResourceRequestBody> {
+ public:
+ // Creates ResourceRequestBody that holds a copy of |bytes|.
+ static scoped_refptr<ResourceRequestBody> CreateFromBytes(const char* bytes,
+ size_t length);
+
+#if defined(OS_ANDROID)
+ // Returns a org.chromium.content_public.common.ResourceRequestBody Java
+ // object that wraps a ref-counted pointer to the |resource_request_body|.
+ base::android::ScopedJavaLocalRef<jobject> ToJavaObject(JNIEnv* env);
+
+ // Extracts and returns a C++ object out of Java's
+ // org.chromium.content_public.common.ResourceRequestBody.
+ static scoped_refptr<ResourceRequestBody> FromJavaObject(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& java_object);
+#endif
+
+ protected:
+ ResourceRequestBody();
+ virtual ~ResourceRequestBody();
+
+ private:
+ friend class base::RefCountedThreadSafe<ResourceRequestBody>;
+ DISALLOW_COPY_AND_ASSIGN(ResourceRequestBody);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_RESOURCE_REQUEST_BODY_H_
diff --git a/chromium/content/public/common/resource_response.cc b/chromium/content/public/common/resource_response.cc
index aed3bc5e267..3633eba892e 100644
--- a/chromium/content/public/common/resource_response.cc
+++ b/chromium/content/public/common/resource_response.cc
@@ -55,6 +55,7 @@ scoped_refptr<ResourceResponse> ResourceResponse::DeepCopy() const {
new_response->head.effective_connection_type = head.effective_connection_type;
new_response->head.signed_certificate_timestamps =
head.signed_certificate_timestamps;
+ new_response->head.cors_exposed_header_names = head.cors_exposed_header_names;
return new_response;
}
diff --git a/chromium/content/public/common/resource_response_info.h b/chromium/content/public/common/resource_response_info.h
index ba38d544b7b..9c004aaf098 100644
--- a/chromium/content/public/common/resource_response_info.h
+++ b/chromium/content/public/common/resource_response_info.h
@@ -157,6 +157,10 @@ struct ResourceResponseInfo {
// validation status. Only present if the renderer process set
// report_raw_headers to true.
net::SignedCertificateTimestampAndStatusList signed_certificate_timestamps;
+
+ // In case this is a CORS response fetched by a ServiceWorker, this is the
+ // set of headers that should be exposed.
+ std::vector<std::string> cors_exposed_header_names;
};
} // namespace content
diff --git a/chromium/content/public/common/service_registry.h b/chromium/content/public/common/service_registry.h
deleted file mode 100644
index e34ed77600d..00000000000
--- a/chromium/content/public/common/service_registry.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_COMMON_SERVICE_REGISTRY_H_
-#define CONTENT_PUBLIC_COMMON_SERVICE_REGISTRY_H_
-
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/strings/string_piece.h"
-#include "content/common/content_export.h"
-#include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/system/core.h"
-#include "services/shell/public/interfaces/interface_provider.mojom.h"
-
-namespace content {
-
-// A ServiceRegistry exposes local services that have been added using
-// AddService to a paired remote ServiceRegistry and provides local access to
-// services exposed by the remote ServiceRegistry through
-// ConnectToRemoteService.
-class CONTENT_EXPORT ServiceRegistry {
- public:
- static ServiceRegistry* Create();
- virtual ~ServiceRegistry() {}
-
- // Binds this ServiceProvider implementation to a message pipe endpoint.
- virtual void Bind(shell::mojom::InterfaceProviderRequest request) = 0;
-
- // Binds to a remote ServiceProvider. This will expose added services to the
- // remote ServiceProvider with the corresponding handle and enable
- // ConnectToRemoteService to provide access to services exposed by the remote
- // ServiceProvider.
- virtual void BindRemoteServiceProvider(
- shell::mojom::InterfaceProviderPtr service_provider) = 0;
-
- // Make the service created by |service_factory| available to the remote
- // ServiceProvider. In response to each request for a service,
- // |service_factory| will be run with an InterfaceRequest<Interface>
- // representing that request. Adding a factory for an already registered
- // service will override the factory. Existing connections to the service are
- // unaffected.
- template <typename Interface>
- void AddService(const base::Callback<void(mojo::InterfaceRequest<Interface>)>&
- service_factory) {
- AddService(Interface::Name_,
- base::Bind(&ServiceRegistry::ForwardToServiceFactory<Interface>,
- service_factory));
- }
- virtual void AddService(
- const std::string& service_name,
- const base::Callback<void(mojo::ScopedMessagePipeHandle)>&
- service_factory) = 0;
-
- // Remove future access to the service implementing Interface. Existing
- // connections to the service are unaffected.
- template <typename Interface>
- void RemoveService() {
- RemoveService(Interface::Name_);
- }
- virtual void RemoveService(const std::string& service_name) = 0;
-
- // Connect to an interface provided by the remote service provider.
- template <typename Interface>
- void ConnectToRemoteService(mojo::InterfaceRequest<Interface> ptr) {
- ConnectToRemoteService(Interface::Name_, ptr.PassMessagePipe());
- }
- virtual void ConnectToRemoteService(base::StringPiece name,
- mojo::ScopedMessagePipeHandle handle) = 0;
-
- // Registers a local service factory to intercept ConnectToRemoteService
- // requests instead of actually connecting to the remote registry. Used only
- // for testing.
- virtual void AddServiceOverrideForTesting(
- const std::string& service_name,
- const base::Callback<void(mojo::ScopedMessagePipeHandle)>&
- service_factory) = 0;
-
- // Removes all local service factories registered
- // by AddServiceOverrideForTesting. Used only for testing.
- virtual void ClearServiceOverridesForTesting() = 0;
-
- private:
- template <typename Interface>
- static void ForwardToServiceFactory(
- const base::Callback<void(mojo::InterfaceRequest<Interface>)>&
- service_factory,
- mojo::ScopedMessagePipeHandle handle) {
- service_factory.Run(mojo::MakeRequest<Interface>(std::move(handle)));
- }
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_SERVICE_REGISTRY_H_
diff --git a/chromium/content/public/common/ssl_status.cc b/chromium/content/public/common/ssl_status.cc
index 8a9fa54226a..709f4188a26 100644
--- a/chromium/content/public/common/ssl_status.cc
+++ b/chromium/content/public/common/ssl_status.cc
@@ -19,7 +19,8 @@ SSLStatus::SSLStatus()
content_status(NORMAL_CONTENT),
num_unknown_scts(0),
num_invalid_scts(0),
- num_valid_scts(0) {}
+ num_valid_scts(0),
+ pkp_bypassed(false) {}
SSLStatus::SSLStatus(SecurityStyle security_style,
int cert_id,
@@ -33,7 +34,8 @@ SSLStatus::SSLStatus(SecurityStyle security_style,
content_status(NORMAL_CONTENT),
num_unknown_scts(0),
num_invalid_scts(0),
- num_valid_scts(0) {
+ num_valid_scts(0),
+ pkp_bypassed(ssl_info.pkp_bypassed) {
// Count unknown, invalid and valid SCTs.
for (const auto& sct_and_status : ssl_info.signed_certificate_timestamps) {
switch (sct_and_status.status) {
diff --git a/chromium/content/public/common/ssl_status.h b/chromium/content/public/common/ssl_status.h
index c0d70c0a3dc..8233da77200 100644
--- a/chromium/content/public/common/ssl_status.h
+++ b/chromium/content/public/common/ssl_status.h
@@ -48,7 +48,8 @@ struct CONTENT_EXPORT SSLStatus {
content_status == status.content_status &&
num_unknown_scts == status.num_unknown_scts &&
num_invalid_scts == status.num_invalid_scts &&
- num_valid_scts == status.num_valid_scts;
+ num_valid_scts == status.num_valid_scts &&
+ pkp_bypassed == status.pkp_bypassed;
}
content::SecurityStyle security_style;
@@ -64,6 +65,8 @@ struct CONTENT_EXPORT SSLStatus {
uint32_t num_unknown_scts;
uint32_t num_invalid_scts;
uint32_t num_valid_scts;
+ // True if PKP was bypassed due to a local trust anchor.
+ bool pkp_bypassed;
};
} // namespace content
diff --git a/chromium/content/public/common/web_preferences.cc b/chromium/content/public/common/web_preferences.cc
index a0bc6f1f265..f0703241c5f 100644
--- a/chromium/content/public/common/web_preferences.cc
+++ b/chromium/content/public/common/web_preferences.cc
@@ -33,6 +33,16 @@ STATIC_ASSERT_ENUM(V8_CACHE_OPTIONS_PARSE, WebSettings::V8CacheOptionsParse);
STATIC_ASSERT_ENUM(V8_CACHE_OPTIONS_CODE, WebSettings::V8CacheOptionsCode);
STATIC_ASSERT_ENUM(V8_CACHE_OPTIONS_LAST, WebSettings::V8CacheOptionsCode);
+STATIC_ASSERT_ENUM(ProgressBarCompletion::LOAD_EVENT,
+ WebSettings::ProgressBarCompletion::LoadEvent);
+STATIC_ASSERT_ENUM(ProgressBarCompletion::RESOURCES_BEFORE_DCL,
+ WebSettings::ProgressBarCompletion::ResourcesBeforeDCL);
+STATIC_ASSERT_ENUM(ProgressBarCompletion::DOM_CONTENT_LOADED,
+ WebSettings::ProgressBarCompletion::DOMContentLoaded);
+STATIC_ASSERT_ENUM(
+ ProgressBarCompletion::RESOURCES_BEFORE_DCL_AND_SAME_ORIGIN_IFRAMES,
+ WebSettings::ProgressBarCompletion::ResourcesBeforeDCLAndSameOriginIFrames);
+
STATIC_ASSERT_ENUM(IMAGE_ANIMATION_POLICY_ALLOWED,
WebSettings::ImageAnimationPolicyAllowed);
STATIC_ASSERT_ENUM(IMAGE_ANIMATION_POLICY_ANIMATION_ONCE,
@@ -147,10 +157,14 @@ WebPreferences::WebPreferences()
viewport_enabled(false),
#if defined(OS_ANDROID)
viewport_meta_enabled(true),
+ shrinks_viewport_contents_to_fit(true),
viewport_style(ViewportStyle::MOBILE),
+ always_show_context_menu_on_touch(false),
#else
viewport_meta_enabled(false),
+ shrinks_viewport_contents_to_fit(false),
viewport_style(ViewportStyle::DEFAULT),
+ always_show_context_menu_on_touch(true),
#endif
main_frame_resizes_are_orientation_changes(false),
initialize_at_minimum_page_scale(true),
@@ -192,6 +206,8 @@ WebPreferences::WebPreferences()
ignore_main_frame_overflow_hidden_quirk(false),
report_screen_size_in_physical_pixels_quirk(false),
resue_global_for_unowned_main_frame(false),
+ autoplay_muted_videos_enabled(false),
+ progress_bar_completion(ProgressBarCompletion::LOAD_EVENT),
#endif
#if defined(OS_ANDROID)
default_minimum_page_scale_factor(0.25f),
diff --git a/chromium/content/public/common/web_preferences.h b/chromium/content/public/common/web_preferences.h
index 54b8ed4acbe..3fb1a79406f 100644
--- a/chromium/content/public/common/web_preferences.h
+++ b/chromium/content/public/common/web_preferences.h
@@ -54,6 +54,17 @@ enum ImageAnimationPolicy {
enum class ViewportStyle { DEFAULT, MOBILE, TELEVISION, LAST = TELEVISION };
+// Controls when the progress bar reports itself as complete. See
+// third_party/WebKit/Source/core/loader/ProgressTracker.cpp for most of its
+// effects.
+enum class ProgressBarCompletion {
+ LOAD_EVENT,
+ RESOURCES_BEFORE_DCL,
+ DOM_CONTENT_LOADED,
+ RESOURCES_BEFORE_DCL_AND_SAME_ORIGIN_IFRAMES,
+ LAST = RESOURCES_BEFORE_DCL_AND_SAME_ORIGIN_IFRAMES
+};
+
// The ISO 15924 script code for undetermined script aka Common. It's the
// default used on WebKit's side to get/set a font setting when no script is
// specified.
@@ -168,7 +179,9 @@ struct CONTENT_EXPORT WebPreferences {
bool supports_multiple_windows;
bool viewport_enabled;
bool viewport_meta_enabled;
+ bool shrinks_viewport_contents_to_fit;
ViewportStyle viewport_style;
+ bool always_show_context_menu_on_touch;
bool main_frame_resizes_are_orientation_changes;
bool initialize_at_minimum_page_scale;
bool smart_insert_delete_enabled;
@@ -224,6 +237,8 @@ struct CONTENT_EXPORT WebPreferences {
// Used by Android_WebView only to support legacy apps that inject script into
// a top-level initial empty document and expect it to persist on navigation.
bool resue_global_for_unowned_main_frame;
+ bool autoplay_muted_videos_enabled;
+ ProgressBarCompletion progress_bar_completion;
#endif
// String that describes how media element autoplay behavior should be
diff --git a/chromium/content/public/gpu/content_gpu_client.h b/chromium/content/public/gpu/content_gpu_client.h
index 3704141283b..25fee787c6d 100644
--- a/chromium/content/public/gpu/content_gpu_client.h
+++ b/chromium/content/public/gpu/content_gpu_client.h
@@ -5,25 +5,32 @@
#ifndef CONTENT_PUBLIC_GPU_CONTENT_GPU_CLIENT_H_
#define CONTENT_PUBLIC_GPU_CONTENT_GPU_CLIENT_H_
+#include "base/metrics/field_trial.h"
#include "content/public/common/content_client.h"
namespace gpu {
class SyncPointManager;
}
-namespace content {
+namespace shell {
+class InterfaceRegistry;
+}
-class ServiceRegistry;
+namespace content {
// Embedder API for participating in gpu logic.
class CONTENT_EXPORT ContentGpuClient {
public:
virtual ~ContentGpuClient() {}
- // Allows client to register Mojo services in |registry| on the GPU process.
- // The registered services will be exposed to the browser process through
- // GpuProcessHost.
- virtual void RegisterMojoServices(ServiceRegistry* registry) {}
+ // Initializes the client. This sets up the field trial synchronization
+ // mechanism, which will notify |observer| when a field trial is activated,
+ // which should be used to inform the browser process of this state.
+ virtual void Initialize(base::FieldTrialList::Observer* observer) {}
+
+ // Allows the client to expose interfaces from the GPU process to the browser
+ // process via |registry|.
+ virtual void ExposeInterfacesToBrowser(shell::InterfaceRegistry* registry) {}
// Allows client to supply a SyncPointManager instance instead of having
// content internally create one.
diff --git a/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.cc b/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.cc
index f6b468b041a..bfcd4e63525 100644
--- a/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.cc
+++ b/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.cc
@@ -75,7 +75,8 @@ GpuVideoDecodeAcceleratorFactory::CreateVDA(
const gpu::GpuPreferences gpu_preferences =
GpuChildThread::current()->gpu_preferences();
- return gvdafactory_impl_->CreateVDA(client, config, gpu_preferences);
+ return gvdafactory_impl_->CreateVDA(
+ client, config, gpu::GpuDriverBugWorkarounds(), gpu_preferences);
}
GpuVideoDecodeAcceleratorFactory::GpuVideoDecodeAcceleratorFactory(
diff --git a/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.h b/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.h
index 6a1beb6f1dc..e45b8f4be86 100644
--- a/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.h
+++ b/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.h
@@ -13,11 +13,8 @@
#include "gpu/config/gpu_info.h"
#include "media/video/video_decode_accelerator.h"
-namespace gfx {
-class GLContext;
-}
-
namespace gl {
+class GLContext;
class GLImage;
}
@@ -41,7 +38,7 @@ class CONTENT_EXPORT GpuVideoDecodeAcceleratorFactory {
virtual ~GpuVideoDecodeAcceleratorFactory();
// Return current GLContext.
- using GetGLContextCallback = base::Callback<gfx::GLContext*(void)>;
+ using GetGLContextCallback = base::Callback<gl::GLContext*(void)>;
// Make the applicable GL context current. To be called by VDAs before
// executing any GL calls. Return true on success, false otherwise.
diff --git a/chromium/content/public/renderer/content_renderer_client.h b/chromium/content/public/renderer/content_renderer_client.h
index d96adc9a82a..9ad5aef7eac 100644
--- a/chromium/content/public/renderer/content_renderer_client.h
+++ b/chromium/content/public/renderer/content_renderer_client.h
@@ -67,6 +67,10 @@ class MediaLog;
class RendererFactory;
}
+namespace shell {
+class InterfaceRegistry;
+}
+
namespace content {
class BrowserPluginDelegate;
class DocumentState;
@@ -332,12 +336,14 @@ class CONTENT_EXPORT ContentRendererClient {
// is called from the worker thread.
virtual void DidInitializeServiceWorkerContextOnWorkerThread(
v8::Local<v8::Context> context,
+ int embedded_worker_id,
const GURL& url) {}
// Notifies that a service worker context will be destroyed. This function
// is called from the worker thread.
virtual void WillDestroyServiceWorkerContextOnWorkerThread(
v8::Local<v8::Context> context,
+ int embedded_worker_id,
const GURL& url) {}
// Whether this renderer should enforce preferences related to the WebRTC
@@ -348,6 +354,11 @@ class CONTENT_EXPORT ContentRendererClient {
// from the worker thread.
virtual void DidInitializeWorkerContextOnWorkerThread(
v8::Local<v8::Context> context) {}
+
+ // Allows the client to expose interfaces from the renderer process to the
+ // browser process via |registry|.
+ virtual void ExposeInterfacesToBrowser(
+ shell::InterfaceRegistry* interface_registry) {}
};
} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_renderer_factory.h b/chromium/content/public/renderer/media_stream_renderer_factory.h
index 12d91209c4d..30516bd8fb1 100644
--- a/chromium/content/public/renderer/media_stream_renderer_factory.h
+++ b/chromium/content/public/renderer/media_stream_renderer_factory.h
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "content/public/renderer/media_stream_audio_renderer.h"
-#include "content/public/renderer/video_frame_provider.h"
+#include "content/public/renderer/media_stream_video_renderer.h"
#include "url/origin.h"
namespace base {
@@ -36,10 +36,10 @@ class MediaStreamRendererFactory {
public:
virtual ~MediaStreamRendererFactory() {}
- virtual scoped_refptr<VideoFrameProvider> GetVideoFrameProvider(
+ virtual scoped_refptr<MediaStreamVideoRenderer> GetVideoRenderer(
const blink::WebMediaStream& web_stream,
const base::Closure& error_cb,
- const VideoFrameProvider::RepaintCB& repaint_cb,
+ const MediaStreamVideoRenderer::RepaintCB& repaint_cb,
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
const scoped_refptr<base::TaskRunner>& worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories) = 0;
diff --git a/chromium/content/public/renderer/video_frame_provider.h b/chromium/content/public/renderer/media_stream_video_renderer.h
index 08e51da9bda..e1e38de89cf 100644
--- a/chromium/content/public/renderer/video_frame_provider.h
+++ b/chromium/content/public/renderer/media_stream_video_renderer.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_PUBLIC_RENDERER_VIDEO_FRAME_PROVIDER_H_
-#define CONTENT_PUBLIC_RENDERER_VIDEO_FRAME_PROVIDER_H_
+#ifndef CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_VIDEO_RENDERER_H_
+#define CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_VIDEO_RENDERER_H_
#include "base/callback.h"
#include "base/memory/ref_counted.h"
@@ -14,11 +14,11 @@ class VideoFrame;
namespace content {
-// Define an interface to provide a sequence of video frames to clients.
+// Interface returned by MediaStreamRendererFactory that provides controls for
+// the flow of video frame callbacks being made.
// TODO(wjia): remove ref count.
-// TODO(wjia): rename interface so it doesn't clash with cc::VideoFrameProvider.
-class VideoFrameProvider
- : public base::RefCountedThreadSafe<VideoFrameProvider> {
+class MediaStreamVideoRenderer
+ : public base::RefCountedThreadSafe<MediaStreamVideoRenderer> {
public:
typedef base::Callback<void(const scoped_refptr<media::VideoFrame>&)>
RepaintCB;
@@ -30,7 +30,7 @@ class VideoFrameProvider
virtual void Stop() = 0;
// Resume to provide video frames to the caller after being paused.
- virtual void Play() = 0;
+ virtual void Resume() = 0;
// Put the provider in pause state and the caller will not receive video
// frames, but the provider might still generate video frames which are
@@ -38,12 +38,12 @@ class VideoFrameProvider
virtual void Pause() = 0;
protected:
- friend class base::RefCountedThreadSafe<VideoFrameProvider>;
+ friend class base::RefCountedThreadSafe<MediaStreamVideoRenderer>;
- virtual ~VideoFrameProvider() {}
+ virtual ~MediaStreamVideoRenderer() {}
};
} // namespace content
-#endif // CONTENT_PUBLIC_RENDERER_VIDEO_FRAME_PROVIDER_H_
+#endif // CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_VIDEO_RENDERER_H_
diff --git a/chromium/content/public/renderer/pepper_plugin_instance.h b/chromium/content/public/renderer/pepper_plugin_instance.h
index 2a20eaf2ab8..470bf664bf1 100644
--- a/chromium/content/public/renderer/pepper_plugin_instance.h
+++ b/chromium/content/public/renderer/pepper_plugin_instance.h
@@ -13,6 +13,7 @@
#include "ppapi/c/pp_resource.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/private/ppb_instance_private.h"
+#include "ppapi/c/private/ppb_pdf.h"
#include "ui/base/ime/text_input_type.h"
class GURL;
diff --git a/chromium/content/public/renderer/render_accessibility.h b/chromium/content/public/renderer/render_accessibility.h
new file mode 100644
index 00000000000..267d4b65f1f
--- /dev/null
+++ b/chromium/content/public/renderer/render_accessibility.h
@@ -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.
+
+#ifndef CONTENT_PUBLIC_RENDERER_RENDER_ACCESSIBILITY_H_
+#define CONTENT_PUBLIC_RENDERER_RENDER_ACCESSIBILITY_H_
+
+#include "content/common/content_export.h"
+#include "ui/accessibility/ax_node.h"
+#include "ui/accessibility/ax_tree_data.h"
+#include "ui/accessibility/ax_tree_source.h"
+
+namespace content {
+
+// This interface exposes the accessibility tree for one RenderFrame.
+class CONTENT_EXPORT RenderAccessibility {
+ public:
+ virtual int GenerateAXID() = 0;
+
+ using PdfAXTreeSource =
+ ui::AXTreeSource<const ui::AXNode*, ui::AXNodeData, ui::AXTreeData>;
+ virtual void SetPdfTreeSource(PdfAXTreeSource* source) = 0;
+
+ protected:
+ ~RenderAccessibility() {}
+
+ private:
+ // This interface should only be implemented inside content.
+ friend class RenderAccessibilityImpl;
+ RenderAccessibility() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_RENDER_ACCESSIBILITY_H_
diff --git a/chromium/content/public/renderer/render_frame.h b/chromium/content/public/renderer/render_frame.h
index 06fb03655f2..47b958db2ac 100644
--- a/chromium/content/public/renderer/render_frame.h
+++ b/chromium/content/public/renderer/render_frame.h
@@ -15,15 +15,14 @@
#include "content/public/common/console_message_level.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
+#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
class GURL;
namespace blink {
-class WebElement;
class WebFrame;
class WebLocalFrame;
-class WebNode;
class WebPlugin;
class WebURLRequest;
class WebURLResponse;
@@ -35,6 +34,11 @@ class Range;
class Size;
}
+namespace shell {
+class InterfaceRegistry;
+class InterfaceProvider;
+}
+
namespace url {
class Origin;
}
@@ -48,8 +52,8 @@ class Isolate;
namespace content {
class ContextMenuClient;
class PluginInstanceThrottler;
+class RenderAccessibility;
class RenderView;
-class ServiceRegistry;
struct ContextMenuParams;
struct WebPluginInfo;
struct WebPreferences;
@@ -87,6 +91,9 @@ class CONTENT_EXPORT RenderFrame : public IPC::Listener,
// Returns the RenderView associated with this frame.
virtual RenderView* GetRenderView() = 0;
+ // Return the RenderAccessibility associated with this frame.
+ virtual RenderAccessibility* GetRenderAccessibility() = 0;
+
// Get the routing ID of the frame.
virtual int GetRoutingID() = 0;
@@ -135,8 +142,13 @@ class CONTENT_EXPORT RenderFrame : public IPC::Listener,
// Return true if this frame is hidden.
virtual bool IsHidden() = 0;
- // Returns the ServiceRegistry for this frame.
- virtual ServiceRegistry* GetServiceRegistry() = 0;
+ // Returns the InterfaceRegistry that this process uses to expose interfaces
+ // to the application running in this frame.
+ virtual shell::InterfaceRegistry* GetInterfaceRegistry() = 0;
+
+ // Returns the InterfaceProvider that this process can use to bind
+ // interfaces exposed to it by the application running in this frame.
+ virtual shell::InterfaceProvider* GetRemoteInterfaces() = 0;
#if defined(ENABLE_PLUGINS)
// Registers a plugin that has been marked peripheral. If the origin
@@ -203,6 +215,9 @@ class CONTENT_EXPORT RenderFrame : public IPC::Listener,
// Whether or not this frame is currently pasting.
virtual bool IsPasting() const = 0;
+ // Returns the current visibility of the frame.
+ virtual blink::WebPageVisibilityState GetVisibilityState() const = 0;
+
protected:
~RenderFrame() override {}
diff --git a/chromium/content/public/renderer/render_frame_observer.cc b/chromium/content/public/renderer/render_frame_observer.cc
index 19d77d01f0e..9e26c91976b 100644
--- a/chromium/content/public/renderer/render_frame_observer.cc
+++ b/chromium/content/public/renderer/render_frame_observer.cc
@@ -29,10 +29,6 @@ RenderFrameObserver::~RenderFrameObserver() {
}
}
-void RenderFrameObserver::OnDestruct() {
- delete this;
-}
-
bool RenderFrameObserver::OnMessageReceived(const IPC::Message& message) {
return false;
}
diff --git a/chromium/content/public/renderer/render_frame_observer.h b/chromium/content/public/renderer/render_frame_observer.h
index bf7c6eee7a7..a48fa5422eb 100644
--- a/chromium/content/public/renderer/render_frame_observer.h
+++ b/chromium/content/public/renderer/render_frame_observer.h
@@ -37,9 +37,10 @@ class RenderFrameImpl;
class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
public IPC::Sender {
public:
- // By default, observers will be deleted when the RenderFrame goes away. If
- // they want to outlive it, they can override this function.
- virtual void OnDestruct();
+ // A subclass can use this to delete itself. If it does not, the subclass must
+ // always null-check each call to render_frame() becase the RenderFrame can
+ // go away at any time.
+ virtual void OnDestruct() = 0;
// Called when a Pepper plugin is created.
virtual void DidCreatePepperPlugin(RendererPpapiHost* host) {}
diff --git a/chromium/content/public/renderer/render_thread.h b/chromium/content/public/renderer/render_thread.h
index 2c219f2506e..2f8307d515d 100644
--- a/chromium/content/public/renderer/render_thread.h
+++ b/chromium/content/public/renderer/render_thread.h
@@ -40,7 +40,6 @@ namespace content {
class RenderThreadObserver;
class ResourceDispatcherDelegate;
-class ServiceRegistry;
class CONTENT_EXPORT RenderThread : virtual public ChildThread {
public:
@@ -108,9 +107,6 @@ class CONTENT_EXPORT RenderThread : virtual public ChildThread {
// Gets the shutdown event for the process.
virtual base::WaitableEvent* GetShutdownEvent() = 0;
-
- // Returns the ServiceRegistry for this thread. Never returns nullptr.
- virtual ServiceRegistry* GetServiceRegistry() = 0;
};
} // namespace content
diff --git a/chromium/content/public/renderer/render_view.h b/chromium/content/public/renderer/render_view.h
index 9aa06333ca4..8fca07e1e5d 100644
--- a/chromium/content/public/renderer/render_view.h
+++ b/chromium/content/public/renderer/render_view.h
@@ -14,7 +14,6 @@
#include "content/common/content_export.h"
#include "content/public/common/top_controls_state.h"
#include "ipc/ipc_sender.h"
-#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/native_widget_types.h"
@@ -109,9 +108,6 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
// false, but set to true by some tests.
virtual bool GetContentStateImmediately() const = 0;
- // Returns the current visibility of the WebView.
- virtual blink::WebPageVisibilityState GetVisibilityState() const = 0;
-
// Used by plugins that load data in this RenderView to update the loading
// notifications.
virtual void DidStartLoading() = 0;
diff --git a/chromium/content/public/renderer/render_view_observer.cc b/chromium/content/public/renderer/render_view_observer.cc
index 5e876cc1bff..f90a8058cb4 100644
--- a/chromium/content/public/renderer/render_view_observer.cc
+++ b/chromium/content/public/renderer/render_view_observer.cc
@@ -24,10 +24,6 @@ RenderViewObserver::~RenderViewObserver() {
render_view_->RemoveObserver(this);
}
-void RenderViewObserver::OnDestruct() {
- delete this;
-}
-
bool RenderViewObserver::OnMessageReceived(const IPC::Message& message) {
return false;
}
diff --git a/chromium/content/public/renderer/render_view_observer.h b/chromium/content/public/renderer/render_view_observer.h
index a245e632c91..a3fa20cfc26 100644
--- a/chromium/content/public/renderer/render_view_observer.h
+++ b/chromium/content/public/renderer/render_view_observer.h
@@ -31,9 +31,10 @@ class RenderViewImpl;
class CONTENT_EXPORT RenderViewObserver : public IPC::Listener,
public IPC::Sender {
public:
- // By default, observers will be deleted when the RenderView goes away. If
- // they want to outlive it, they can override this function.
- virtual void OnDestruct();
+ // A subclass can use this to delete itself. If it does not, the subclass must
+ // always null-check each call to render_view() becase the RenderView can
+ // go away at any time.
+ virtual void OnDestruct() = 0;
// These match the WebKit API notifications
virtual void DidStartLoading() {}
diff --git a/chromium/content/public/renderer/resource_fetcher.h b/chromium/content/public/renderer/resource_fetcher.h
index 64fece51f04..71a12c4c7ad 100644
--- a/chromium/content/public/renderer/resource_fetcher.h
+++ b/chromium/content/public/renderer/resource_fetcher.h
@@ -55,7 +55,8 @@ class CONTENT_EXPORT ResourceFetcher {
virtual void SetBody(const std::string& body) = 0;
virtual void SetHeader(const std::string& header,
const std::string& value) = 0;
- virtual void SetSkipServiceWorker(bool skip_service_worker) = 0;
+ virtual void SetSkipServiceWorker(
+ blink::WebURLRequest::SkipServiceWorker skip_service_worker) = 0;
virtual void SetCachePolicy(blink::WebCachePolicy policy) = 0;
// Associate the corresponding WebURLLoaderOptions to the loader. Must be
diff --git a/chromium/content/public/utility/content_utility_client.h b/chromium/content/public/utility/content_utility_client.h
index 7dc3810bcb7..da96cd70a15 100644
--- a/chromium/content/public/utility/content_utility_client.h
+++ b/chromium/content/public/utility/content_utility_client.h
@@ -15,13 +15,12 @@
class GURL;
namespace shell {
+class InterfaceRegistry;
class ShellClient;
}
namespace content {
-class ServiceRegistry;
-
// Embedder API for participating in renderer logic.
class CONTENT_EXPORT ContentUtilityClient {
public:
@@ -35,8 +34,9 @@ class CONTENT_EXPORT ContentUtilityClient {
// Allows the embedder to filter messages.
virtual bool OnMessageReceived(const IPC::Message& message);
- // Registers Mojo services.
- virtual void RegisterMojoServices(ServiceRegistry* registry) {}
+ // Allows the client to expose interfaces from this utility process to the
+ // browser process via |registry|.
+ virtual void ExposeInterfacesToBrowser(shell::InterfaceRegistry* registry) {}
// Registers Mojo applications.
virtual void RegisterMojoApplications(StaticMojoApplicationMap* apps) {}
diff --git a/chromium/content/renderer/BUILD.gn b/chromium/content/renderer/BUILD.gn
index 13138ab148a..3f9286e2144 100644
--- a/chromium/content/renderer/BUILD.gn
+++ b/chromium/content/renderer/BUILD.gn
@@ -7,6 +7,7 @@ import("//build/config/ui.gni")
import("//content/renderer/renderer.gni")
import("//media/media_options.gni")
import("//third_party/webrtc/build/webrtc.gni")
+import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
source_set("renderer") {
# Only the public target should depend on this. All other targets (even
@@ -51,19 +52,19 @@ source_set("renderer") {
"//device/bluetooth",
"//device/usb/public/interfaces",
"//device/vibration:mojo_bindings",
+ "//device/vr:mojo_bindings",
"//gin",
"//gpu",
"//gpu/command_buffer/client:gles2_interface",
- "//ipc/mojo",
"//jingle:jingle_glue",
"//media",
"//media/blink",
+ "//media/capture",
"//media/gpu",
"//media/gpu/ipc/client",
"//media/gpu/ipc/common",
"//media/midi",
"//mojo/common",
- "//mojo/converters/geometry",
"//mojo/edk/js",
"//mojo/public/cpp/bindings",
"//mojo/public/js",
@@ -72,7 +73,6 @@ source_set("renderer") {
"//services/shell/public/cpp",
"//services/shell/public/interfaces",
"//skia",
- "//skia/public",
"//storage/common",
"//third_party/WebKit/public:blink",
"//third_party/WebKit/public:mojo_bindings",
@@ -89,6 +89,7 @@ source_set("renderer") {
"//ui/events:dom_keycode_converter",
"//ui/events:events_base",
"//ui/events/blink",
+ "//ui/gfx/geometry/mojo",
"//ui/gl",
"//ui/native_theme",
"//ui/surface",
@@ -99,25 +100,24 @@ source_set("renderer") {
if (use_aura) {
public_deps += [ "//content/renderer/mus" ]
allow_circular_includes_from += [ "//content/renderer/mus" ]
+ deps += [ "//components/mus/common:mus_common" ]
}
- if (is_mac) {
- sources -= [
- "webscrollbarbehavior_impl_gtkoraura.cc",
- "webscrollbarbehavior_impl_gtkoraura.h",
- ]
+ if (use_external_popup_menu) {
sources += [
"external_popup_menu.cc",
"external_popup_menu.h",
]
}
- if (is_android) {
- sources += [
- "external_popup_menu.cc",
- "external_popup_menu.h",
+ if (is_mac) {
+ sources -= [
+ "webscrollbarbehavior_impl_gtkoraura.cc",
+ "webscrollbarbehavior_impl_gtkoraura.h",
]
+ }
+ if (is_android) {
# Add back the Linux file which Android shares.
set_sources_assignment_filter([])
sources += [ "render_view_linux.cc" ]
@@ -240,7 +240,7 @@ source_set("renderer") {
"//media/mojo/interfaces",
# Defines in mojo_media_config are also pulled in here.
- "//media/mojo/services:proxy",
+ "//media/mojo/clients",
]
}
@@ -251,6 +251,10 @@ source_set("renderer") {
if (use_ozone) {
deps += [ "//ui/ozone" ]
}
+
+ if (enable_ipc_fuzzer) {
+ configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_config" ]
+ }
}
# See comment at the top of //content/BUILD.gn for how this works.
diff --git a/chromium/content/renderer/DEPS b/chromium/content/renderer/DEPS
index 4a800d455d1..3ea84f5c94a 100644
--- a/chromium/content/renderer/DEPS
+++ b/chromium/content/renderer/DEPS
@@ -1,6 +1,7 @@
include_rules = [
- # Allow inclusion of specific components that we depend on. We may only
- # depend on components which we share with the mojo html_viewer.
+ # Allow inclusion of specific components that we depend on.
+ # See comment in content/DEPS for which components are allowed.
+ "+components/mus/common",
"+components/mus/public",
"+components/scheduler",
"+components/url_formatter",
diff --git a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
index ff82c5669af..02e85a92856 100644
--- a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -405,6 +405,19 @@ ui::AXEvent AXEventFromBlink(blink::WebAXEvent event) {
}
}
+ui::AXMarkerType AXMarkerTypeFromBlink(blink::WebAXMarkerType marker_type) {
+ switch (marker_type) {
+ case blink::WebAXMarkerTypeSpelling:
+ return ui::AX_MARKER_TYPE_SPELLING;
+ case blink::WebAXMarkerTypeGrammar:
+ return ui::AX_MARKER_TYPE_GRAMMAR;
+ case blink::WebAXMarkerTypeTextMatch:
+ return ui::AX_MARKER_TYPE_TEXT_MATCH;
+ }
+ NOTREACHED();
+ return ui::AX_MARKER_TYPE_NONE;
+}
+
ui::AXTextDirection AXTextDirectionFromBlink(
blink::WebAXTextDirection text_direction) {
switch (text_direction) {
@@ -416,10 +429,8 @@ ui::AXTextDirection AXTextDirectionFromBlink(
return ui::AX_TEXT_DIRECTION_TTB;
case blink::WebAXTextDirectionBT:
return ui::AX_TEXT_DIRECTION_BTT;
- default:
- NOTREACHED();
}
-
+ NOTREACHED();
return ui::AX_TEXT_DIRECTION_NONE;
}
@@ -477,7 +488,6 @@ ui::AXInvalidState AXInvalidStateFromBlink(
case blink::WebAXInvalidStateOther:
return ui::AX_INVALID_STATE_OTHER;
}
-
NOTREACHED();
return ui::AX_INVALID_STATE_NONE;
}
@@ -495,10 +505,8 @@ ui::AXSortDirection AXSortDirectionFromBlink(
return ui::AX_SORT_DIRECTION_DESCENDING;
case blink::WebAXSortDirectionOther:
return ui::AX_SORT_DIRECTION_OTHER;
- default:
- NOTREACHED();
}
-
+ NOTREACHED();
return ui::AX_SORT_DIRECTION_NONE;
}
@@ -520,11 +528,9 @@ ui::AXNameFrom AXNameFromFromBlink(blink::WebAXNameFrom name_from) {
return ui::AX_NAME_FROM_VALUE;
case blink::WebAXNameFromTitle:
return ui::AX_NAME_FROM_ATTRIBUTE;
- default:
- NOTREACHED();
}
-
- return ui::AX_NAME_FROM_UNINITIALIZED;
+ NOTREACHED();
+ return ui::AX_NAME_FROM_NONE;
}
ui::AXDescriptionFrom AXDescriptionFromFromBlink(
@@ -540,11 +546,9 @@ ui::AXDescriptionFrom AXDescriptionFromFromBlink(
return ui::AX_DESCRIPTION_FROM_PLACEHOLDER;
case blink::WebAXDescriptionFromRelatedElement:
return ui::AX_DESCRIPTION_FROM_RELATED_ELEMENT;
- default:
- NOTREACHED();
}
-
- return ui::AX_DESCRIPTION_FROM_UNINITIALIZED;
+ NOTREACHED();
+ return ui::AX_DESCRIPTION_FROM_NONE;
}
} // namespace content.
diff --git a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.h b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.h
index 4342971ba74..a2e932cd337 100644
--- a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.h
+++ b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.h
@@ -24,6 +24,8 @@ ui::AXEvent AXEventFromBlink(blink::WebAXEvent event);
// in AXNodeData instead.)
uint32_t AXStateFromBlink(const blink::WebAXObject& o);
+ui::AXMarkerType AXMarkerTypeFromBlink(blink::WebAXMarkerType marker_type);
+
ui::AXTextDirection AXTextDirectionFromBlink(
blink::WebAXTextDirection text_direction);
diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
index cd6d2f87338..79f5324c143 100644
--- a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -13,7 +13,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/common/accessibility_messages.h"
#include "content/renderer/accessibility/blink_ax_enum_conversion.h"
-#include "content/renderer/accessibility/renderer_accessibility.h"
+#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_frame_proxy.h"
@@ -133,22 +133,20 @@ bool BlinkAXTreeSource::IsInTree(blink::WebAXObject node) const {
return false;
}
-AXContentTreeData BlinkAXTreeSource::GetTreeData() const {
- AXContentTreeData tree_data;
-
+bool BlinkAXTreeSource::GetTreeData(AXContentTreeData* tree_data) const {
blink::WebDocument document = BlinkAXTreeSource::GetMainDocument();
const blink::WebAXObject& root = GetRoot();
- tree_data.doctype = "html";
- tree_data.loaded = root.isLoaded();
- tree_data.loading_progress = root.estimatedLoadingProgress();
- tree_data.mimetype = document.isXHTMLDocument() ? "text/xhtml" : "text/html";
- tree_data.title = document.title().utf8();
- tree_data.url = document.url().string().utf8();
+ tree_data->doctype = "html";
+ tree_data->loaded = root.isLoaded();
+ tree_data->loading_progress = root.estimatedLoadingProgress();
+ tree_data->mimetype = document.isXHTMLDocument() ? "text/xhtml" : "text/html";
+ tree_data->title = document.title().utf8();
+ tree_data->url = document.url().string().utf8();
WebAXObject focus = document.focusedAccessibilityObject();
if (!focus.isNull())
- tree_data.focus_id = focus.axID();
+ tree_data->focus_id = focus.axID();
WebAXObject anchor_object, focus_object;
int anchor_offset, focus_offset;
@@ -157,27 +155,27 @@ AXContentTreeData BlinkAXTreeSource::GetTreeData() const {
anchor_offset >= 0 && focus_offset >= 0) {
int32_t anchor_id = anchor_object.axID();
int32_t focus_id = focus_object.axID();
- tree_data.sel_anchor_object_id = anchor_id;
- tree_data.sel_anchor_offset = anchor_offset;
- tree_data.sel_focus_object_id = focus_id;
- tree_data.sel_focus_offset = focus_offset;
+ tree_data->sel_anchor_object_id = anchor_id;
+ tree_data->sel_anchor_offset = anchor_offset;
+ tree_data->sel_focus_object_id = focus_id;
+ tree_data->sel_focus_offset = focus_offset;
}
// Get the tree ID for this frame and the parent frame.
WebLocalFrame* web_frame = document.frame();
if (web_frame) {
RenderFrame* render_frame = RenderFrame::FromWebFrame(web_frame);
- tree_data.routing_id = render_frame->GetRoutingID();
+ tree_data->routing_id = render_frame->GetRoutingID();
// Get the tree ID for the parent frame.
blink::WebFrame* parent_web_frame = web_frame->parent();
if (parent_web_frame) {
- tree_data.parent_routing_id =
+ tree_data->parent_routing_id =
GetRoutingIdForFrameOrProxy(parent_web_frame);
}
}
- return tree_data;
+ return true;
}
blink::WebAXObject BlinkAXTreeSource::GetRoot() const {
@@ -445,6 +443,32 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
if (src.canvasHasFallbackContent())
dst->AddBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK, true);
+ // Spelling, grammar and other document markers.
+ WebVector<blink::WebAXMarkerType> src_marker_types;
+ WebVector<int> src_marker_starts;
+ WebVector<int> src_marker_ends;
+ src.markers(src_marker_types, src_marker_starts, src_marker_ends);
+ DCHECK_EQ(src_marker_types.size(), src_marker_starts.size());
+ DCHECK_EQ(src_marker_starts.size(), src_marker_ends.size());
+
+ if (src_marker_types.size()) {
+ std::vector<int32_t> marker_types;
+ std::vector<int32_t> marker_starts;
+ std::vector<int32_t> marker_ends;
+ marker_types.reserve(src_marker_types.size());
+ marker_starts.reserve(src_marker_starts.size());
+ marker_ends.reserve(src_marker_ends.size());
+ for (size_t i = 0; i < src_marker_types.size(); ++i) {
+ marker_types.push_back(
+ static_cast<int32_t>(AXMarkerTypeFromBlink(src_marker_types[i])));
+ marker_starts.push_back(src_marker_starts[i]);
+ marker_ends.push_back(src_marker_ends[i]);
+ }
+ dst->AddIntListAttribute(ui::AX_ATTR_MARKER_TYPES, marker_types);
+ dst->AddIntListAttribute(ui::AX_ATTR_MARKER_STARTS, marker_starts);
+ dst->AddIntListAttribute(ui::AX_ATTR_MARKER_ENDS, marker_ends);
+ }
+
WebNode node = src.node();
bool is_iframe = false;
@@ -471,7 +495,7 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
WebVector<int> src_line_breaks;
src.lineBreaks(src_line_breaks);
- if (src_line_breaks.size() > 0) {
+ if (src_line_breaks.size()) {
std::vector<int32_t> line_breaks;
line_breaks.reserve(src_line_breaks.size());
for (size_t i = 0; i < src_line_breaks.size(); ++i)
@@ -525,6 +549,12 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
dst->AddStringAttribute(
ui::AX_ATTR_LIVE_RELEVANT,
src.liveRegionRelevant().utf8());
+ // If we are not at the root of an atomic live region.
+ if (src.containerLiveRegionAtomic() && !src.liveRegionRoot().isDetached() &&
+ !src.liveRegionAtomic()) {
+ dst->AddIntAttribute(ui::AX_ATTR_MEMBER_OF_ID,
+ src.liveRegionRoot().axID());
+ }
dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_ATOMIC,
src.containerLiveRegionAtomic());
dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY,
diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.h b/chromium/content/renderer/accessibility/blink_ax_tree_source.h
index e7a7d4aa90f..90f7f152224 100644
--- a/chromium/content/renderer/accessibility/blink_ax_tree_source.h
+++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.h
@@ -39,7 +39,7 @@ class BlinkAXTreeSource
void set_accessibility_focus_id(int id) { accessibility_focus_id_ = id; }
// AXTreeSource implementation.
- AXContentTreeData GetTreeData() const override;
+ bool GetTreeData(AXContentTreeData* tree_data) const override;
blink::WebAXObject GetRoot() const override;
blink::WebAXObject GetFromId(int32_t id) const override;
int32_t GetId(blink::WebAXObject node) const override;
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility.cc b/chromium/content/renderer/accessibility/render_accessibility_impl.cc
index 9b630650233..5611c7f3182 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility.cc
+++ b/chromium/content/renderer/accessibility/render_accessibility_impl.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/renderer/accessibility/renderer_accessibility.h"
+#include "content/renderer/accessibility/render_accessibility_impl.h"
#include <stddef.h>
#include <stdint.h>
@@ -25,9 +25,11 @@
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebSettings.h"
#include "third_party/WebKit/public/web/WebView.h"
+#include "ui/accessibility/ax_node.h"
using blink::WebAXObject;
using blink::WebDocument;
+using blink::WebElement;
using blink::WebLocalFrame;
using blink::WebNode;
using blink::WebPoint;
@@ -44,7 +46,7 @@ namespace content {
const size_t kMaxSnapshotNodeCount = 5000;
// static
-void RendererAccessibility::SnapshotAccessibilityTree(
+void RenderAccessibilityImpl::SnapshotAccessibilityTree(
RenderFrameImpl* render_frame,
AXContentTreeUpdate* response) {
DCHECK(render_frame);
@@ -61,11 +63,12 @@ void RendererAccessibility::SnapshotAccessibilityTree(
serializer.SerializeChanges(context.root(), response);
}
-RendererAccessibility::RendererAccessibility(RenderFrameImpl* render_frame)
+RenderAccessibilityImpl::RenderAccessibilityImpl(RenderFrameImpl* render_frame)
: RenderFrameObserver(render_frame),
render_frame_(render_frame),
tree_source_(render_frame),
serializer_(&tree_source_),
+ pdf_tree_source_(nullptr),
last_scroll_offset_(gfx::Size()),
ack_pending_(false),
reset_token_(0),
@@ -102,12 +105,12 @@ RendererAccessibility::RendererAccessibility(RenderFrameImpl* render_frame)
}
}
-RendererAccessibility::~RendererAccessibility() {
+RenderAccessibilityImpl::~RenderAccessibilityImpl() {
}
-bool RendererAccessibility::OnMessageReceived(const IPC::Message& message) {
+bool RenderAccessibilityImpl::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RendererAccessibility, message)
+ IPC_BEGIN_MESSAGE_MAP(RenderAccessibilityImpl, message)
IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus)
IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction, OnDoDefaultAction)
IPC_MESSAGE_HANDLER(AccessibilityMsg_Events_ACK, OnEventsAck)
@@ -128,12 +131,12 @@ bool RendererAccessibility::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void RendererAccessibility::HandleWebAccessibilityEvent(
+void RenderAccessibilityImpl::HandleWebAccessibilityEvent(
const blink::WebAXObject& obj, blink::WebAXEvent event) {
HandleAXEvent(obj, AXEventFromBlink(event));
}
-void RendererAccessibility::HandleAccessibilityFindInPageResult(
+void RenderAccessibilityImpl::HandleAccessibilityFindInPageResult(
int identifier,
int match_index,
const blink::WebAXObject& start_object,
@@ -150,7 +153,7 @@ void RendererAccessibility::HandleAccessibilityFindInPageResult(
Send(new AccessibilityHostMsg_FindInPageResult(routing_id(), params));
}
-void RendererAccessibility::AccessibilityFocusedNodeChanged(
+void RenderAccessibilityImpl::AccessibilityFocusedNodeChanged(
const WebNode& node) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
@@ -163,7 +166,7 @@ void RendererAccessibility::AccessibilityFocusedNodeChanged(
}
}
-void RendererAccessibility::DisableAccessibility() {
+void RenderAccessibilityImpl::DisableAccessibility() {
RenderView* render_view = render_frame_->GetRenderView();
if (!render_view)
return;
@@ -179,7 +182,7 @@ void RendererAccessibility::DisableAccessibility() {
settings->setAccessibilityEnabled(false);
}
-void RendererAccessibility::HandleAXEvent(
+void RenderAccessibilityImpl::HandleAXEvent(
const blink::WebAXObject& obj, ui::AXEvent event) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
@@ -226,18 +229,55 @@ void RendererAccessibility::HandleAXEvent(
// up additional events.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&RendererAccessibility::SendPendingAccessibilityEvents,
+ base::Bind(&RenderAccessibilityImpl::SendPendingAccessibilityEvents,
weak_factory_.GetWeakPtr()));
}
}
-WebDocument RendererAccessibility::GetMainDocument() {
+int RenderAccessibilityImpl::GenerateAXID() {
+ WebAXObject root = tree_source_.GetRoot();
+ return root.generateAXID();
+}
+
+void RenderAccessibilityImpl::SetPdfTreeSource(
+ RenderAccessibilityImpl::PdfAXTreeSource* pdf_tree_source) {
+ pdf_tree_source_ = pdf_tree_source;
+ pdf_serializer_.reset(new PdfAXTreeSerializer(pdf_tree_source_));
+
+ WebAXObject root = tree_source_.GetRoot();
+ if (!root.updateLayoutAndCheckValidity())
+ return;
+
+ std::queue<WebAXObject> objs_to_explore;
+ objs_to_explore.push(root);
+ while (objs_to_explore.size()) {
+ WebAXObject obj = objs_to_explore.front();
+ objs_to_explore.pop();
+
+ WebNode node = obj.node();
+ if (!node.isNull() && node.isElementNode()) {
+ WebElement element = node.to<WebElement>();
+ if (element.hasHTMLTagName("embed")) {
+ HandleAXEvent(obj, ui::AX_EVENT_CHILDREN_CHANGED);
+ break;
+ }
+ }
+
+ // Explore children of this object.
+ std::vector<blink::WebAXObject> children;
+ tree_source_.GetChildren(obj, &children);
+ for (size_t i = 0; i < children.size(); ++i)
+ objs_to_explore.push(children[i]);
+ }
+}
+
+WebDocument RenderAccessibilityImpl::GetMainDocument() {
if (render_frame_ && render_frame_->GetWebFrame())
return render_frame_->GetWebFrame()->document();
return WebDocument();
}
-void RendererAccessibility::SendPendingAccessibilityEvents() {
+void RenderAccessibilityImpl::SendPendingAccessibilityEvents() {
const WebDocument& document = GetMainDocument();
if (document.isNull())
return;
@@ -289,6 +329,9 @@ void RendererAccessibility::SendPendingAccessibilityEvents() {
continue;
}
+ if (pdf_tree_source_)
+ AddPdfTreeToUpdate(&event_msg.update);
+
event_msgs.push_back(event_msg);
// For each node in the update, set the location in our map from
@@ -310,7 +353,7 @@ void RendererAccessibility::SendPendingAccessibilityEvents() {
SendLocationChanges();
}
-void RendererAccessibility::SendLocationChanges() {
+void RenderAccessibilityImpl::SendLocationChanges() {
std::vector<AccessibilityHostMsg_LocationChangeParams> messages;
// Update layout on the root of the tree.
@@ -356,7 +399,7 @@ void RendererAccessibility::SendLocationChanges() {
Send(new AccessibilityHostMsg_LocationChanges(routing_id(), messages));
}
-void RendererAccessibility::OnDoDefaultAction(int acc_obj_id) {
+void RenderAccessibilityImpl::OnDoDefaultAction(int acc_obj_id) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
return;
@@ -372,17 +415,17 @@ void RendererAccessibility::OnDoDefaultAction(int acc_obj_id) {
obj.performDefaultAction();
}
-void RendererAccessibility::OnEventsAck() {
+void RenderAccessibilityImpl::OnEventsAck() {
DCHECK(ack_pending_);
ack_pending_ = false;
SendPendingAccessibilityEvents();
}
-void RendererAccessibility::OnFatalError() {
+void RenderAccessibilityImpl::OnFatalError() {
CHECK(false) << "Invalid accessibility tree.";
}
-void RendererAccessibility::OnHitTest(gfx::Point point) {
+void RenderAccessibilityImpl::OnHitTest(gfx::Point point) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
return;
@@ -411,7 +454,7 @@ void RendererAccessibility::OnHitTest(gfx::Point point) {
HandleAXEvent(obj, ui::AX_EVENT_HOVER);
}
-void RendererAccessibility::OnSetAccessibilityFocus(int acc_obj_id) {
+void RenderAccessibilityImpl::OnSetAccessibilityFocus(int acc_obj_id) {
if (tree_source_.accessibility_focus_id() == acc_obj_id)
return;
@@ -431,7 +474,7 @@ void RendererAccessibility::OnSetAccessibilityFocus(int acc_obj_id) {
HandleAXEvent(obj, ui::AX_EVENT_TREE_CHANGED);
}
-void RendererAccessibility::OnReset(int reset_token) {
+void RenderAccessibilityImpl::OnReset(int reset_token) {
reset_token_ = reset_token;
serializer_.Reset();
pending_events_.clear();
@@ -446,7 +489,7 @@ void RendererAccessibility::OnReset(int reset_token) {
}
}
-void RendererAccessibility::OnScrollToMakeVisible(
+void RenderAccessibilityImpl::OnScrollToMakeVisible(
int acc_obj_id, gfx::Rect subfocus) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
@@ -470,7 +513,8 @@ void RendererAccessibility::OnScrollToMakeVisible(
HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_LAYOUT_COMPLETE);
}
-void RendererAccessibility::OnScrollToPoint(int acc_obj_id, gfx::Point point) {
+void RenderAccessibilityImpl::OnScrollToPoint(
+ int acc_obj_id, gfx::Point point) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
return;
@@ -492,7 +536,7 @@ void RendererAccessibility::OnScrollToPoint(int acc_obj_id, gfx::Point point) {
HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_LAYOUT_COMPLETE);
}
-void RendererAccessibility::OnSetScrollOffset(int acc_obj_id,
+void RenderAccessibilityImpl::OnSetScrollOffset(int acc_obj_id,
gfx::Point offset) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
@@ -505,7 +549,7 @@ void RendererAccessibility::OnSetScrollOffset(int acc_obj_id,
obj.setScrollOffset(WebPoint(offset.x(), offset.y()));
}
-void RendererAccessibility::OnSetFocus(int acc_obj_id) {
+void RenderAccessibilityImpl::OnSetFocus(int acc_obj_id) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
return;
@@ -535,7 +579,7 @@ void RendererAccessibility::OnSetFocus(int acc_obj_id) {
obj.setFocused(true);
}
-void RendererAccessibility::OnSetSelection(int anchor_acc_obj_id,
+void RenderAccessibilityImpl::OnSetSelection(int anchor_acc_obj_id,
int anchor_offset,
int focus_acc_obj_id,
int focus_offset) {
@@ -573,7 +617,7 @@ void RendererAccessibility::OnSetSelection(int anchor_acc_obj_id,
HandleAXEvent(root, ui::AX_EVENT_LAYOUT_COMPLETE);
}
-void RendererAccessibility::OnSetValue(
+void RenderAccessibilityImpl::OnSetValue(
int acc_obj_id,
base::string16 value) {
const WebDocument& document = GetMainDocument();
@@ -592,7 +636,7 @@ void RendererAccessibility::OnSetValue(
HandleAXEvent(obj, ui::AX_EVENT_VALUE_CHANGED);
}
-void RendererAccessibility::OnShowContextMenu(int acc_obj_id) {
+void RenderAccessibilityImpl::OnShowContextMenu(int acc_obj_id) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
return;
@@ -608,4 +652,30 @@ void RendererAccessibility::OnShowContextMenu(int acc_obj_id) {
obj.showContextMenu();
}
+void RenderAccessibilityImpl::OnDestruct() {
+ delete this;
+}
+
+void RenderAccessibilityImpl::AddPdfTreeToUpdate(AXContentTreeUpdate* update) {
+ for (size_t i = 0; i < update->nodes.size(); ++i) {
+ if (update->nodes[i].role == ui::AX_ROLE_EMBEDDED_OBJECT) {
+ const ui::AXNode* root = pdf_tree_source_->GetRoot();
+ update->nodes[i].child_ids.push_back(root->id());
+
+ ui::AXTreeUpdate pdf_update;
+ pdf_serializer_->SerializeChanges(root, &pdf_update);
+
+ // We have to copy the updated nodes using a loop because we're
+ // converting from a generic ui::AXNodeData to a vector of its
+ // content-specific subclass AXContentNodeData.
+ size_t old_count = update->nodes.size();
+ size_t new_count = pdf_update.nodes.size();
+ update->nodes.resize(old_count + new_count);
+ for (size_t i = 0; i < new_count; ++i)
+ update->nodes[old_count + i] = pdf_update.nodes[i];
+ break;
+ }
+ }
+}
+
} // namespace content
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility.h b/chromium/content/renderer/accessibility/render_accessibility_impl.h
index 91bcd553afc..f56d2add2cf 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility.h
+++ b/chromium/content/renderer/accessibility/render_accessibility_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_H_
-#define CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_H_
+#ifndef CONTENT_RENDERER_ACCESSIBILITY_RENDER_ACCESSIBILITY_IMPL_H_
+#define CONTENT_RENDERER_ACCESSIBILITY_RENDER_ACCESSIBILITY_IMPL_H_
#include <vector>
@@ -11,9 +11,11 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/ax_content_node_data.h"
+#include "content/public/renderer/render_accessibility.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/renderer/accessibility/blink_ax_tree_source.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
+#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_serializer.h"
struct AccessibilityHostMsg_EventParams;
@@ -47,7 +49,9 @@ class RenderFrameImpl;
// representation of that tree whenever it changes. It also handles requests
// from the browser to perform accessibility actions on nodes in the tree
// (e.g., change focus, or click on a button).
-class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
+class CONTENT_EXPORT RenderAccessibilityImpl
+ : public RenderAccessibility,
+ RenderFrameObserver {
public:
// Request a one-time snapshot of the accessibility tree without
// enabling accessibility if it wasn't already enabled.
@@ -55,8 +59,12 @@ class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
RenderFrameImpl* render_frame,
AXContentTreeUpdate* response);
- explicit RendererAccessibility(RenderFrameImpl* render_frame);
- ~RendererAccessibility() override;
+ explicit RenderAccessibilityImpl(RenderFrameImpl* render_frame);
+ ~RenderAccessibilityImpl() override;
+
+ // RenderAccessibility implementation.
+ int GenerateAXID() override;
+ void SetPdfTreeSource(PdfAXTreeSource* source) override;
// RenderFrameObserver implementation.
bool OnMessageReceived(const IPC::Message& message) override;
@@ -76,7 +84,7 @@ class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
void AccessibilityFocusedNodeChanged(const blink::WebNode& node);
- // This can be called before deleting a RendererAccessibility instance due
+ // This can be called before deleting a RenderAccessibilityImpl instance due
// to the accessibility mode changing, as opposed to during frame destruction
// (when there'd be no point).
void DisableAccessibility();
@@ -100,6 +108,9 @@ class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
RenderFrameImpl* render_frame_;
private:
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
// Handlers for messages from the browser to the renderer.
void OnDoDefaultAction(int acc_obj_id);
void OnEventsAck();
@@ -118,6 +129,8 @@ class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
void OnSetValue(int acc_obj_id, base::string16 value);
void OnShowContextMenu(int acc_obj_id);
+ void AddPdfTreeToUpdate(AXContentTreeUpdate* update);
+
// Events from Blink are collected until they are ready to be
// sent to the browser.
std::vector<AccessibilityHostMsg_EventParams> pending_events_;
@@ -132,6 +145,12 @@ class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
AXContentTreeData>;
BlinkAXTreeSerializer serializer_;
+ using PdfAXTreeSerializer = ui::AXTreeSerializer<const ui::AXNode*,
+ ui::AXNodeData,
+ ui::AXTreeData>;
+ std::unique_ptr<PdfAXTreeSerializer> pdf_serializer_;
+ PdfAXTreeSource* pdf_tree_source_;
+
// Current location of every object, so we can detect when it moves.
base::hash_map<int, gfx::Rect> locations_;
@@ -148,9 +167,9 @@ class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
int reset_token_;
// So we can queue up tasks to be executed later.
- base::WeakPtrFactory<RendererAccessibility> weak_factory_;
+ base::WeakPtrFactory<RenderAccessibilityImpl> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(RendererAccessibility);
+ DISALLOW_COPY_AND_ASSIGN(RenderAccessibilityImpl);
};
} // namespace content
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc b/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc
index 19566520c3d..77c180742c6 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
+++ b/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <tuple>
+
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
@@ -12,7 +14,7 @@
#include "content/common/view_message_enums.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/render_view_test.h"
-#include "content/renderer/accessibility/renderer_accessibility.h"
+#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,20 +29,20 @@ using blink::WebDocument;
namespace content {
-class TestRendererAccessibility : public RendererAccessibility {
+class TestRenderAccessibilityImpl : public RenderAccessibilityImpl {
public:
- explicit TestRendererAccessibility(RenderFrameImpl* render_frame)
- : RendererAccessibility(render_frame) {
+ explicit TestRenderAccessibilityImpl(RenderFrameImpl* render_frame)
+ : RenderAccessibilityImpl(render_frame) {
}
void SendPendingAccessibilityEvents() {
- RendererAccessibility::SendPendingAccessibilityEvents();
+ RenderAccessibilityImpl::SendPendingAccessibilityEvents();
}
};
-class RendererAccessibilityTest : public RenderViewTest {
+class RenderAccessibilityImplTest : public RenderViewTest {
public:
- RendererAccessibilityTest() {}
+ RenderAccessibilityImplTest() {}
RenderViewImpl* view() {
return static_cast<RenderViewImpl*>(view_);
@@ -73,9 +75,9 @@ class RendererAccessibilityTest : public RenderViewTest {
const IPC::Message* message =
sink_->GetUniqueMessageMatching(AccessibilityHostMsg_Events::ID);
ASSERT_TRUE(message);
- base::Tuple<std::vector<AccessibilityHostMsg_EventParams>, int> param;
+ std::tuple<std::vector<AccessibilityHostMsg_EventParams>, int> param;
AccessibilityHostMsg_Events::Read(message, &param);
- *param_list = base::get<0>(param);
+ *param_list = std::get<0>(param);
}
void GetLastAccEvent(
@@ -95,12 +97,12 @@ class RendererAccessibilityTest : public RenderViewTest {
protected:
IPC::TestSink* sink_;
- DISALLOW_COPY_AND_ASSIGN(RendererAccessibilityTest);
+ DISALLOW_COPY_AND_ASSIGN(RenderAccessibilityImplTest);
};
-TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
- // The job of RendererAccessibility is to serialize the
+TEST_F(RenderAccessibilityImplTest, SendFullAccessibilityTreeOnReload) {
+ // The job of RenderAccessibilityImpl is to serialize the
// accessibility tree built by WebKit and send it to the browser.
// When the accessibility tree changes, it tries to send only
// the nodes that actually changed or were reparented. This test
@@ -115,9 +117,9 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
"</body>";
LoadHTML(html.c_str());
- // Creating a RendererAccessibility should sent the tree to the browser.
- std::unique_ptr<TestRendererAccessibility> accessibility(
- new TestRendererAccessibility(frame()));
+ // Creating a RenderAccessibilityImpl should sent the tree to the browser.
+ std::unique_ptr<TestRenderAccessibilityImpl> accessibility(
+ new TestRenderAccessibilityImpl(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
@@ -166,8 +168,8 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
}
-TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
- // Test RendererAccessibility and make sure it sends the
+TEST_F(RenderAccessibilityImplTest, HideAccessibilityObject) {
+ // Test RenderAccessibilityImpl and make sure it sends the
// proper event to the browser when an object in the tree
// is hidden, but its children are not.
std::string html =
@@ -181,8 +183,8 @@ TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
"</body>";
LoadHTML(html.c_str());
- std::unique_ptr<TestRendererAccessibility> accessibility(
- new TestRendererAccessibility(frame()));
+ std::unique_ptr<TestRenderAccessibilityImpl> accessibility(
+ new TestRenderAccessibilityImpl(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
@@ -209,7 +211,7 @@ TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
GetLastAccEvent(&event);
ASSERT_EQ(2U, event.update.nodes.size());
- // RendererAccessibility notices that 'C' is being reparented,
+ // RenderAccessibilityImpl notices that 'C' is being reparented,
// so it clears the subtree rooted at 'A', then updates 'A' and then 'C'.
EXPECT_EQ(node_a.axID(), event.update.node_id_to_clear);
EXPECT_EQ(node_a.axID(), event.update.nodes[0].id);
@@ -217,8 +219,8 @@ TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
EXPECT_EQ(2, CountAccessibilityNodesSentToBrowser());
}
-TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) {
- // Test RendererAccessibility and make sure it sends the
+TEST_F(RenderAccessibilityImplTest, ShowAccessibilityObject) {
+ // Test RenderAccessibilityImpl and make sure it sends the
// proper event to the browser when an object in the tree
// is shown, causing its own already-visible children to be
// reparented to it.
@@ -233,8 +235,8 @@ TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) {
"</body>";
LoadHTML(html.c_str());
- std::unique_ptr<TestRendererAccessibility> accessibility(
- new TestRendererAccessibility(frame()));
+ std::unique_ptr<TestRenderAccessibilityImpl> accessibility(
+ new TestRenderAccessibilityImpl(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
@@ -266,8 +268,8 @@ TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) {
EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
}
-TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
- // Test RendererAccessibility and make sure it sends the
+TEST_F(RenderAccessibilityImplTest, DetachAccessibilityObject) {
+ // Test RenderAccessibilityImpl and make sure it sends the
// proper event to the browser when an object in the tree
// is detached, but its children are not. This can happen when
// a layout occurs and an anonymous render block is no longer needed.
@@ -277,8 +279,8 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
"</body>";
LoadHTML(html.c_str());
- std::unique_ptr<TestRendererAccessibility> accessibility(
- new TestRendererAccessibility(frame()));
+ std::unique_ptr<TestRenderAccessibilityImpl> accessibility(
+ new TestRenderAccessibilityImpl(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(7, CountAccessibilityNodesSentToBrowser());
diff --git a/chromium/content/renderer/android/disambiguation_popup_helper.cc b/chromium/content/renderer/android/disambiguation_popup_helper.cc
index 93a561f3839..19f2c563ff8 100644
--- a/chromium/content/renderer/android/disambiguation_popup_helper.cc
+++ b/chromium/content/renderer/android/disambiguation_popup_helper.cc
@@ -6,6 +6,8 @@
#include <stddef.h>
+#include <algorithm>
+
#include "third_party/WebKit/public/platform/WebRect.h"
#include "ui/gfx/geometry/size_conversions.h"
@@ -33,23 +35,25 @@ const float kDisambiguationPopupMinScale = 2.0;
// a certain clickable size after zooming
float FindOptimalScaleFactor(const WebVector<WebRect>& target_rects,
float total_scale) {
- using std::min;
- using std::max;
- if (!target_rects.size()) // shall never reach
+ DCHECK_GT(total_scale, 0.0f);
+ if (!target_rects.size()) {
+ NOTREACHED();
return kDisambiguationPopupMinScale;
- float smallest_target = min(target_rects[0].width * total_scale,
- target_rects[0].height * total_scale);
+ }
+ int smallest_target = std::min(target_rects[0].width, target_rects[0].height);
for (size_t i = 1; i < target_rects.size(); i++) {
- smallest_target = min(smallest_target, target_rects[i].width * total_scale);
- smallest_target = min(smallest_target,
- target_rects[i].height * total_scale);
+ smallest_target = std::min(
+ {smallest_target, target_rects[i].width, target_rects[i].height});
}
- smallest_target = max(smallest_target, 1.0f);
- return min(kDisambiguationPopupMaxScale, max(kDisambiguationPopupMinScale,
- kDisambiguationPopupMinimumTouchSize / smallest_target)) * total_scale;
+ const float smallest_target_f = std::max(smallest_target * total_scale, 1.0f);
+ return std::min(kDisambiguationPopupMaxScale,
+ std::max(kDisambiguationPopupMinScale,
+ kDisambiguationPopupMinimumTouchSize /
+ smallest_target_f)) *
+ total_scale;
}
-void TrimEdges(int *e1, int *e2, int max_combined) {
+void TrimEdges(int* e1, int* e2, int max_combined) {
if (*e1 + *e2 <= max_combined)
return;
@@ -89,6 +93,7 @@ gfx::Rect CropZoomArea(const gfx::Rect& zoom_rect,
namespace content {
+// static
float DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
const gfx::Rect& tap_rect,
const WebVector<WebRect>& target_rects,
diff --git a/chromium/content/renderer/android/renderer_date_time_picker.cc b/chromium/content/renderer/android/renderer_date_time_picker.cc
index b936490b032..d8c0c652214 100644
--- a/chromium/content/renderer/android/renderer_date_time_picker.cc
+++ b/chromium/content/renderer/android/renderer_date_time_picker.cc
@@ -110,4 +110,8 @@ void RendererDateTimePicker::OnCancel() {
static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog();
}
+void RendererDateTimePicker::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/android/renderer_date_time_picker.h b/chromium/content/renderer/android/renderer_date_time_picker.h
index d04016bf271..2e9741aa0db 100644
--- a/chromium/content/renderer/android/renderer_date_time_picker.h
+++ b/chromium/content/renderer/android/renderer_date_time_picker.h
@@ -34,6 +34,7 @@ class RendererDateTimePicker : public RenderViewObserver {
// RenderViewObserver
bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() override;
blink::WebDateTimeChooserParams chooser_params_;
blink::WebDateTimeChooserCompletion* chooser_completion_; // Not owned by us
diff --git a/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc b/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc
deleted file mode 100644
index 7bb1dc8f727..00000000000
--- a/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/android/synchronous_compositor_external_begin_frame_source.h"
-
-#include "cc/output/begin_frame_args.h"
-#include "content/renderer/android/synchronous_compositor_registry.h"
-
-namespace content {
-
-SynchronousCompositorExternalBeginFrameSource::
- SynchronousCompositorExternalBeginFrameSource(
- int routing_id,
- SynchronousCompositorRegistry* registry)
- : routing_id_(routing_id),
- registry_(registry),
- registered_(false),
- client_(nullptr) {
- thread_checker_.DetachFromThread();
-}
-
-SynchronousCompositorExternalBeginFrameSource::
- ~SynchronousCompositorExternalBeginFrameSource() {
- DCHECK(CalledOnValidThread());
-
- if (registered_) {
- registry_->UnregisterBeginFrameSource(routing_id_, this);
- }
- DCHECK(!client_);
-}
-
-void SynchronousCompositorExternalBeginFrameSource::BeginFrame(
- const cc::BeginFrameArgs& args) {
- DCHECK(CalledOnValidThread());
- CallOnBeginFrame(args);
-}
-
-void SynchronousCompositorExternalBeginFrameSource::SetClient(
- SynchronousCompositorExternalBeginFrameSourceClient* client) {
- DCHECK(CalledOnValidThread());
- if (client_ == client)
- return;
-
- if (client_)
- client_->OnNeedsBeginFramesChange(false);
-
- client_ = client;
-
- if (client_)
- client_->OnNeedsBeginFramesChange(needs_begin_frames());
-
- // State without client is paused, and default client state is not paused.
- SetBeginFrameSourcePaused(!client_);
-}
-
-void SynchronousCompositorExternalBeginFrameSource::OnNeedsBeginFramesChanged(
- bool needs_begin_frames) {
- DCHECK(CalledOnValidThread());
- if (client_)
- client_->OnNeedsBeginFramesChange(needs_begin_frames);
-}
-
-void SynchronousCompositorExternalBeginFrameSource::AddObserver(
- cc::BeginFrameObserver* obs) {
- DCHECK(CalledOnValidThread());
- BeginFrameSourceBase::AddObserver(obs);
- if (registered_)
- return;
- registry_->RegisterBeginFrameSource(routing_id_, this);
- registered_ = true;
-}
-
-bool
-SynchronousCompositorExternalBeginFrameSource::CalledOnValidThread() const {
- return thread_checker_.CalledOnValidThread();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.h b/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.h
deleted file mode 100644
index e058c37662e..00000000000
--- a/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_
-#define CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "cc/scheduler/begin_frame_source.h"
-
-namespace content {
-
-class SynchronousCompositorRegistry;
-
-class SynchronousCompositorExternalBeginFrameSourceClient {
- public:
- virtual void OnNeedsBeginFramesChange(bool needs_begin_frames) = 0;
-
- protected:
- virtual ~SynchronousCompositorExternalBeginFrameSourceClient() {}
-};
-
-// Make sure that this is initialized and set to client before output
-// surface is bound to compositor.
-class SynchronousCompositorExternalBeginFrameSource
- : public cc::BeginFrameSourceBase {
- public:
- SynchronousCompositorExternalBeginFrameSource(
- int routing_id,
- SynchronousCompositorRegistry* registry);
- ~SynchronousCompositorExternalBeginFrameSource() override;
-
- void BeginFrame(const cc::BeginFrameArgs& args);
- void SetClient(SynchronousCompositorExternalBeginFrameSourceClient* client);
- using cc::BeginFrameSourceBase::SetBeginFrameSourcePaused;
-
- // cc::BeginFrameSourceBase implementation.
- void OnNeedsBeginFramesChanged(bool needs_begin_frames) override;
- void AddObserver(cc::BeginFrameObserver* obs) override;
-
- private:
- bool CalledOnValidThread() const;
-
- const int routing_id_;
- SynchronousCompositorRegistry* const registry_;
- bool registered_;
-
- // Not owned.
- SynchronousCompositorExternalBeginFrameSourceClient* client_;
-
- base::ThreadChecker thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorExternalBeginFrameSource);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_
diff --git a/chromium/content/renderer/android/synchronous_compositor_filter.cc b/chromium/content/renderer/android/synchronous_compositor_filter.cc
index 43b7131a2b0..a73fde1af96 100644
--- a/chromium/content/renderer/android/synchronous_compositor_filter.cc
+++ b/chromium/content/renderer/android/synchronous_compositor_filter.cc
@@ -154,32 +154,6 @@ void SynchronousCompositorFilter::UnregisterOutputSurface(
RemoveEntryIfNeeded(routing_id);
}
-void SynchronousCompositorFilter::RegisterBeginFrameSource(
- int routing_id,
- SynchronousCompositorExternalBeginFrameSource* begin_frame_source) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- DCHECK(begin_frame_source);
- Entry& entry = entry_map_[routing_id];
- DCHECK(!entry.begin_frame_source);
- entry.begin_frame_source = begin_frame_source;
- CheckIsReady(routing_id);
-}
-
-void SynchronousCompositorFilter::UnregisterBeginFrameSource(
- int routing_id,
- SynchronousCompositorExternalBeginFrameSource* begin_frame_source) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- DCHECK(begin_frame_source);
- DCHECK(ContainsKey(entry_map_, routing_id));
- Entry& entry = entry_map_[routing_id];
- DCHECK_EQ(begin_frame_source, entry.begin_frame_source);
-
- if (entry.IsReady())
- UnregisterObjects(routing_id);
- entry.begin_frame_source = nullptr;
- RemoveEntryIfNeeded(routing_id);
-}
-
void SynchronousCompositorFilter::CheckIsReady(int routing_id) {
DCHECK(compositor_task_runner_->BelongsToCurrentThread());
DCHECK(ContainsKey(entry_map_, routing_id));
@@ -187,9 +161,8 @@ void SynchronousCompositorFilter::CheckIsReady(int routing_id) {
if (filter_ready_ && entry.IsReady()) {
DCHECK(!sync_compositor_map_.contains(routing_id));
std::unique_ptr<SynchronousCompositorProxy> proxy(
- new SynchronousCompositorProxy(
- routing_id, this, entry.begin_frame_source,
- entry.synchronous_input_handler_proxy, &input_handler_));
+ new SynchronousCompositorProxy(routing_id, this,
+ entry.synchronous_input_handler_proxy));
if (entry.output_surface)
proxy->SetOutputSurface(entry.output_surface);
sync_compositor_map_.add(routing_id, std::move(proxy));
@@ -206,53 +179,11 @@ void SynchronousCompositorFilter::RemoveEntryIfNeeded(int routing_id) {
DCHECK(compositor_task_runner_->BelongsToCurrentThread());
DCHECK(ContainsKey(entry_map_, routing_id));
Entry& entry = entry_map_[routing_id];
- if (!entry.begin_frame_source && !entry.output_surface &&
- !entry.synchronous_input_handler_proxy) {
+ if (!entry.output_surface && !entry.synchronous_input_handler_proxy) {
entry_map_.erase(routing_id);
}
}
-void SynchronousCompositorFilter::SetBoundHandler(const Handler& handler) {
- compositor_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(
- &SynchronousCompositorFilter::SetBoundHandlerOnCompositorThread, this,
- handler));
-}
-
-void SynchronousCompositorFilter::RegisterRoutingID(int routing_id) {}
-void SynchronousCompositorFilter::UnregisterRoutingID(int routing_id) {}
-
-void SynchronousCompositorFilter::SetBoundHandlerOnCompositorThread(
- const Handler& handler) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- input_handler_ = handler;
-}
-
-void SynchronousCompositorFilter::DidOverscroll(
- int routing_id,
- const DidOverscrollParams& params) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- SynchronousCompositorProxy* proxy = FindProxy(routing_id);
- if (!proxy) {
- DLOG(WARNING) << "No matching proxy in DidOverScroll " << routing_id;
- return;
- }
- proxy->DidOverscroll(params);
-}
-
-void SynchronousCompositorFilter::DidStartFlinging(int routing_id) {}
-
-void SynchronousCompositorFilter::DidStopFlinging(int routing_id) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- Send(new InputHostMsg_DidStopFlinging(routing_id));
-}
-
-void SynchronousCompositorFilter::NotifyInputEventHandled(
- int routing_id,
- blink::WebInputEvent::Type type,
- InputEventAckState ack_result) {}
-
void SynchronousCompositorFilter::DidAddSynchronousHandlerProxy(
int routing_id,
ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
@@ -277,12 +208,12 @@ void SynchronousCompositorFilter::DidRemoveSynchronousHandlerProxy(
}
SynchronousCompositorFilter::Entry::Entry()
- : begin_frame_source(nullptr),
- output_surface(nullptr),
+ : output_surface(nullptr),
synchronous_input_handler_proxy(nullptr) {}
+// TODO(boliu): refactor this
bool SynchronousCompositorFilter::Entry::IsReady() {
- return begin_frame_source && synchronous_input_handler_proxy;
+ return synchronous_input_handler_proxy;
}
} // namespace content
diff --git a/chromium/content/renderer/android/synchronous_compositor_filter.h b/chromium/content/renderer/android/synchronous_compositor_filter.h
index b7cee7bbf42..a188fdbd7af 100644
--- a/chromium/content/renderer/android/synchronous_compositor_filter.h
+++ b/chromium/content/renderer/android/synchronous_compositor_filter.h
@@ -29,7 +29,6 @@ class SynchronousCompositorFilter
: public IPC::MessageFilter,
public IPC::Sender,
public SynchronousCompositorRegistry,
- public InputHandlerManagerClient,
public SynchronousInputHandlerProxyClient {
public:
SynchronousCompositorFilter(const scoped_refptr<base::SingleThreadTaskRunner>&
@@ -53,24 +52,6 @@ class SynchronousCompositorFilter
void UnregisterOutputSurface(
int routing_id,
SynchronousCompositorOutputSurface* output_surface) override;
- void RegisterBeginFrameSource(int routing_id,
- SynchronousCompositorExternalBeginFrameSource*
- begin_frame_source) override;
- void UnregisterBeginFrameSource(int routing_id,
- SynchronousCompositorExternalBeginFrameSource*
- begin_frame_source) override;
-
- // InputHandlerManagerClient overrides.
- void SetBoundHandler(const Handler& handler) override;
- void RegisterRoutingID(int routing_id) override;
- void UnregisterRoutingID(int routing_id) override;
- void DidOverscroll(int routing_id,
- const DidOverscrollParams& params) override;
- void DidStartFlinging(int routing_id) override;
- void DidStopFlinging(int routing_id) override;
- void NotifyInputEventHandled(int routing_id,
- blink::WebInputEvent::Type type,
- InputEventAckState ack_result) override;
// SynchronousInputHandlerProxyClient overrides.
void DidAddSynchronousHandlerProxy(
@@ -88,7 +69,6 @@ class SynchronousCompositorFilter
// Compositor thread methods.
void FilterReadyyOnCompositorThread();
void OnMessageReceivedOnCompositorThread(const IPC::Message& message);
- void SetBoundHandlerOnCompositorThread(const Handler& handler);
void CheckIsReady(int routing_id);
void UnregisterObjects(int routing_id);
void RemoveEntryIfNeeded(int routing_id);
@@ -105,11 +85,9 @@ class SynchronousCompositorFilter
base::ScopedPtrHashMap<int /* routing_id */,
std::unique_ptr<SynchronousCompositorProxy>>;
SyncCompositorMap sync_compositor_map_;
- Handler input_handler_;
bool filter_ready_;
struct Entry {
- SynchronousCompositorExternalBeginFrameSource* begin_frame_source;
SynchronousCompositorOutputSurface* output_surface;
ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy;
diff --git a/chromium/content/renderer/android/synchronous_compositor_output_surface.cc b/chromium/content/renderer/android/synchronous_compositor_output_surface.cc
index 119dac59883..37d3a23e90f 100644
--- a/chromium/content/renderer/android/synchronous_compositor_output_surface.cc
+++ b/chromium/content/renderer/android/synchronous_compositor_output_surface.cc
@@ -7,14 +7,17 @@
#include <vector>
#include "base/auto_reset.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 "cc/output/compositor_frame.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface_client.h"
#include "cc/output/software_output_device.h"
#include "content/common/android/sync_compositor_messages.h"
-#include "content/renderer/android/synchronous_compositor_external_begin_frame_source.h"
#include "content/renderer/android/synchronous_compositor_filter.h"
#include "content/renderer/android/synchronous_compositor_registry.h"
#include "content/renderer/gpu/frame_swap_message_queue.h"
@@ -69,17 +72,15 @@ class SynchronousCompositorOutputSurface::SoftwareDevice
};
SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
- const scoped_refptr<cc::ContextProvider>& context_provider,
- const scoped_refptr<cc::ContextProvider>& worker_context_provider,
+ scoped_refptr<cc::ContextProvider> context_provider,
+ scoped_refptr<cc::ContextProvider> worker_context_provider,
int routing_id,
uint32_t output_surface_id,
SynchronousCompositorRegistry* registry,
scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
- : cc::OutputSurface(
- context_provider,
- worker_context_provider,
- nullptr,
- std::unique_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
+ : cc::OutputSurface(std::move(context_provider),
+ std::move(worker_context_provider),
+ base::MakeUnique<SoftwareDevice>(this)),
routing_id_(routing_id),
output_surface_id_(output_surface_id),
registry_(registry),
@@ -107,6 +108,8 @@ void SynchronousCompositorOutputSurface::SetSyncClient(
SynchronousCompositorOutputSurfaceClient* compositor) {
DCHECK(CalledOnValidThread());
sync_client_ = compositor;
+ if (sync_client_)
+ Send(new SyncCompositorHostMsg_OutputSurfaceCreated(routing_id_));
}
bool SynchronousCompositorOutputSurface::OnMessageReceived(
@@ -132,7 +135,6 @@ bool SynchronousCompositorOutputSurface::BindToClient(
base::Unretained(this)));
registry_->RegisterOutputSurface(routing_id_, this);
registered_ = true;
- Send(new SyncCompositorHostMsg_OutputSurfaceCreated(routing_id_));
return true;
}
@@ -146,18 +148,20 @@ void SynchronousCompositorOutputSurface::DetachFromClient() {
CancelFallbackTick();
}
-void SynchronousCompositorOutputSurface::Reshape(const gfx::Size& size,
- float scale_factor,
- bool has_alpha) {
+void SynchronousCompositorOutputSurface::Reshape(
+ const gfx::Size& size,
+ float scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha) {
// Intentional no-op: surface size is controlled by the embedder.
}
void SynchronousCompositorOutputSurface::SwapBuffers(
- cc::CompositorFrame* frame) {
+ cc::CompositorFrame frame) {
DCHECK(CalledOnValidThread());
DCHECK(sync_client_);
if (!fallback_tick_running_) {
- sync_client_->SwapBuffers(output_surface_id_, frame);
+ sync_client_->SwapBuffers(output_surface_id_, std::move(frame));
DeliverMessages();
}
client_->DidSwapBuffers();
@@ -191,13 +195,24 @@ void SynchronousCompositorOutputSurface::Invalidate() {
fallback_tick_.Reset(
base::Bind(&SynchronousCompositorOutputSurface::FallbackTickFired,
base::Unretained(this)));
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, fallback_tick_.callback(),
base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
fallback_tick_pending_ = true;
}
}
+void SynchronousCompositorOutputSurface::BindFramebuffer() {
+ // This is a delegating output surface, no framebuffer/direct drawing support.
+ NOTREACHED();
+}
+
+uint32_t SynchronousCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
+ // This is a delegating output surface, no framebuffer/direct drawing support.
+ NOTREACHED();
+ return 0;
+}
+
void SynchronousCompositorOutputSurface::DemandDrawHw(
const gfx::Size& surface_size,
const gfx::Transform& transform,
diff --git a/chromium/content/renderer/android/synchronous_compositor_output_surface.h b/chromium/content/renderer/android/synchronous_compositor_output_surface.h
index 672cf2d234c..09720941418 100644
--- a/chromium/content/renderer/android/synchronous_compositor_output_surface.h
+++ b/chromium/content/renderer/android/synchronous_compositor_output_surface.h
@@ -42,7 +42,7 @@ class SynchronousCompositorOutputSurfaceClient {
virtual void DidActivatePendingTree() = 0;
virtual void Invalidate() = 0;
virtual void SwapBuffers(uint32_t output_surface_id,
- cc::CompositorFrame* frame) = 0;
+ cc::CompositorFrame frame) = 0;
protected:
virtual ~SynchronousCompositorOutputSurfaceClient() {}
@@ -60,8 +60,8 @@ class SynchronousCompositorOutputSurface
: NON_EXPORTED_BASE(public cc::OutputSurface) {
public:
SynchronousCompositorOutputSurface(
- const scoped_refptr<cc::ContextProvider>& context_provider,
- const scoped_refptr<cc::ContextProvider>& worker_context_provider,
+ scoped_refptr<cc::ContextProvider> context_provider,
+ scoped_refptr<cc::ContextProvider> worker_context_provider,
int routing_id,
uint32_t output_surface_id,
SynchronousCompositorRegistry* registry,
@@ -76,9 +76,12 @@ class SynchronousCompositorOutputSurface
void DetachFromClient() override;
void Reshape(const gfx::Size& size,
float scale_factor,
+ const gfx::ColorSpace& color_space,
bool has_alpha) override;
- void SwapBuffers(cc::CompositorFrame* frame) override;
+ void SwapBuffers(cc::CompositorFrame frame) override;
void Invalidate() override;
+ void BindFramebuffer() override;
+ uint32_t GetFramebufferCopyTextureFormat() override;
// Partial SynchronousCompositor API implementation.
void DemandDrawHw(const gfx::Size& surface_size,
diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy.cc b/chromium/content/renderer/android/synchronous_compositor_proxy.cc
index ae6a13135e0..6b9883b5a21 100644
--- a/chromium/content/renderer/android/synchronous_compositor_proxy.cc
+++ b/chromium/content/renderer/android/synchronous_compositor_proxy.cc
@@ -17,7 +17,6 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/events/latency_info.h"
#include "ui/gfx/skia_util.h"
namespace content {
@@ -25,14 +24,10 @@ namespace content {
SynchronousCompositorProxy::SynchronousCompositorProxy(
int routing_id,
IPC::Sender* sender,
- SynchronousCompositorExternalBeginFrameSource* begin_frame_source,
- ui::SynchronousInputHandlerProxy* input_handler_proxy,
- InputHandlerManagerClient::Handler* handler)
+ ui::SynchronousInputHandlerProxy* input_handler_proxy)
: routing_id_(routing_id),
sender_(sender),
- begin_frame_source_(begin_frame_source),
input_handler_proxy_(input_handler_proxy),
- input_handler_(handler),
use_in_process_zero_copy_software_draw_(
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSingleProcess)),
@@ -46,18 +41,15 @@ SynchronousCompositorProxy::SynchronousCompositorProxy(
max_page_scale_factor_(0.f),
need_animate_scroll_(false),
need_invalidate_count_(0u),
- need_begin_frame_(false),
did_activate_pending_tree_count_(0u) {
- DCHECK(begin_frame_source_);
DCHECK(input_handler_proxy_);
- DCHECK(input_handler_);
- begin_frame_source_->SetClient(this);
input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(this);
}
SynchronousCompositorProxy::~SynchronousCompositorProxy() {
- SetOutputSurface(nullptr);
- begin_frame_source_->SetClient(nullptr);
+ // The OutputSurface is destroyed/removed by the compositor before shutting
+ // down everything.
+ DCHECK_EQ(output_surface_, nullptr);
input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(nullptr);
}
@@ -102,14 +94,6 @@ void SynchronousCompositorProxy::UpdateRootLayerState(
}
}
-void SynchronousCompositorProxy::OnNeedsBeginFramesChange(
- bool needs_begin_frames) {
- if (need_begin_frame_ == needs_begin_frames)
- return;
- need_begin_frame_ = needs_begin_frames;
- SendAsyncRendererStateIfNeeded();
-}
-
void SynchronousCompositorProxy::Invalidate() {
++need_invalidate_count_;
SendAsyncRendererStateIfNeeded();
@@ -139,7 +123,6 @@ void SynchronousCompositorProxy::PopulateCommonParams(
params->max_page_scale_factor = max_page_scale_factor_;
params->need_animate_scroll = need_animate_scroll_;
params->need_invalidate_count = need_invalidate_count_;
- params->need_begin_frame = need_begin_frame_;
params->did_activate_pending_tree_count = did_activate_pending_tree_count_;
}
@@ -149,8 +132,8 @@ void SynchronousCompositorProxy::OnMessageReceived(
return;
IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorProxy, message)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_HandleInputEvent, HandleInputEvent)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_BeginFrame, BeginFrame)
+ IPC_MESSAGE_HANDLER(SyncCompositorMsg_SynchronizeRendererState,
+ PopulateCommonParams)
IPC_MESSAGE_HANDLER(SyncCompositorMsg_ComputeScroll, OnComputeScroll)
IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncCompositorMsg_DemandDrawHw,
DemandDrawHw)
@@ -158,7 +141,6 @@ void SynchronousCompositorProxy::OnMessageReceived(
IPC_MESSAGE_HANDLER(SyncCompositorMsg_ZeroSharedMemory, ZeroSharedMemory)
IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncCompositorMsg_DemandDrawSw,
DemandDrawSw)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_UpdateState, ProcessCommonParams)
IPC_MESSAGE_HANDLER(SyncCompositorMsg_ZoomBy, SynchronouslyZoomBy)
IPC_MESSAGE_HANDLER(SyncCompositorMsg_SetScroll, SetScroll)
IPC_END_MESSAGE_MAP()
@@ -168,44 +150,13 @@ bool SynchronousCompositorProxy::Send(IPC::Message* message) {
return sender_->Send(message);
}
-void SynchronousCompositorProxy::HandleInputEvent(
- const SyncCompositorCommonBrowserParams& common_params,
- const blink::WebInputEvent* event,
- SyncCompositorCommonRendererParams* common_renderer_params,
- InputEventAckState* ack) {
- DCHECK(!inside_receive_);
- base::AutoReset<bool> scoped_inside_receive(&inside_receive_, true);
-
- ProcessCommonParams(common_params);
- DCHECK(!input_handler_->is_null());
- ui::LatencyInfo latency;
- *ack = input_handler_->Run(routing_id_, event, &latency);
- PopulateCommonParams(common_renderer_params);
-}
-
-void SynchronousCompositorProxy::BeginFrame(
- const SyncCompositorCommonBrowserParams& common_params,
- const cc::BeginFrameArgs& args,
- SyncCompositorCommonRendererParams* common_renderer_params) {
- DCHECK(!inside_receive_);
- base::AutoReset<bool> scoped_inside_receive(&inside_receive_, true);
-
- ProcessCommonParams(common_params);
- if (need_begin_frame_) {
- begin_frame_source_->BeginFrame(args);
- }
- PopulateCommonParams(common_renderer_params);
-}
-
void SynchronousCompositorProxy::DemandDrawHw(
- const SyncCompositorCommonBrowserParams& common_params,
const SyncCompositorDemandDrawHwParams& params,
IPC::Message* reply_message) {
DCHECK(!inside_receive_);
DCHECK(reply_message);
inside_receive_ = true;
- ProcessCommonParams(common_params);
if (output_surface_) {
base::AutoReset<IPC::Message*> scoped_hardware_draw_reply(
@@ -218,29 +169,28 @@ void SynchronousCompositorProxy::DemandDrawHw(
if (inside_receive_) {
// Did not swap.
- cc::CompositorFrame empty_frame;
- SendDemandDrawHwReply(&empty_frame, 0u, reply_message);
+ SendDemandDrawHwReply(cc::CompositorFrame(), 0u, reply_message);
inside_receive_ = false;
}
}
void SynchronousCompositorProxy::SwapBuffersHw(uint32_t output_surface_id,
- cc::CompositorFrame* frame) {
+ cc::CompositorFrame frame) {
DCHECK(inside_receive_);
DCHECK(hardware_draw_reply_);
- DCHECK(frame);
- SendDemandDrawHwReply(frame, output_surface_id, hardware_draw_reply_);
+ SendDemandDrawHwReply(std::move(frame), output_surface_id,
+ hardware_draw_reply_);
inside_receive_ = false;
}
void SynchronousCompositorProxy::SendDemandDrawHwReply(
- cc::CompositorFrame* frame,
+ cc::CompositorFrame frame,
uint32_t output_surface_id,
IPC::Message* reply_message) {
SyncCompositorCommonRendererParams common_renderer_params;
PopulateCommonParams(&common_renderer_params);
SyncCompositorMsg_DemandDrawHw::WriteReplyParams(
- reply_message, common_renderer_params, output_surface_id, *frame);
+ reply_message, common_renderer_params, output_surface_id, frame);
Send(reply_message);
}
@@ -254,7 +204,6 @@ struct SynchronousCompositorProxy::SharedMemoryWithSize {
};
void SynchronousCompositorProxy::SetSharedMemory(
- const SyncCompositorCommonBrowserParams& common_params,
const SyncCompositorSetSharedMemoryParams& params,
bool* success,
SyncCompositorCommonRendererParams* common_renderer_params) {
@@ -262,7 +211,6 @@ void SynchronousCompositorProxy::SetSharedMemory(
base::AutoReset<bool> scoped_inside_receive(&inside_receive_, true);
*success = false;
- ProcessCommonParams(common_params);
if (!base::SharedMemory::IsHandleValid(params.shm_handle))
return;
@@ -276,18 +224,21 @@ void SynchronousCompositorProxy::SetSharedMemory(
}
void SynchronousCompositorProxy::ZeroSharedMemory() {
- DCHECK(!software_draw_shm_->zeroed);
+ // It is possible for this to get called twice, eg. if draw is called before
+ // the OutputSurface is ready. Just ignore duplicated calls rather than
+ // inventing a complicated system to avoid it.
+ if (software_draw_shm_->zeroed)
+ return;
+
memset(software_draw_shm_->shm.memory(), 0, software_draw_shm_->buffer_size);
software_draw_shm_->zeroed = true;
}
void SynchronousCompositorProxy::DemandDrawSw(
- const SyncCompositorCommonBrowserParams& common_params,
const SyncCompositorDemandDrawSwParams& params,
IPC::Message* reply_message) {
DCHECK(!inside_receive_);
inside_receive_ = true;
- ProcessCommonParams(common_params);
if (output_surface_) {
base::AutoReset<IPC::Message*> scoped_software_draw_reply(
&software_draw_reply_, reply_message);
@@ -302,8 +253,7 @@ void SynchronousCompositorProxy::DemandDrawSw(
}
if (inside_receive_) {
// Did not swap.
- cc::CompositorFrame empty_frame;
- SendDemandDrawSwReply(false, &empty_frame, reply_message);
+ SendDemandDrawSwReply(false, cc::CompositorFrame(), reply_message);
inside_receive_ = false;
}
}
@@ -330,40 +280,37 @@ void SynchronousCompositorProxy::DoDemandDrawSw(
output_surface_->DemandDrawSw(&canvas);
}
-void SynchronousCompositorProxy::SwapBuffersSw(cc::CompositorFrame* frame) {
+void SynchronousCompositorProxy::SwapBuffersSw(cc::CompositorFrame frame) {
DCHECK(inside_receive_);
DCHECK(software_draw_reply_);
- DCHECK(frame);
- SendDemandDrawSwReply(true, frame, software_draw_reply_);
+ SendDemandDrawSwReply(true, std::move(frame), software_draw_reply_);
inside_receive_ = false;
}
void SynchronousCompositorProxy::SendDemandDrawSwReply(
bool success,
- cc::CompositorFrame* frame,
+ cc::CompositorFrame frame,
IPC::Message* reply_message) {
SyncCompositorCommonRendererParams common_renderer_params;
PopulateCommonParams(&common_renderer_params);
SyncCompositorMsg_DemandDrawSw::WriteReplyParams(
- reply_message, success, common_renderer_params, *frame);
+ reply_message, success, common_renderer_params, frame);
Send(reply_message);
}
void SynchronousCompositorProxy::SwapBuffers(uint32_t output_surface_id,
- cc::CompositorFrame* frame) {
+ cc::CompositorFrame frame) {
DCHECK(hardware_draw_reply_ || software_draw_reply_);
DCHECK(!(hardware_draw_reply_ && software_draw_reply_));
if (hardware_draw_reply_) {
- SwapBuffersHw(output_surface_id, frame);
+ SwapBuffersHw(output_surface_id, std::move(frame));
} else if (software_draw_reply_) {
- SwapBuffersSw(frame);
+ SwapBuffersSw(std::move(frame));
}
}
void SynchronousCompositorProxy::OnComputeScroll(
- const SyncCompositorCommonBrowserParams& common_params,
base::TimeTicks animation_time) {
- ProcessCommonParams(common_params);
if (need_animate_scroll_) {
need_animate_scroll_ = false;
input_handler_proxy_->SynchronouslyAnimate(animation_time);
@@ -371,13 +318,11 @@ void SynchronousCompositorProxy::OnComputeScroll(
}
void SynchronousCompositorProxy::SynchronouslyZoomBy(
- const SyncCompositorCommonBrowserParams& common_params,
float zoom_delta,
const gfx::Point& anchor,
SyncCompositorCommonRendererParams* common_renderer_params) {
DCHECK(!inside_receive_);
base::AutoReset<bool> scoped_inside_receive(&inside_receive_, true);
- ProcessCommonParams(common_params);
input_handler_proxy_->SynchronouslyZoomBy(zoom_delta, anchor);
PopulateCommonParams(common_renderer_params);
}
@@ -390,18 +335,4 @@ void SynchronousCompositorProxy::SetScroll(
input_handler_proxy_->SynchronouslySetRootScrollOffset(total_scroll_offset_);
}
-void SynchronousCompositorProxy::DidOverscroll(
- const DidOverscrollParams& did_overscroll_params) {
- SyncCompositorCommonRendererParams params;
- PopulateCommonParams(&params);
- Send(new SyncCompositorHostMsg_OverScroll(routing_id_, params,
- did_overscroll_params));
-}
-
-void SynchronousCompositorProxy::ProcessCommonParams(
- const SyncCompositorCommonBrowserParams& common_params) {
- begin_frame_source_->SetBeginFrameSourcePaused(
- common_params.begin_frame_source_paused);
-}
-
} // namespace content
diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy.h b/chromium/content/renderer/android/synchronous_compositor_proxy.h
index d6f9e1ae996..6058aad9adc 100644
--- a/chromium/content/renderer/android/synchronous_compositor_proxy.h
+++ b/chromium/content/renderer/android/synchronous_compositor_proxy.h
@@ -10,9 +10,7 @@
#include "base/macros.h"
#include "content/common/input/input_event_ack_state.h"
-#include "content/renderer/android/synchronous_compositor_external_begin_frame_source.h"
#include "content/renderer/android/synchronous_compositor_output_surface.h"
-#include "content/renderer/input/input_handler_manager_client.h"
#include "ui/events/blink/synchronous_input_handler_proxy.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/size_f.h"
@@ -35,7 +33,6 @@ class CompositorFrame;
namespace content {
class SynchronousCompositorOutputSurface;
-struct SyncCompositorCommonBrowserParams;
struct SyncCompositorCommonRendererParams;
struct SyncCompositorDemandDrawHwParams;
struct SyncCompositorDemandDrawSwParams;
@@ -43,15 +40,12 @@ struct SyncCompositorSetSharedMemoryParams;
class SynchronousCompositorProxy
: public ui::SynchronousInputHandler,
- public SynchronousCompositorExternalBeginFrameSourceClient,
public SynchronousCompositorOutputSurfaceClient {
public:
SynchronousCompositorProxy(
int routing_id,
IPC::Sender* sender,
- SynchronousCompositorExternalBeginFrameSource* begin_frame_source,
- ui::SynchronousInputHandlerProxy* input_handler_proxy,
- InputHandlerManagerClient::Handler* handler);
+ ui::SynchronousInputHandlerProxy* input_handler_proxy);
~SynchronousCompositorProxy() override;
// ui::SynchronousInputHandler overrides.
@@ -63,73 +57,51 @@ class SynchronousCompositorProxy
float min_page_scale_factor,
float max_page_scale_factor) override;
- // SynchronousCompositorExternalBeginFrameSourceClient overrides.
- void OnNeedsBeginFramesChange(bool needs_begin_frames) override;
-
// SynchronousCompositorOutputSurfaceClient overrides.
void DidActivatePendingTree() override;
void Invalidate() override;
void SwapBuffers(uint32_t output_surface_id,
- cc::CompositorFrame* frame) override;
+ cc::CompositorFrame frame) override;
void SetOutputSurface(SynchronousCompositorOutputSurface* output_surface);
void OnMessageReceived(const IPC::Message& message);
bool Send(IPC::Message* message);
- void DidOverscroll(const DidOverscrollParams& did_overscroll_params);
private:
struct SharedMemoryWithSize;
- void ProcessCommonParams(
- const SyncCompositorCommonBrowserParams& common_params);
- void PopulateCommonParams(SyncCompositorCommonRendererParams* params) const;
-
// IPC handlers.
- void HandleInputEvent(
- const SyncCompositorCommonBrowserParams& common_params,
- const blink::WebInputEvent* event,
- SyncCompositorCommonRendererParams* common_renderer_params,
- InputEventAckState* ack);
- void BeginFrame(const SyncCompositorCommonBrowserParams& common_params,
- const cc::BeginFrameArgs& args,
- SyncCompositorCommonRendererParams* common_renderer_params);
- void OnComputeScroll(const SyncCompositorCommonBrowserParams& common_params,
- base::TimeTicks animation_time);
- void DemandDrawHw(const SyncCompositorCommonBrowserParams& common_params,
- const SyncCompositorDemandDrawHwParams& params,
+ void PopulateCommonParams(SyncCompositorCommonRendererParams* params) const;
+ void OnComputeScroll(base::TimeTicks animation_time);
+ void DemandDrawHw(const SyncCompositorDemandDrawHwParams& params,
IPC::Message* reply_message);
void SetSharedMemory(
- const SyncCompositorCommonBrowserParams& common_params,
const SyncCompositorSetSharedMemoryParams& params,
bool* success,
SyncCompositorCommonRendererParams* common_renderer_params);
void ZeroSharedMemory();
- void DemandDrawSw(const SyncCompositorCommonBrowserParams& common_params,
- const SyncCompositorDemandDrawSwParams& params,
+ void DemandDrawSw(const SyncCompositorDemandDrawSwParams& params,
IPC::Message* reply_message);
void SynchronouslyZoomBy(
- const SyncCompositorCommonBrowserParams& common_params,
float zoom_delta,
const gfx::Point& anchor,
SyncCompositorCommonRendererParams* common_renderer_params);
void SetScroll(const gfx::ScrollOffset& total_scroll_offset);
- void SwapBuffersHw(uint32_t output_surface_id, cc::CompositorFrame* frame);
- void SendDemandDrawHwReply(cc::CompositorFrame* frame,
+ void SwapBuffersHw(uint32_t output_surface_id, cc::CompositorFrame frame);
+ void SendDemandDrawHwReply(cc::CompositorFrame frame,
uint32_t output_surface_id,
IPC::Message* reply_message);
void DoDemandDrawSw(const SyncCompositorDemandDrawSwParams& params);
- void SwapBuffersSw(cc::CompositorFrame* frame);
+ void SwapBuffersSw(cc::CompositorFrame frame);
void SendDemandDrawSwReply(bool success,
- cc::CompositorFrame* frame,
+ cc::CompositorFrame frame,
IPC::Message* reply_message);
void SendAsyncRendererStateIfNeeded();
const int routing_id_;
IPC::Sender* const sender_;
- SynchronousCompositorExternalBeginFrameSource* const begin_frame_source_;
ui::SynchronousInputHandlerProxy* const input_handler_proxy_;
- InputHandlerManagerClient::Handler* const input_handler_;
const bool use_in_process_zero_copy_software_draw_;
SynchronousCompositorOutputSurface* output_surface_;
bool inside_receive_;
@@ -149,7 +121,6 @@ class SynchronousCompositorProxy
float max_page_scale_factor_;
bool need_animate_scroll_;
uint32_t need_invalidate_count_;
- bool need_begin_frame_;
uint32_t did_activate_pending_tree_count_;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorProxy);
diff --git a/chromium/content/renderer/android/synchronous_compositor_registry.h b/chromium/content/renderer/android/synchronous_compositor_registry.h
index 381d394b78b..11ba68bd656 100644
--- a/chromium/content/renderer/android/synchronous_compositor_registry.h
+++ b/chromium/content/renderer/android/synchronous_compositor_registry.h
@@ -8,7 +8,6 @@
namespace content {
-class SynchronousCompositorExternalBeginFrameSource;
class SynchronousCompositorOutputSurface;
class SynchronousCompositorRegistry {
@@ -19,12 +18,6 @@ class SynchronousCompositorRegistry {
virtual void UnregisterOutputSurface(
int routing_id,
SynchronousCompositorOutputSurface* output_surface) = 0;
- virtual void RegisterBeginFrameSource(
- int routing_id,
- SynchronousCompositorExternalBeginFrameSource* begin_frame_source) = 0;
- virtual void UnregisterBeginFrameSource(
- int routing_id,
- SynchronousCompositorExternalBeginFrameSource* begin_frame_source) = 0;
protected:
virtual ~SynchronousCompositorRegistry() {}
diff --git a/chromium/content/renderer/background_sync/background_sync_client_impl.h b/chromium/content/renderer/background_sync/background_sync_client_impl.h
index 921ca854ebd..a264ffc9514 100644
--- a/chromium/content/renderer/background_sync/background_sync_client_impl.h
+++ b/chromium/content/renderer/background_sync/background_sync_client_impl.h
@@ -26,8 +26,6 @@ class CONTENT_EXPORT BackgroundSyncClientImpl
~BackgroundSyncClientImpl() override;
private:
- using SyncCallback =
- mojo::Callback<void(blink::mojom::ServiceWorkerEventStatus)>;
explicit BackgroundSyncClientImpl(
mojo::InterfaceRequest<blink::mojom::BackgroundSyncServiceClient>
request);
diff --git a/chromium/content/renderer/bluetooth/bluetooth_dispatcher.cc b/chromium/content/renderer/bluetooth/bluetooth_dispatcher.cc
deleted file mode 100644
index 2ff8caaf74c..00000000000
--- a/chromium/content/renderer/bluetooth/bluetooth_dispatcher.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/bluetooth/bluetooth_dispatcher.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/lazy_instance.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/child/thread_safe_sender.h"
-#include "content/common/bluetooth/bluetooth_messages.h"
-#include "device/bluetooth/bluetooth_uuid.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDeviceInit.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothRemoteGATTService.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h"
-
-using blink::WebBluetoothDeviceInit;
-using blink::WebBluetoothError;
-using blink::WebBluetoothRemoteGATTService;
-using blink::WebBluetoothReadValueCallbacks;
-using blink::WebBluetoothRequestDeviceCallbacks;
-using blink::WebBluetoothScanFilter;
-using blink::WebRequestDeviceOptions;
-using blink::WebString;
-using blink::WebVector;
-
-namespace content {
-
-namespace {
-
-base::LazyInstance<base::ThreadLocalPointer<void>>::Leaky g_dispatcher_tls =
- LAZY_INSTANCE_INITIALIZER;
-
-void* const kHasBeenDeleted = reinterpret_cast<void*>(0x1);
-
-int CurrentWorkerId() {
- return WorkerThread::GetCurrentId();
-}
-
-} // namespace
-
-BluetoothDispatcher::BluetoothDispatcher(ThreadSafeSender* sender)
- : thread_safe_sender_(sender) {
- g_dispatcher_tls.Pointer()->Set(static_cast<void*>(this));
-}
-
-BluetoothDispatcher::~BluetoothDispatcher() {
- g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
-}
-
-BluetoothDispatcher* BluetoothDispatcher::GetOrCreateThreadSpecificInstance(
- ThreadSafeSender* thread_safe_sender) {
- if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
- NOTREACHED() << "Re-instantiating TLS BluetoothDispatcher.";
- g_dispatcher_tls.Pointer()->Set(NULL);
- }
- if (g_dispatcher_tls.Pointer()->Get())
- return static_cast<BluetoothDispatcher*>(g_dispatcher_tls.Pointer()->Get());
-
- BluetoothDispatcher* dispatcher = new BluetoothDispatcher(thread_safe_sender);
- if (CurrentWorkerId())
- WorkerThread::AddObserver(dispatcher);
- return dispatcher;
-}
-
-bool BluetoothDispatcher::Send(IPC::Message* msg) {
- return thread_safe_sender_->Send(msg);
-}
-
-void BluetoothDispatcher::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcher, msg)
- IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceSuccess,
- OnRequestDeviceSuccess);
- IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceError, OnRequestDeviceError);
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled) << "Unhandled message:" << msg.type();
-}
-
-void BluetoothDispatcher::requestDevice(
- int frame_routing_id,
- const WebRequestDeviceOptions& options,
- blink::WebBluetoothRequestDeviceCallbacks* callbacks) {
- int request_id = pending_requests_.Add(callbacks);
-
- // Convert |options| to its IPC form.
- std::vector<content::BluetoothScanFilter> filters(options.filters.size());
- for (size_t i = 0; i < options.filters.size(); ++i) {
- const WebBluetoothScanFilter& web_filter = options.filters[i];
- BluetoothScanFilter& filter = filters[i];
- filter.services.reserve(web_filter.services.size());
- for (const WebString& service : web_filter.services) {
- filter.services.push_back(device::BluetoothUUID(service.utf8()));
- }
- filter.name = web_filter.name.utf8();
- filter.namePrefix = web_filter.namePrefix.utf8();
- }
- std::vector<device::BluetoothUUID> optional_services;
- optional_services.reserve(options.optionalServices.size());
- for (const WebString& optional_service : options.optionalServices) {
- optional_services.push_back(device::BluetoothUUID(optional_service.utf8()));
- }
-
- Send(new BluetoothHostMsg_RequestDevice(CurrentWorkerId(), request_id,
- frame_routing_id, filters,
- optional_services));
-}
-
-void BluetoothDispatcher::WillStopCurrentWorkerThread() {
- delete this;
-}
-
-void BluetoothDispatcher::OnRequestDeviceSuccess(
- int thread_id,
- int request_id,
- const BluetoothDevice& device) {
- DCHECK(pending_requests_.Lookup(request_id)) << request_id;
-
- WebVector<WebString> uuids(device.uuids.size());
- for (size_t i = 0; i < device.uuids.size(); ++i)
- uuids[i] = WebString::fromUTF8(device.uuids[i].c_str());
-
- pending_requests_.Lookup(request_id)
- ->onSuccess(base::WrapUnique(new WebBluetoothDeviceInit(
- WebString::fromUTF8(device.id), WebString(device.name), uuids)));
- pending_requests_.Remove(request_id);
-}
-
-void BluetoothDispatcher::OnRequestDeviceError(int thread_id,
- int request_id,
- WebBluetoothError error) {
- DCHECK(pending_requests_.Lookup(request_id)) << request_id;
- pending_requests_.Lookup(request_id)->onError(WebBluetoothError(error));
- pending_requests_.Remove(request_id);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/bluetooth/bluetooth_dispatcher.h b/chromium/content/renderer/bluetooth/bluetooth_dispatcher.h
deleted file mode 100644
index e627d53ebdb..00000000000
--- a/chromium/content/renderer/bluetooth/bluetooth_dispatcher.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_BLUETOOTH_BLUETOOTH_DISPATCHER_H_
-#define CONTENT_CHILD_BLUETOOTH_BLUETOOTH_DISPATCHER_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <queue>
-
-#include "base/id_map.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/common/bluetooth/bluetooth_device.h"
-#include "content/public/child/worker_thread.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetooth.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
-
-namespace base {
-class MessageLoop;
-class TaskRunner;
-}
-
-namespace IPC {
-class Message;
-}
-
-namespace content {
-class ThreadSafeSender;
-
-// Dispatcher for child process threads which communicates to the browser's
-// BluetoothDispatcherHost.
-//
-// Instances are created for each thread as necessary by WebBluetoothImpl.
-//
-// Incoming IPC messages are received by the BluetoothMessageFilter and
-// directed to the thread specific instance of this class.
-// Outgoing messages come from WebBluetoothImpl.
-class BluetoothDispatcher : public WorkerThread::Observer {
- public:
- explicit BluetoothDispatcher(ThreadSafeSender* sender);
- ~BluetoothDispatcher() override;
-
- // Gets or Creates a BluetoothDispatcher for the current thread.
- // |thread_safe_sender| is required when constructing a BluetoothDispatcher.
- static BluetoothDispatcher* GetOrCreateThreadSpecificInstance(
- ThreadSafeSender* thread_safe_sender);
-
- // IPC Send and Receiving interface, see IPC::Sender and IPC::Listener.
- bool Send(IPC::Message* msg);
- void OnMessageReceived(const IPC::Message& msg);
-
- // Corresponding to WebBluetoothImpl methods.
- void requestDevice(int frame_routing_id,
- const blink::WebRequestDeviceOptions& options,
- blink::WebBluetoothRequestDeviceCallbacks* callbacks);
-
- // WorkerThread::Observer implementation.
- void WillStopCurrentWorkerThread() override;
-
- private:
- // IPC Handlers, see definitions in bluetooth_messages.h.
- void OnRequestDeviceSuccess(int thread_id,
- int request_id,
- const BluetoothDevice& device);
- void OnRequestDeviceError(int thread_id,
- int request_id,
- blink::WebBluetoothError error);
-
- scoped_refptr<ThreadSafeSender> thread_safe_sender_;
-
- // Tracks device requests sent to browser to match replies with callbacks.
- // Owns callback objects.
- IDMap<blink::WebBluetoothRequestDeviceCallbacks, IDMapOwnPointer>
- pending_requests_;
-
- DISALLOW_COPY_AND_ASSIGN(BluetoothDispatcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_BLUETOOTH_BLUETOOTH_DISPATCHER_H_
diff --git a/chromium/content/renderer/bluetooth/bluetooth_message_filter.cc b/chromium/content/renderer/bluetooth/bluetooth_message_filter.cc
deleted file mode 100644
index bd688da95c3..00000000000
--- a/chromium/content/renderer/bluetooth/bluetooth_message_filter.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/bluetooth/bluetooth_message_filter.h"
-
-#include "content/child/thread_safe_sender.h"
-#include "content/renderer/bluetooth/bluetooth_dispatcher.h"
-#include "ipc/ipc_message_macros.h"
-
-namespace content {
-
-BluetoothMessageFilter::BluetoothMessageFilter(ThreadSafeSender* sender)
- : WorkerThreadMessageFilter(sender) {
-}
-
-BluetoothMessageFilter::~BluetoothMessageFilter() {
-}
-
-bool BluetoothMessageFilter::ShouldHandleMessage(
- const IPC::Message& msg) const {
- return IPC_MESSAGE_CLASS(msg) == BluetoothMsgStart;
-}
-
-void BluetoothMessageFilter::OnFilteredMessageReceived(
- const IPC::Message& msg) {
- BluetoothDispatcher::GetOrCreateThreadSpecificInstance(thread_safe_sender())
- ->OnMessageReceived(msg);
-}
-
-bool BluetoothMessageFilter::GetWorkerThreadIdForMessage(
- const IPC::Message& msg,
- int* ipc_thread_id) {
- return base::PickleIterator(msg).ReadInt(ipc_thread_id);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/bluetooth/bluetooth_message_filter.h b/chromium/content/renderer/bluetooth/bluetooth_message_filter.h
deleted file mode 100644
index 365e21aeb71..00000000000
--- a/chromium/content/renderer/bluetooth/bluetooth_message_filter.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_BLUETOOTH_BLUETOOTH_MESSAGE_FILTER_H_
-#define CONTENT_CHILD_BLUETOOTH_BLUETOOTH_MESSAGE_FILTER_H_
-
-#include "base/macros.h"
-#include "content/child/worker_thread_message_filter.h"
-
-namespace content {
-
-class BluetoothMessageFilter : public WorkerThreadMessageFilter {
- public:
- explicit BluetoothMessageFilter(ThreadSafeSender* thread_safe_sender);
-
- private:
- ~BluetoothMessageFilter() override;
-
- // WorkerThreadMessageFilter:
- bool ShouldHandleMessage(const IPC::Message& msg) const override;
- void OnFilteredMessageReceived(const IPC::Message& msg) override;
- bool GetWorkerThreadIdForMessage(const IPC::Message& msg,
- int* ipc_thread_id) override;
-
- DISALLOW_COPY_AND_ASSIGN(BluetoothMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_BLUETOOTH_BLUETOOTH_MESSAGE_FILTER_H_
diff --git a/chromium/content/renderer/bluetooth/bluetooth_type_converters.cc b/chromium/content/renderer/bluetooth/bluetooth_type_converters.cc
new file mode 100644
index 00000000000..c7bf1a79489
--- /dev/null
+++ b/chromium/content/renderer/bluetooth/bluetooth_type_converters.cc
@@ -0,0 +1,60 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/bluetooth/bluetooth_type_converters.h"
+
+#include "content/child/mojo/type_converters.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h"
+
+namespace mojo {
+
+// static
+blink::mojom::WebBluetoothScanFilterPtr TypeConverter<
+ blink::mojom::WebBluetoothScanFilterPtr,
+ blink::WebBluetoothScanFilter>::Convert(const blink::WebBluetoothScanFilter&
+ web_filter) {
+ blink::mojom::WebBluetoothScanFilterPtr filter =
+ blink::mojom::WebBluetoothScanFilter::New();
+
+ if (!web_filter.services.isEmpty())
+ filter->services =
+ Array<base::Optional<device::BluetoothUUID>>::From(web_filter.services);
+
+ if (web_filter.hasName)
+ filter->name = String::From(web_filter.name);
+
+ if (!web_filter.namePrefix.isEmpty())
+ filter->name_prefix = String::From(web_filter.namePrefix);
+ return filter;
+}
+
+// static
+blink::mojom::WebBluetoothRequestDeviceOptionsPtr
+TypeConverter<blink::mojom::WebBluetoothRequestDeviceOptionsPtr,
+ blink::WebRequestDeviceOptions>::
+ Convert(const blink::WebRequestDeviceOptions& web_options) {
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options =
+ blink::mojom::WebBluetoothRequestDeviceOptions::New();
+
+ options->filters = mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>::From(
+ web_options.filters);
+ options->optional_services =
+ mojo::Array<base::Optional<device::BluetoothUUID>>::From(
+ web_options.optionalServices);
+ return options;
+}
+
+// static
+base::Optional<device::BluetoothUUID>
+TypeConverter<base::Optional<device::BluetoothUUID>, blink::WebString>::Convert(
+ const blink::WebString& web_string) {
+ base::Optional<device::BluetoothUUID> uuid =
+ device::BluetoothUUID(web_string.utf8());
+
+ DCHECK(uuid->IsValid());
+
+ return uuid;
+}
+
+} // namespace mojo
diff --git a/chromium/content/renderer/bluetooth/bluetooth_type_converters.h b/chromium/content/renderer/bluetooth/bluetooth_type_converters.h
new file mode 100644
index 00000000000..2b6e5263d4f
--- /dev/null
+++ b/chromium/content/renderer/bluetooth/bluetooth_type_converters.h
@@ -0,0 +1,43 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_BLUETOOTH_BLUETOOTH_TYPE_CONVERTERS_H_
+#define CONTENT_RENDERER_BLUETOOTH_BLUETOOTH_TYPE_CONVERTERS_H_
+
+#include "base/optional.h"
+#include "device/bluetooth/bluetooth_uuid.h"
+#include "mojo/public/cpp/bindings/type_converter.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+
+namespace blink {
+struct WebBluetoothScanFilter;
+struct WebRequestDeviceOptions;
+}
+
+namespace mojo {
+
+template <>
+struct TypeConverter<blink::mojom::WebBluetoothScanFilterPtr,
+ blink::WebBluetoothScanFilter> {
+ static blink::mojom::WebBluetoothScanFilterPtr Convert(
+ const blink::WebBluetoothScanFilter& web_filter);
+};
+
+template <>
+struct TypeConverter<blink::mojom::WebBluetoothRequestDeviceOptionsPtr,
+ blink::WebRequestDeviceOptions> {
+ static blink::mojom::WebBluetoothRequestDeviceOptionsPtr Convert(
+ const blink::WebRequestDeviceOptions& web_options);
+};
+
+template <>
+struct TypeConverter<base::Optional<device::BluetoothUUID>, blink::WebString> {
+ static base::Optional<device::BluetoothUUID> Convert(
+ const blink::WebString& web_string);
+};
+
+} // namespace mojo
+
+#endif // CONTENT_RENDERER_BLUETOOTH_BLUETOOTH_TYPE_CONVERTERS_H_
diff --git a/chromium/content/renderer/bluetooth/web_bluetooth_impl.cc b/chromium/content/renderer/bluetooth/web_bluetooth_impl.cc
index 2f4da53dcdf..f245362d225 100644
--- a/chromium/content/renderer/bluetooth/web_bluetooth_impl.cc
+++ b/chromium/content/renderer/bluetooth/web_bluetooth_impl.cc
@@ -9,26 +9,24 @@
#include <vector>
#include "base/memory/ptr_util.h"
+#include "base/optional.h"
#include "content/child/mojo/type_converters.h"
#include "content/child/thread_safe_sender.h"
-#include "content/public/common/service_registry.h"
-#include "content/renderer/bluetooth/bluetooth_dispatcher.h"
+#include "content/renderer/bluetooth/bluetooth_type_converters.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/array.h"
+#include "services/shell/public/cpp/interface_provider.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDevice.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDeviceInit.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothRemoteGATTCharacteristic.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothRemoteGATTCharacteristicInit.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothRemoteGATTService.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h"
namespace content {
-WebBluetoothImpl::WebBluetoothImpl(ServiceRegistry* service_registry,
- ThreadSafeSender* thread_safe_sender,
- int frame_routing_id)
- : service_registry_(service_registry),
- binding_(this),
- thread_safe_sender_(thread_safe_sender),
- frame_routing_id_(frame_routing_id) {}
+WebBluetoothImpl::WebBluetoothImpl(shell::InterfaceProvider* remote_interfaces)
+ : remote_interfaces_(remote_interfaces), binding_(this) {}
WebBluetoothImpl::~WebBluetoothImpl() {
}
@@ -36,7 +34,11 @@ WebBluetoothImpl::~WebBluetoothImpl() {
void WebBluetoothImpl::requestDevice(
const blink::WebRequestDeviceOptions& options,
blink::WebBluetoothRequestDeviceCallbacks* callbacks) {
- GetDispatcher()->requestDevice(frame_routing_id_, options, callbacks);
+ GetWebBluetoothService().RequestDevice(
+ blink::mojom::WebBluetoothRequestDeviceOptions::From(options),
+ base::Bind(&WebBluetoothImpl::OnRequestDeviceComplete,
+ base::Unretained(this),
+ base::Passed(base::WrapUnique(callbacks))));
}
void WebBluetoothImpl::connect(
@@ -60,13 +62,18 @@ void WebBluetoothImpl::disconnect(const blink::WebString& device_id) {
mojo::String::From(device_id));
}
-void WebBluetoothImpl::getPrimaryService(
+void WebBluetoothImpl::getPrimaryServices(
const blink::WebString& device_id,
- const blink::WebString& service_uuid,
- blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) {
- GetWebBluetoothService().RemoteServerGetPrimaryService(
- mojo::String::From(device_id), mojo::String::From(service_uuid),
- base::Bind(&WebBluetoothImpl::OnGetPrimaryServiceComplete,
+
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ const blink::WebString& services_uuid,
+ blink::WebBluetoothGetPrimaryServicesCallbacks* callbacks) {
+ GetWebBluetoothService().RemoteServerGetPrimaryServices(
+ mojo::String::From(device_id), quantity,
+ services_uuid.isEmpty()
+ ? base::nullopt
+ : base::make_optional(device::BluetoothUUID(services_uuid.utf8())),
+ base::Bind(&WebBluetoothImpl::OnGetPrimaryServicesComplete,
base::Unretained(this), device_id,
base::Passed(base::WrapUnique(callbacks))));
}
@@ -78,8 +85,10 @@ void WebBluetoothImpl::getCharacteristics(
blink::WebBluetoothGetCharacteristicsCallbacks* callbacks) {
GetWebBluetoothService().RemoteServiceGetCharacteristics(
mojo::String::From(service_instance_id), quantity,
- characteristics_uuid.isEmpty() ? nullptr
- : mojo::String::From(characteristics_uuid),
+ characteristics_uuid.isEmpty()
+ ? base::nullopt
+ : base::make_optional(
+ device::BluetoothUUID(characteristics_uuid.utf8())),
base::Bind(&WebBluetoothImpl::OnGetCharacteristicsComplete,
base::Unretained(this), service_instance_id,
base::Passed(base::WrapUnique(callbacks))));
@@ -154,11 +163,32 @@ void WebBluetoothImpl::RemoteCharacteristicValueChanged(
value.PassStorage()));
}
+void WebBluetoothImpl::OnRequestDeviceComplete(
+ std::unique_ptr<blink::WebBluetoothRequestDeviceCallbacks> callbacks,
+ const blink::mojom::WebBluetoothError error,
+ blink::mojom::WebBluetoothDevicePtr device) {
+ if (error == blink::mojom::WebBluetoothError::SUCCESS) {
+ blink::WebVector<blink::WebString> uuids(device->uuids.size());
+ for (size_t i = 0; i < device->uuids.size(); ++i)
+ uuids[i] = blink::WebString::fromUTF8(device->uuids[i]);
+
+ callbacks->onSuccess(base::WrapUnique(new blink::WebBluetoothDeviceInit(
+ blink::WebString::fromUTF8(device->id),
+ blink::WebString::fromUTF8(device->name), uuids)));
+ } else {
+ callbacks->onError(error);
+ }
+}
+
void WebBluetoothImpl::GattServerDisconnected(const mojo::String& device_id) {
auto device_iter = connected_devices_.find(device_id);
if (device_iter != connected_devices_.end()) {
- device_iter->second->dispatchGattServerDisconnected();
+ // Remove device from the map before calling dispatchGattServerDisconnected
+ // to avoid removing a device the gattserverdisconnected event handler might
+ // have re-connected.
+ blink::WebBluetoothDevice* device = device_iter->second;
connected_devices_.erase(device_iter);
+ device->dispatchGattServerDisconnected();
}
}
@@ -173,17 +203,23 @@ void WebBluetoothImpl::OnConnectComplete(
}
}
-void WebBluetoothImpl::OnGetPrimaryServiceComplete(
+void WebBluetoothImpl::OnGetPrimaryServicesComplete(
const blink::WebString& device_id,
- std::unique_ptr<blink::WebBluetoothGetPrimaryServiceCallbacks> callbacks,
+ std::unique_ptr<blink::WebBluetoothGetPrimaryServicesCallbacks> callbacks,
blink::mojom::WebBluetoothError error,
- blink::mojom::WebBluetoothRemoteGATTServicePtr service) {
+ mojo::Array<blink::mojom::WebBluetoothRemoteGATTServicePtr> services) {
if (error == blink::mojom::WebBluetoothError::SUCCESS) {
- callbacks->onSuccess(
- base::WrapUnique(new blink::WebBluetoothRemoteGATTService(
- blink::WebString::fromUTF8(service->instance_id),
- blink::WebString::fromUTF8(service->uuid), true /* isPrimary */,
- device_id)));
+ // TODO(dcheng): This WebVector should use smart pointers.
+ blink::WebVector<blink::WebBluetoothRemoteGATTService*> promise_services(
+ services.size());
+
+ for (size_t i = 0; i < services.size(); i++) {
+ promise_services[i] = new blink::WebBluetoothRemoteGATTService(
+ blink::WebString::fromUTF8(services[i]->instance_id),
+ blink::WebString::fromUTF8(services[i]->uuid), true /* isPrimary */,
+ device_id);
+ }
+ callbacks->onSuccess(promise_services);
} else {
callbacks->onError(error);
}
@@ -260,15 +296,9 @@ void WebBluetoothImpl::DispatchCharacteristicValueChanged(
}
}
-BluetoothDispatcher* WebBluetoothImpl::GetDispatcher() {
- return BluetoothDispatcher::GetOrCreateThreadSpecificInstance(
- thread_safe_sender_.get());
-}
-
blink::mojom::WebBluetoothService& WebBluetoothImpl::GetWebBluetoothService() {
if (!web_bluetooth_service_) {
- service_registry_->ConnectToRemoteService(
- mojo::GetProxy(&web_bluetooth_service_));
+ remote_interfaces_->GetInterface(mojo::GetProxy(&web_bluetooth_service_));
// Create an associated interface ptr and pass it to the WebBluetoothService
// so that it can send us events without us prompting.
blink::mojom::WebBluetoothServiceClientAssociatedPtrInfo ptr_info;
diff --git a/chromium/content/renderer/bluetooth/web_bluetooth_impl.h b/chromium/content/renderer/bluetooth/web_bluetooth_impl.h
index fae4ad485ee..13d7c7b9a18 100644
--- a/chromium/content/renderer/bluetooth/web_bluetooth_impl.h
+++ b/chromium/content/renderer/bluetooth/web_bluetooth_impl.h
@@ -25,11 +25,14 @@ namespace blink {
class WebBluetoothRemoteGATTCharacteristic;
}
+namespace shell {
+class InterfaceProvider;
+}
+
namespace content {
class BluetoothDispatcher;
class ThreadSafeSender;
-class ServiceRegistry;
// Implementation of blink::WebBluetooth. Passes calls through to the thread
// specific BluetoothDispatcher.
@@ -37,9 +40,7 @@ class CONTENT_EXPORT WebBluetoothImpl
: NON_EXPORTED_BASE(public blink::mojom::WebBluetoothServiceClient),
NON_EXPORTED_BASE(public blink::WebBluetooth) {
public:
- WebBluetoothImpl(ServiceRegistry* service_registry,
- ThreadSafeSender* thread_safe_sender,
- int frame_routing_id);
+ WebBluetoothImpl(shell::InterfaceProvider* remote_interfaces);
~WebBluetoothImpl() override;
// blink::WebBluetooth interface:
@@ -51,10 +52,11 @@ class CONTENT_EXPORT WebBluetoothImpl
blink::WebBluetoothDevice* device,
blink::WebBluetoothRemoteGATTServerConnectCallbacks* callbacks) override;
void disconnect(const blink::WebString& device_id) override;
- void getPrimaryService(
+ void getPrimaryServices(
const blink::WebString& device_id,
- const blink::WebString& service_uuid,
- blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) override;
+ blink::mojom::WebBluetoothGATTQueryQuantity quantity,
+ const blink::WebString& services_uuid,
+ blink::WebBluetoothGetPrimaryServicesCallbacks* callbacks) override;
void getCharacteristics(
const blink::WebString& service_instance_id,
blink::mojom::WebBluetoothGATTQueryQuantity quantity,
@@ -87,15 +89,19 @@ class CONTENT_EXPORT WebBluetoothImpl
void GattServerDisconnected(const mojo::String& device_id) override;
// Callbacks for WebBluetoothService calls:
+ void OnRequestDeviceComplete(
+ std::unique_ptr<blink::WebBluetoothRequestDeviceCallbacks> callbacks,
+ const blink::mojom::WebBluetoothError error,
+ blink::mojom::WebBluetoothDevicePtr device);
void OnConnectComplete(
std::unique_ptr<blink::WebBluetoothRemoteGATTServerConnectCallbacks>
callbacks,
blink::mojom::WebBluetoothError error);
- void OnGetPrimaryServiceComplete(
+ void OnGetPrimaryServicesComplete(
const blink::WebString& device_id,
- std::unique_ptr<blink::WebBluetoothGetPrimaryServiceCallbacks> callbacks,
+ std::unique_ptr<blink::WebBluetoothGetPrimaryServicesCallbacks> callbacks,
blink::mojom::WebBluetoothError error,
- blink::mojom::WebBluetoothRemoteGATTServicePtr service);
+ mojo::Array<blink::mojom::WebBluetoothRemoteGATTServicePtr> services);
void OnGetCharacteristicsComplete(
const blink::WebString& service_instance_id,
std::unique_ptr<blink::WebBluetoothGetCharacteristicsCallbacks> callbacks,
@@ -120,10 +126,8 @@ class CONTENT_EXPORT WebBluetoothImpl
const std::string& characteristic_instance_id,
const std::vector<uint8_t>& value);
- BluetoothDispatcher* GetDispatcher();
-
blink::mojom::WebBluetoothService& GetWebBluetoothService();
- ServiceRegistry* const service_registry_;
+ shell::InterfaceProvider* const remote_interfaces_;
blink::mojom::WebBluetoothServicePtr web_bluetooth_service_;
// Map of characteristic_instance_ids to
@@ -142,9 +146,6 @@ class CONTENT_EXPORT WebBluetoothImpl
// Binding associated with |web_bluetooth_service_|.
mojo::AssociatedBinding<blink::mojom::WebBluetoothServiceClient> binding_;
- const scoped_refptr<ThreadSafeSender> thread_safe_sender_;
- const int frame_routing_id_;
-
DISALLOW_COPY_AND_ASSIGN(WebBluetoothImpl);
};
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.cc b/chromium/content/renderer/browser_plugin/browser_plugin.cc
index 76e71752418..75d15c837cc 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.cc
@@ -325,7 +325,7 @@ void BrowserPlugin::destroy() {
render_frame ? render_frame->GetRenderView() : nullptr);
if (render_view)
render_view->mouse_lock_dispatcher()->OnLockTargetDestroyed(this);
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
v8::Local<v8::Object> BrowserPlugin::v8ScriptableObject(v8::Isolate* isolate) {
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.h b/chromium/content/renderer/browser_plugin/browser_plugin.h
index 6cd8bebea23..99092e4ba99 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.h
@@ -23,7 +23,7 @@ struct BrowserPluginHostMsg_ResizeGuest_Params;
struct FrameMsg_BuffersSwapped_Params;
namespace cc {
-struct SurfaceId;
+class SurfaceId;
struct SurfaceSequence;
}
diff --git a/chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc b/chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc
index 5bc3521dea1..a490e4c69b5 100644
--- a/chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc
+++ b/chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc
@@ -82,6 +82,9 @@ ServiceWorkerResponse ResponseFromWebResponse(
const blink::WebServiceWorkerResponse& web_response) {
ServiceWorkerHeaderMap headers;
GetServiceWorkerHeaderMapFromWebResponse(web_response, &headers);
+ ServiceWorkerHeaderList cors_exposed_header_names;
+ GetCorsExposedHeaderNamesFromWebResponse(web_response,
+ &cors_exposed_header_names);
// We don't support streaming for cache.
DCHECK(web_response.streamURL().isEmpty());
return ServiceWorkerResponse(
@@ -93,7 +96,7 @@ ServiceWorkerResponse ResponseFromWebResponse(
blink::WebServiceWorkerResponseErrorUnknown,
base::Time::FromInternalValue(web_response.responseTime()),
!web_response.cacheStorageCacheName().isNull(),
- web_response.cacheStorageCacheName().utf8());
+ web_response.cacheStorageCacheName().utf8(), cors_exposed_header_names);
}
CacheStorageCacheQueryParams QueryParamsFromWebQueryParams(
@@ -655,6 +658,13 @@ void CacheStorageDispatcher::PopulateWebResponseFromResponse(
response.is_in_cache_storage
? blink::WebString::fromUTF8(response.cache_storage_cache_name)
: blink::WebString());
+ blink::WebVector<blink::WebString> headers(
+ response.cors_exposed_header_names.size());
+ std::transform(
+ response.cors_exposed_header_names.begin(),
+ response.cors_exposed_header_names.end(), headers.begin(),
+ [](const std::string& h) { return blink::WebString::fromLatin1(h); });
+ web_response->setCorsExposedHeaderNames(headers);
for (const auto& i : response.headers) {
web_response->setHeader(base::ASCIIToUTF16(i.first),
diff --git a/chromium/content/renderer/raster_worker_pool.cc b/chromium/content/renderer/categorized_worker_pool.cc
index 8c50e01b3b9..41814b4bcd3 100644
--- a/chromium/content/renderer/raster_worker_pool.cc
+++ b/chromium/content/renderer/categorized_worker_pool.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/renderer/raster_worker_pool.h"
+#include "content/renderer/categorized_worker_pool.h"
#include <string>
#include <utility>
@@ -17,15 +17,16 @@
namespace content {
namespace {
-// A thread which forwards to RasterWorkerPool::Run with the runnable
+// A thread which forwards to CategorizedWorkerPool::Run with the runnable
// categories.
-class RasterWorkerPoolThread : public base::SimpleThread {
+class CategorizedWorkerPoolThread : public base::SimpleThread {
public:
- RasterWorkerPoolThread(const std::string& name_prefix,
- const Options& options,
- RasterWorkerPool* pool,
- std::vector<cc::TaskCategory> categories,
- base::ConditionVariable* has_ready_to_run_tasks_cv)
+ CategorizedWorkerPoolThread(
+ const std::string& name_prefix,
+ const Options& options,
+ CategorizedWorkerPool* pool,
+ std::vector<cc::TaskCategory> categories,
+ base::ConditionVariable* has_ready_to_run_tasks_cv)
: SimpleThread(name_prefix, options),
pool_(pool),
categories_(categories),
@@ -34,18 +35,18 @@ class RasterWorkerPoolThread : public base::SimpleThread {
void Run() override { pool_->Run(categories_, has_ready_to_run_tasks_cv_); }
private:
- RasterWorkerPool* const pool_;
+ CategorizedWorkerPool* const pool_;
const std::vector<cc::TaskCategory> categories_;
base::ConditionVariable* const has_ready_to_run_tasks_cv_;
};
} // namespace
-// A sequenced task runner which posts tasks to a RasterWorkerPool.
-class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
+// A sequenced task runner which posts tasks to a CategorizedWorkerPool.
+class CategorizedWorkerPool::CategorizedWorkerPoolSequencedTaskRunner
: public base::SequencedTaskRunner {
public:
- explicit RasterWorkerPoolSequencedTaskRunner(
+ explicit CategorizedWorkerPoolSequencedTaskRunner(
cc::TaskGraphRunner* task_graph_runner)
: task_graph_runner_(task_graph_runner),
namespace_token_(task_graph_runner->GetNamespaceToken()) {}
@@ -95,7 +96,7 @@ class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
}
private:
- ~RasterWorkerPoolSequencedTaskRunner() override {
+ ~CategorizedWorkerPoolSequencedTaskRunner() override {
task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
task_graph_runner_->CollectCompletedTasks(namespace_token_,
&completed_tasks_);
@@ -117,14 +118,14 @@ class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
cc::Task::Vector completed_tasks_;
};
-RasterWorkerPool::RasterWorkerPool()
+CategorizedWorkerPool::CategorizedWorkerPool()
: namespace_token_(GetNamespaceToken()),
has_ready_to_run_foreground_tasks_cv_(&lock_),
has_ready_to_run_background_tasks_cv_(&lock_),
has_namespaces_with_finished_running_tasks_cv_(&lock_),
shutdown_(false) {}
-void RasterWorkerPool::Start(int num_threads) {
+void CategorizedWorkerPool::Start(int num_threads) {
DCHECK(threads_.empty());
// Start |num_threads| threads for foreground work, including nonconcurrent
@@ -134,7 +135,7 @@ void RasterWorkerPool::Start(int num_threads) {
foreground_categories.push_back(cc::TASK_CATEGORY_FOREGROUND);
for (int i = 0; i < num_threads; i++) {
- std::unique_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
+ std::unique_ptr<base::SimpleThread> thread(new CategorizedWorkerPoolThread(
base::StringPrintf("CompositorTileWorker%u",
static_cast<unsigned>(threads_.size() + 1))
.c_str(),
@@ -154,14 +155,14 @@ void RasterWorkerPool::Start(int num_threads) {
thread_options.set_priority(base::ThreadPriority::BACKGROUND);
#endif
- std::unique_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
+ std::unique_ptr<base::SimpleThread> thread(new CategorizedWorkerPoolThread(
"CompositorTileWorkerBackground", thread_options, this,
background_categories, &has_ready_to_run_background_tasks_cv_));
thread->Start();
threads_.push_back(std::move(thread));
}
-void RasterWorkerPool::Shutdown() {
+void CategorizedWorkerPool::Shutdown() {
WaitForTasksToFinishRunning(namespace_token_);
CollectCompletedTasks(namespace_token_, &completed_tasks_);
// Shutdown raster threads.
@@ -185,7 +186,7 @@ void RasterWorkerPool::Shutdown() {
}
// Overridden from base::TaskRunner:
-bool RasterWorkerPool::PostDelayedTask(
+bool CategorizedWorkerPool::PostDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) {
@@ -218,12 +219,13 @@ bool RasterWorkerPool::PostDelayedTask(
return true;
}
-bool RasterWorkerPool::RunsTasksOnCurrentThread() const {
+bool CategorizedWorkerPool::RunsTasksOnCurrentThread() const {
return true;
}
-void RasterWorkerPool::Run(const std::vector<cc::TaskCategory>& categories,
- base::ConditionVariable* has_ready_to_run_tasks_cv) {
+void CategorizedWorkerPool::Run(
+ const std::vector<cc::TaskCategory>& categories,
+ base::ConditionVariable* has_ready_to_run_tasks_cv) {
base::AutoLock lock(lock_);
while (true) {
@@ -243,7 +245,7 @@ void RasterWorkerPool::Run(const std::vector<cc::TaskCategory>& categories,
}
}
-void RasterWorkerPool::FlushForTesting() {
+void CategorizedWorkerPool::FlushForTesting() {
base::AutoLock lock(lock_);
while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) {
@@ -252,21 +254,21 @@ void RasterWorkerPool::FlushForTesting() {
}
scoped_refptr<base::SequencedTaskRunner>
-RasterWorkerPool::CreateSequencedTaskRunner() {
- return new RasterWorkerPoolSequencedTaskRunner(this);
+CategorizedWorkerPool::CreateSequencedTaskRunner() {
+ return new CategorizedWorkerPoolSequencedTaskRunner(this);
}
-RasterWorkerPool::~RasterWorkerPool() {}
+CategorizedWorkerPool::~CategorizedWorkerPool() {}
-cc::NamespaceToken RasterWorkerPool::GetNamespaceToken() {
+cc::NamespaceToken CategorizedWorkerPool::GetNamespaceToken() {
base::AutoLock lock(lock_);
return work_queue_.GetNamespaceToken();
}
-void RasterWorkerPool::ScheduleTasks(cc::NamespaceToken token,
- cc::TaskGraph* graph) {
+void CategorizedWorkerPool::ScheduleTasks(cc::NamespaceToken token,
+ cc::TaskGraph* graph) {
TRACE_EVENT2("disabled-by-default-cc.debug",
- "RasterWorkerPool::ScheduleTasks", "num_nodes",
+ "CategorizedWorkerPool::ScheduleTasks", "num_nodes",
graph->nodes.size(), "num_edges", graph->edges.size());
{
base::AutoLock lock(lock_);
@@ -274,8 +276,9 @@ void RasterWorkerPool::ScheduleTasks(cc::NamespaceToken token,
}
}
-void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token,
- cc::TaskGraph* graph) {
+void CategorizedWorkerPool::ScheduleTasksWithLockAcquired(
+ cc::NamespaceToken token,
+ cc::TaskGraph* graph) {
DCHECK(token.IsValid());
DCHECK(!cc::TaskGraphWorkQueue::DependencyMismatch(graph));
DCHECK(!shutdown_);
@@ -286,9 +289,10 @@ void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token,
SignalHasReadyToRunTasksWithLockAcquired();
}
-void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
+void CategorizedWorkerPool::WaitForTasksToFinishRunning(
+ cc::NamespaceToken token) {
TRACE_EVENT0("disabled-by-default-cc.debug",
- "RasterWorkerPool::WaitForTasksToFinishRunning");
+ "CategorizedWorkerPool::WaitForTasksToFinishRunning");
DCHECK(token.IsValid());
@@ -310,11 +314,11 @@ void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
}
}
-void RasterWorkerPool::CollectCompletedTasks(
+void CategorizedWorkerPool::CollectCompletedTasks(
cc::NamespaceToken token,
cc::Task::Vector* completed_tasks) {
TRACE_EVENT0("disabled-by-default-cc.debug",
- "RasterWorkerPool::CollectCompletedTasks");
+ "CategorizedWorkerPool::CollectCompletedTasks");
{
base::AutoLock lock(lock_);
@@ -322,14 +326,14 @@ void RasterWorkerPool::CollectCompletedTasks(
}
}
-void RasterWorkerPool::CollectCompletedTasksWithLockAcquired(
+void CategorizedWorkerPool::CollectCompletedTasksWithLockAcquired(
cc::NamespaceToken token,
cc::Task::Vector* completed_tasks) {
DCHECK(token.IsValid());
work_queue_.CollectCompletedTasks(token, completed_tasks);
}
-bool RasterWorkerPool::RunTaskWithLockAcquired(
+bool CategorizedWorkerPool::RunTaskWithLockAcquired(
const std::vector<cc::TaskCategory>& categories) {
for (const auto& category : categories) {
if (ShouldRunTaskForCategoryWithLockAcquired(category)) {
@@ -340,7 +344,7 @@ bool RasterWorkerPool::RunTaskWithLockAcquired(
return false;
}
-void RasterWorkerPool::RunTaskInCategoryWithLockAcquired(
+void CategorizedWorkerPool::RunTaskInCategoryWithLockAcquired(
cc::TaskCategory category) {
TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask");
@@ -366,7 +370,7 @@ void RasterWorkerPool::RunTaskInCategoryWithLockAcquired(
has_namespaces_with_finished_running_tasks_cv_.Signal();
}
-bool RasterWorkerPool::ShouldRunTaskForCategoryWithLockAcquired(
+bool CategorizedWorkerPool::ShouldRunTaskForCategoryWithLockAcquired(
cc::TaskCategory category) {
lock_.AssertAcquired();
@@ -399,7 +403,7 @@ bool RasterWorkerPool::ShouldRunTaskForCategoryWithLockAcquired(
return true;
}
-void RasterWorkerPool::SignalHasReadyToRunTasksWithLockAcquired() {
+void CategorizedWorkerPool::SignalHasReadyToRunTasksWithLockAcquired() {
lock_.AssertAcquired();
if (ShouldRunTaskForCategoryWithLockAcquired(cc::TASK_CATEGORY_FOREGROUND) ||
@@ -413,15 +417,15 @@ void RasterWorkerPool::SignalHasReadyToRunTasksWithLockAcquired() {
}
}
-RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
+CategorizedWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
: closure_(closure) {}
// Overridden from cc::Task:
-void RasterWorkerPool::ClosureTask::RunOnWorkerThread() {
+void CategorizedWorkerPool::ClosureTask::RunOnWorkerThread() {
closure_.Run();
closure_.Reset();
}
-RasterWorkerPool::ClosureTask::~ClosureTask() {}
+CategorizedWorkerPool::ClosureTask::~ClosureTask() {}
} // namespace content
diff --git a/chromium/content/renderer/raster_worker_pool.h b/chromium/content/renderer/categorized_worker_pool.h
index 10c312be68b..2f75f2183f2 100644
--- a/chromium/content/renderer/raster_worker_pool.h
+++ b/chromium/content/renderer/categorized_worker_pool.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_RENDERER_RASTER_WORKER_POOL_H_
-#define CONTENT_RENDERER_RASTER_WORKER_POOL_H_
+#ifndef CONTENT_RENDERER_CATEGORIZED_WORKER_POOL_H_
+#define CONTENT_RENDERER_CATEGORIZED_WORKER_POOL_H_
#include <memory>
@@ -21,18 +21,18 @@
namespace content {
-// A pool of threads used to run raster work.
-// Work can be scheduled on the threads using different interfaces.
-// The pool itself implements TaskRunner interface and tasks posted via that
-// interface might run in parallel.
-// CreateSequencedTaskRunner creates a sequenced task runner that might run in
-// parallel with other instances of sequenced task runners.
-// It's also possible to get the underlying TaskGraphRunner to schedule a graph
-// of tasks with their dependencies.
-class CONTENT_EXPORT RasterWorkerPool : public base::TaskRunner,
- public cc::TaskGraphRunner {
+// A pool of threads used to run categorized work. The work can be scheduled on
+// the threads using different interfaces.
+// 1. The pool itself implements TaskRunner interface and tasks posted via that
+// interface might run in parallel.
+// 2. The pool also implements TaskGraphRunner interface which allows to
+// schedule a graph of tasks with their dependencies.
+// 3. CreateSequencedTaskRunner() creates a sequenced task runner that might run
+// in parallel with other instances of sequenced task runners.
+class CONTENT_EXPORT CategorizedWorkerPool : public base::TaskRunner,
+ public cc::TaskGraphRunner {
public:
- RasterWorkerPool();
+ CategorizedWorkerPool();
// Overridden from base::TaskRunner:
bool PostDelayedTask(const tracked_objects::Location& from_here,
@@ -70,11 +70,11 @@ class CONTENT_EXPORT RasterWorkerPool : public base::TaskRunner,
scoped_refptr<base::SequencedTaskRunner> CreateSequencedTaskRunner();
protected:
- ~RasterWorkerPool() override;
+ ~CategorizedWorkerPool() override;
private:
- class RasterWorkerPoolSequencedTaskRunner;
- friend class RasterWorkerPoolSequencedTaskRunner;
+ class CategorizedWorkerPoolSequencedTaskRunner;
+ friend class CategorizedWorkerPoolSequencedTaskRunner;
// Simple Task for the TaskGraphRunner that wraps a closure.
// This class is used to schedule TaskRunner tasks on the
@@ -145,4 +145,4 @@ class CONTENT_EXPORT RasterWorkerPool : public base::TaskRunner,
} // namespace content
-#endif // CONTENT_RENDERER_RASTER_WORKER_POOL_H_
+#endif // CONTENT_RENDERER_CATEGORIZED_WORKER_POOL_H_
diff --git a/chromium/content/renderer/categorized_worker_pool_unittest.cc b/chromium/content/renderer/categorized_worker_pool_unittest.cc
new file mode 100644
index 00000000000..9e6fb19ec0a
--- /dev/null
+++ b/chromium/content/renderer/categorized_worker_pool_unittest.cc
@@ -0,0 +1,122 @@
+// 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 "base/test/sequenced_task_runner_test_template.h"
+#include "base/test/task_runner_test_template.h"
+#include "base/threading/simple_thread.h"
+#include "cc/test/task_graph_runner_test_template.h"
+#include "content/renderer/categorized_worker_pool.h"
+
+namespace base {
+namespace {
+
+// Number of threads spawned in tests.
+const int kNumThreads = 4;
+
+class CategorizedWorkerPoolTestDelegate {
+ public:
+ CategorizedWorkerPoolTestDelegate()
+ : categorized_worker_pool_(new content::CategorizedWorkerPool()) {}
+
+ void StartTaskRunner() { categorized_worker_pool_->Start(kNumThreads); }
+
+ scoped_refptr<content::CategorizedWorkerPool> GetTaskRunner() {
+ return categorized_worker_pool_;
+ }
+
+ void StopTaskRunner() { categorized_worker_pool_->FlushForTesting(); }
+
+ ~CategorizedWorkerPoolTestDelegate() { categorized_worker_pool_->Shutdown(); }
+
+ private:
+ scoped_refptr<content::CategorizedWorkerPool> categorized_worker_pool_;
+};
+
+INSTANTIATE_TYPED_TEST_CASE_P(CategorizedWorkerPool,
+ TaskRunnerTest,
+ CategorizedWorkerPoolTestDelegate);
+
+class CategorizedWorkerPoolSequencedTestDelegate {
+ public:
+ CategorizedWorkerPoolSequencedTestDelegate()
+ : categorized_worker_pool_(new content::CategorizedWorkerPool()) {}
+
+ void StartTaskRunner() { categorized_worker_pool_->Start(kNumThreads); }
+
+ scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() {
+ return categorized_worker_pool_->CreateSequencedTaskRunner();
+ }
+
+ void StopTaskRunner() { categorized_worker_pool_->FlushForTesting(); }
+
+ ~CategorizedWorkerPoolSequencedTestDelegate() {
+ categorized_worker_pool_->Shutdown();
+ }
+
+ private:
+ scoped_refptr<content::CategorizedWorkerPool> categorized_worker_pool_;
+};
+
+INSTANTIATE_TYPED_TEST_CASE_P(CategorizedWorkerPool,
+ SequencedTaskRunnerTest,
+ CategorizedWorkerPoolSequencedTestDelegate);
+
+} // namespace
+} // namespace base
+
+namespace cc {
+namespace {
+
+template <int NumThreads>
+class CategorizedWorkerPoolTaskGraphRunnerTestDelegate {
+ public:
+ CategorizedWorkerPoolTaskGraphRunnerTestDelegate()
+ : categorized_worker_pool_(new content::CategorizedWorkerPool()) {}
+
+ void StartTaskGraphRunner() { categorized_worker_pool_->Start(NumThreads); }
+
+ cc::TaskGraphRunner* GetTaskGraphRunner() {
+ return categorized_worker_pool_->GetTaskGraphRunner();
+ }
+
+ void StopTaskGraphRunner() { categorized_worker_pool_->FlushForTesting(); }
+
+ ~CategorizedWorkerPoolTaskGraphRunnerTestDelegate() {
+ categorized_worker_pool_->Shutdown();
+ }
+
+ private:
+ scoped_refptr<content::CategorizedWorkerPool> categorized_worker_pool_;
+};
+
+// Multithreaded tests.
+INSTANTIATE_TYPED_TEST_CASE_P(
+ CategorizedWorkerPool_1_Threads,
+ TaskGraphRunnerTest,
+ CategorizedWorkerPoolTaskGraphRunnerTestDelegate<1>);
+INSTANTIATE_TYPED_TEST_CASE_P(
+ CategorizedWorkerPool_2_Threads,
+ TaskGraphRunnerTest,
+ CategorizedWorkerPoolTaskGraphRunnerTestDelegate<2>);
+INSTANTIATE_TYPED_TEST_CASE_P(
+ CategorizedWorkerPool_3_Threads,
+ TaskGraphRunnerTest,
+ CategorizedWorkerPoolTaskGraphRunnerTestDelegate<3>);
+INSTANTIATE_TYPED_TEST_CASE_P(
+ CategorizedWorkerPool_4_Threads,
+ TaskGraphRunnerTest,
+ CategorizedWorkerPoolTaskGraphRunnerTestDelegate<4>);
+INSTANTIATE_TYPED_TEST_CASE_P(
+ CategorizedWorkerPool_5_Threads,
+ TaskGraphRunnerTest,
+ CategorizedWorkerPoolTaskGraphRunnerTestDelegate<5>);
+
+// Single threaded tests.
+INSTANTIATE_TYPED_TEST_CASE_P(
+ CategorizedWorkerPool,
+ SingleThreadTaskGraphRunnerTest,
+ CategorizedWorkerPoolTaskGraphRunnerTestDelegate<1>);
+
+} // namespace
+} // namespace cc
diff --git a/chromium/content/renderer/child_frame_compositing_helper.cc b/chromium/content/renderer/child_frame_compositing_helper.cc
index cc2ba004c4d..9b98bc69ec1 100644
--- a/chromium/content/renderer/child_frame_compositing_helper.cc
+++ b/chromium/content/renderer/child_frame_compositing_helper.cc
@@ -149,7 +149,7 @@ void ChildFrameCompositingHelper::ChildFrameGone() {
void ChildFrameCompositingHelper::SatisfyCallback(
scoped_refptr<ThreadSafeSender> sender,
int host_routing_id,
- cc::SurfaceSequence sequence) {
+ const cc::SurfaceSequence& sequence) {
// This may be called on either the main or impl thread.
sender->Send(new FrameHostMsg_SatisfySequence(host_routing_id, sequence));
}
@@ -159,7 +159,7 @@ void ChildFrameCompositingHelper::SatisfyCallbackBrowserPlugin(
scoped_refptr<ThreadSafeSender> sender,
int host_routing_id,
int browser_plugin_instance_id,
- cc::SurfaceSequence sequence) {
+ const cc::SurfaceSequence& sequence) {
sender->Send(new BrowserPluginHostMsg_SatisfySequence(
host_routing_id, browser_plugin_instance_id, sequence));
}
@@ -168,8 +168,8 @@ void ChildFrameCompositingHelper::SatisfyCallbackBrowserPlugin(
void ChildFrameCompositingHelper::RequireCallback(
scoped_refptr<ThreadSafeSender> sender,
int host_routing_id,
- cc::SurfaceId id,
- cc::SurfaceSequence sequence) {
+ const cc::SurfaceId& id,
+ const cc::SurfaceSequence& sequence) {
// This may be called on either the main or impl thread.
sender->Send(new FrameHostMsg_RequireSequence(host_routing_id, id, sequence));
}
@@ -178,8 +178,8 @@ void ChildFrameCompositingHelper::RequireCallbackBrowserPlugin(
scoped_refptr<ThreadSafeSender> sender,
int host_routing_id,
int browser_plugin_instance_id,
- cc::SurfaceId id,
- cc::SurfaceSequence sequence) {
+ const cc::SurfaceId& id,
+ const cc::SurfaceSequence& sequence) {
// This may be called on either the main or impl thread.
sender->Send(new BrowserPluginHostMsg_RequireSequence(
host_routing_id, browser_plugin_instance_id, id, sequence));
diff --git a/chromium/content/renderer/child_frame_compositing_helper.h b/chromium/content/renderer/child_frame_compositing_helper.h
index e51ab82870b..09548c71f92 100644
--- a/chromium/content/renderer/child_frame_compositing_helper.h
+++ b/chromium/content/renderer/child_frame_compositing_helper.h
@@ -93,22 +93,22 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
cc::Layer* layer);
static void SatisfyCallback(scoped_refptr<ThreadSafeSender> sender,
int host_routing_id,
- cc::SurfaceSequence sequence);
+ const cc::SurfaceSequence& sequence);
static void SatisfyCallbackBrowserPlugin(
scoped_refptr<ThreadSafeSender> sender,
int host_routing_id,
int browser_plugin_instance_id,
- cc::SurfaceSequence sequence);
+ const cc::SurfaceSequence& sequence);
static void RequireCallback(scoped_refptr<ThreadSafeSender> sender,
int host_routing_id,
- cc::SurfaceId id,
- cc::SurfaceSequence sequence);
+ const cc::SurfaceId& id,
+ const cc::SurfaceSequence& sequence);
static void RequireCallbackBrowserPlugin(
scoped_refptr<ThreadSafeSender> sender,
int host_routing_id,
int browser_plugin_instance_id,
- cc::SurfaceId id,
- cc::SurfaceSequence sequence);
+ const cc::SurfaceId& id,
+ const cc::SurfaceSequence& sequence);
void UpdateWebLayer(blink::WebLayer* layer);
int host_routing_id_;
diff --git a/chromium/content/renderer/devtools/devtools_agent.cc b/chromium/content/renderer/devtools/devtools_agent.cc
index 87820f63c32..858e75fd0b9 100644
--- a/chromium/content/renderer/devtools/devtools_agent.cc
+++ b/chromium/content/renderer/devtools/devtools_agent.cc
@@ -22,6 +22,7 @@
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_widget.h"
#include "ipc/ipc_channel.h"
+#include "third_party/WebKit/public/platform/WebFloatRect.h"
#include "third_party/WebKit/public/platform/WebPoint.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebDevToolsAgent.h"
@@ -107,6 +108,10 @@ void DevToolsAgent::WidgetWillClose() {
ContinueProgram();
}
+void DevToolsAgent::OnDestruct() {
+ delete this;
+}
+
void DevToolsAgent::sendProtocolMessage(int session_id,
int call_id,
const blink::WebString& message,
@@ -258,7 +263,9 @@ void DevToolsAgent::OnDispatchOnInspectorBackend(int session_id,
}
void DevToolsAgent::OnInspectElement(int x, int y) {
- GetWebAgent()->inspectElementAt(WebPoint(x, y));
+ blink::WebFloatRect point_rect(x, y, 0, 0);
+ frame_->GetRenderWidget()->convertWindowToViewport(&point_rect);
+ GetWebAgent()->inspectElementAt(WebPoint(point_rect.x, point_rect.y));
}
void DevToolsAgent::OnRequestNewWindowACK(bool success) {
diff --git a/chromium/content/renderer/devtools/devtools_agent.h b/chromium/content/renderer/devtools/devtools_agent.h
index 04a5ddec5be..f1a2ea4c315 100644
--- a/chromium/content/renderer/devtools/devtools_agent.h
+++ b/chromium/content/renderer/devtools/devtools_agent.h
@@ -58,6 +58,7 @@ class CONTENT_EXPORT DevToolsAgent
// RenderFrameObserver implementation.
bool OnMessageReceived(const IPC::Message& message) override;
void WidgetWillClose() override;
+ void OnDestruct() override;
// WebDevToolsAgentClient implementation.
void sendProtocolMessage(int session_id,
diff --git a/chromium/content/renderer/devtools/devtools_agent_filter.cc b/chromium/content/renderer/devtools/devtools_agent_filter.cc
index 0ccf71b20a4..1e015f7910f 100644
--- a/chromium/content/renderer/devtools/devtools_agent_filter.cc
+++ b/chromium/content/renderer/devtools/devtools_agent_filter.cc
@@ -21,8 +21,12 @@ namespace {
class MessageImpl : public WebDevToolsAgent::MessageDescriptor {
public:
- MessageImpl(const std::string& message, int routing_id)
- : msg_(message),
+ MessageImpl(
+ const std::string& method,
+ const std::string& message,
+ int routing_id)
+ : method_(method),
+ msg_(message),
routing_id_(routing_id) {
}
~MessageImpl() override {}
@@ -33,8 +37,10 @@ class MessageImpl : public WebDevToolsAgent::MessageDescriptor {
return agent->GetWebAgent();
}
WebString message() override { return WebString::fromUTF8(msg_); }
+ WebString method() override { return WebString::fromUTF8(method_); }
private:
+ std::string method_;
std::string msg_;
int routing_id_;
};
@@ -72,7 +78,7 @@ void DevToolsAgentFilter::OnDispatchOnInspectorBackend(
if (WebDevToolsAgent::shouldInterruptForMethod(
WebString::fromUTF8(method))) {
WebDevToolsAgent::interruptAndDispatch(
- session_id, new MessageImpl(message, current_routing_id_));
+ session_id, new MessageImpl(method, message, current_routing_id_));
}
}
diff --git a/chromium/content/renderer/devtools/devtools_client.cc b/chromium/content/renderer/devtools/devtools_client.cc
index 3f961293824..edc31a3f368 100644
--- a/chromium/content/renderer/devtools/devtools_client.cc
+++ b/chromium/content/renderer/devtools/devtools_client.cc
@@ -39,6 +39,10 @@ void DevToolsClient::DidClearWindowObject() {
render_frame()->ExecuteJavaScript(base::UTF8ToUTF16(compatibility_script_));
}
+void DevToolsClient::OnDestruct() {
+ delete this;
+}
+
void DevToolsClient::sendMessageToEmbedder(const WebString& message) {
Send(new DevToolsHostMsg_DispatchOnEmbedder(routing_id(),
message.utf8()));
diff --git a/chromium/content/renderer/devtools/devtools_client.h b/chromium/content/renderer/devtools/devtools_client.h
index 3d14c4a69c5..d4206e5a8a0 100644
--- a/chromium/content/renderer/devtools/devtools_client.h
+++ b/chromium/content/renderer/devtools/devtools_client.h
@@ -38,6 +38,7 @@ class CONTENT_EXPORT DevToolsClient
private:
// RenderFrameObserver overrides.
void DidClearWindowObject() override;
+ void OnDestruct() override;
// WebDevToolsFrontendClient implementation.
void sendMessageToEmbedder(const blink::WebString&) override;
diff --git a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc
index bad6fa72699..d5f4983f139 100644
--- a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc
+++ b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc
@@ -25,10 +25,10 @@ RenderWidgetScreenMetricsEmulator::RenderWidgetScreenMetricsEmulator(
}
RenderWidgetScreenMetricsEmulator::~RenderWidgetScreenMetricsEmulator() {
+ delegate_->Resize(original_resize_params_);
delegate_->SetScreenMetricsEmulationParameters(false, emulation_params_);
delegate_->SetScreenRects(original_view_screen_rect_,
original_window_screen_rect_);
- delegate_->Resize(original_resize_params_);
}
void RenderWidgetScreenMetricsEmulator::ChangeEmulationParams(
diff --git a/chromium/content/renderer/devtools/v8_sampling_profiler.cc b/chromium/content/renderer/devtools/v8_sampling_profiler.cc
index 5aca412225c..baf2e50b372 100644
--- a/chromium/content/renderer/devtools/v8_sampling_profiler.cc
+++ b/chromium/content/renderer/devtools/v8_sampling_profiler.cc
@@ -639,7 +639,9 @@ void V8SamplingProfiler::EnableSamplingEventForTesting(int code_added_events,
int sample_events) {
render_thread_sampler_->SetEventsToCollectForTest(code_added_events,
sample_events);
- waitable_event_for_testing_.reset(new base::WaitableEvent(false, false));
+ waitable_event_for_testing_.reset(
+ new base::WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED));
}
void V8SamplingProfiler::WaitSamplingEventForTesting() {
diff --git a/chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc b/chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc
index af31cde91c3..eb1f2af080f 100644
--- a/chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc
+++ b/chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc
@@ -2,15 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/renderer/devtools/v8_sampling_profiler.h"
+
#include <stddef.h>
+#include <utility>
+
#include "base/json/json_reader.h"
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_event.h"
#include "content/public/test/render_view_test.h"
-#include "content/renderer/devtools/v8_sampling_profiler.h"
using base::DictionaryValue;
using base::ListValue;
@@ -37,7 +40,9 @@ class V8SamplingProfilerTest : public RenderViewTest {
void KickV8() { ExecuteJavaScriptForTests("1"); }
void SyncFlush(TraceLog* trace_log) {
- base::WaitableEvent flush_complete_event(false, false);
+ base::WaitableEvent flush_complete_event(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
trace_log->Flush(
base::Bind(&V8SamplingProfilerTest::OnTraceDataCollected,
base::Unretained(static_cast<V8SamplingProfilerTest*>(this)),
@@ -73,7 +78,7 @@ class V8SamplingProfilerTest : public RenderViewTest {
while (root_list->GetSize()) {
std::unique_ptr<Value> item;
root_list->Remove(0, &item);
- trace_parsed_.Append(item.release());
+ trace_parsed_.Append(std::move(item));
}
if (!has_more_events)
diff --git a/chromium/content/renderer/dom_automation_controller.cc b/chromium/content/renderer/dom_automation_controller.cc
index 3f119b6920d..91b456a3832 100644
--- a/chromium/content/renderer/dom_automation_controller.cc
+++ b/chromium/content/renderer/dom_automation_controller.cc
@@ -102,8 +102,8 @@ bool DomAutomationController::SendMsg(const gin::Arguments& args) {
(args.PeekNext()->IsString() || args.PeekNext()->IsBoolean() ||
args.PeekNext()->IsNumber())) {
V8ValueConverterImpl conv;
- value.reset(
- conv.FromV8Value(args.PeekNext(), args.isolate()->GetCurrentContext()));
+ value =
+ conv.FromV8Value(args.PeekNext(), args.isolate()->GetCurrentContext());
} else {
return false;
}
diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc
index 3c3e549c12b..d475fe2e0da 100644
--- a/chromium/content/renderer/dom_serializer_browsertest.cc
+++ b/chromium/content/renderer/dom_serializer_browsertest.cc
@@ -75,6 +75,9 @@ class LoadObserver : public RenderViewObserver {
}
private:
+ // RenderViewObserver implementation.
+ void OnDestruct() override { delete this; }
+
base::Closure quit_closure_;
};
diff --git a/chromium/content/renderer/external_popup_menu.cc b/chromium/content/renderer/external_popup_menu.cc
index 7bb01a1d320..95b41a757e6 100644
--- a/chromium/content/renderer/external_popup_menu.cc
+++ b/chromium/content/renderer/external_popup_menu.cc
@@ -63,6 +63,7 @@ void ExternalPopupMenu::close() {
// |this| was deleted.
}
+#if defined(USE_EXTERNAL_POPUP_MENU)
#if defined(OS_MACOSX)
void ExternalPopupMenu::DidSelectItem(int index) {
if (!popup_menu_client_)
@@ -72,9 +73,7 @@ void ExternalPopupMenu::DidSelectItem(int index) {
else
popup_menu_client_->didAcceptIndex(index);
}
-#endif
-
-#if defined(OS_ANDROID)
+#else
void ExternalPopupMenu::DidSelectItems(bool canceled,
const std::vector<int>& indices) {
if (!popup_menu_client_)
@@ -85,5 +84,6 @@ void ExternalPopupMenu::DidSelectItems(bool canceled,
popup_menu_client_->didAcceptIndices(indices);
}
#endif
+#endif
} // namespace content
diff --git a/chromium/content/renderer/external_popup_menu.h b/chromium/content/renderer/external_popup_menu.h
index 0d99eb7e6d9..0158f99fc0d 100644
--- a/chromium/content/renderer/external_popup_menu.h
+++ b/chromium/content/renderer/external_popup_menu.h
@@ -31,16 +31,16 @@ class ExternalPopupMenu : public blink::WebExternalPopupMenu {
void SetOriginScaleAndOffsetForEmulation(
float scale, const gfx::PointF& offset);
+#if defined(USE_EXTERNAL_POPUP_MENU)
#if defined(OS_MACOSX)
// Called when the user has selected an item. |selected_item| is -1 if the
// user canceled the popup.
void DidSelectItem(int selected_index);
-#endif
-
-#if defined(OS_ANDROID)
+#else
// Called when the user has selected items or canceled the popup.
void DidSelectItems(bool canceled, const std::vector<int>& selected_indices);
#endif
+#endif
// blink::WebExternalPopupMenu implementation:
void show(const blink::WebRect& bounds) override;
diff --git a/chromium/content/renderer/external_popup_menu_browsertest.cc b/chromium/content/renderer/external_popup_menu_browsertest.cc
index ea6054b92d3..d1eb5a4520d 100644
--- a/chromium/content/renderer/external_popup_menu_browsertest.cc
+++ b/chromium/content/renderer/external_popup_menu_browsertest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <tuple>
+
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/frame_messages.h"
@@ -87,10 +89,10 @@ TEST_F(ExternalPopupMenuTest, NormalCase) {
const IPC::Message* message =
sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
ASSERT_TRUE(message != NULL);
- base::Tuple<FrameHostMsg_ShowPopup_Params> param;
+ std::tuple<FrameHostMsg_ShowPopup_Params> param;
FrameHostMsg_ShowPopup::Read(message, &param);
- ASSERT_EQ(3U, base::get<0>(param).popup_items.size());
- EXPECT_EQ(1, base::get<0>(param).selected_item);
+ ASSERT_EQ(3U, std::get<0>(param).popup_items.size());
+ EXPECT_EQ(1, std::get<0>(param).selected_item);
// Simulate the user canceling the popup; the index should not have changed.
frame()->OnSelectPopupMenuItem(-1);
@@ -107,8 +109,8 @@ TEST_F(ExternalPopupMenuTest, NormalCase) {
message = sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
ASSERT_TRUE(message != NULL);
FrameHostMsg_ShowPopup::Read(message, &param);
- ASSERT_EQ(3U, base::get<0>(param).popup_items.size());
- EXPECT_EQ(0, base::get<0>(param).selected_item);
+ ASSERT_EQ(3U, std::get<0>(param).popup_items.size());
+ EXPECT_EQ(0, std::get<0>(param).selected_item);
}
// Page shows popup, then navigates away while popup showing, then select.
@@ -190,11 +192,11 @@ TEST_F(ExternalPopupMenuDisplayNoneTest, SelectItem) {
const IPC::Message* message =
sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
ASSERT_TRUE(message != NULL);
- base::Tuple<FrameHostMsg_ShowPopup_Params> param;
+ std::tuple<FrameHostMsg_ShowPopup_Params> param;
FrameHostMsg_ShowPopup::Read(message, &param);
// Number of items should match item count minus the number
// of "display: none" items.
- ASSERT_EQ(5U, base::get<0>(param).popup_items.size());
+ ASSERT_EQ(5U, std::get<0>(param).popup_items.size());
// Select index 1 item. This should select item with index 2,
// skipping the item with 'display: none'
diff --git a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
index d97dbe23377..1eea2aafb99 100644
--- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
+++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
@@ -44,7 +44,7 @@ MultiResolutionImageResourceFetcher::MultiResolutionImageResourceFetcher(
// workers. This should ideally not happen or at least not all the time.
// See https://crbug.com/448427
if (request_context == WebURLRequest::RequestContextFavicon)
- fetcher_->SetSkipServiceWorker(true);
+ fetcher_->SetSkipServiceWorker(WebURLRequest::SkipServiceWorker::All);
fetcher_->SetCachePolicy(cache_policy);
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
index fa58f999c84..51878491e6a 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
@@ -69,7 +69,8 @@ void ResourceFetcherImpl::SetHeader(const std::string& header,
}
}
-void ResourceFetcherImpl::SetSkipServiceWorker(bool skip_service_worker) {
+void ResourceFetcherImpl::SetSkipServiceWorker(
+ blink::WebURLRequest::SkipServiceWorker skip_service_worker) {
DCHECK(!request_.isNull());
DCHECK(!loader_);
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.h b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
index 38f3bb39940..731ca48832c 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_impl.h
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
@@ -35,7 +35,8 @@ class ResourceFetcherImpl : public ResourceFetcher,
void SetMethod(const std::string& method) override;
void SetBody(const std::string& body) override;
void SetHeader(const std::string& header, const std::string& value) override;
- void SetSkipServiceWorker(bool skip_service_worker) override;
+ void SetSkipServiceWorker(
+ blink::WebURLRequest::SkipServiceWorker skip_service_worker) override;
void SetCachePolicy(blink::WebCachePolicy policy) override;
void SetLoaderOptions(const blink::WebURLLoaderOptions& options) override;
void Start(blink::WebFrame* frame,
diff --git a/chromium/content/renderer/frame_blame_context.cc b/chromium/content/renderer/frame_blame_context.cc
index 74ed6ee2b25..a73f347cb4d 100644
--- a/chromium/content/renderer/frame_blame_context.cc
+++ b/chromium/content/renderer/frame_blame_context.cc
@@ -24,7 +24,7 @@ base::trace_event::BlameContext* GetParentBlameContext(
const char kFrameBlameContextCategory[] = "blink";
const char kFrameBlameContextName[] = "FrameBlameContext";
-const char kFrameBlameContextType[] = "Frame";
+const char kFrameBlameContextType[] = "RenderFrame";
const char kFrameBlameContextScope[] = "RenderFrame";
FrameBlameContext::FrameBlameContext(RenderFrameImpl* render_frame,
diff --git a/chromium/content/renderer/gamepad_shared_memory_reader.cc b/chromium/content/renderer/gamepad_shared_memory_reader.cc
index 89ed79eb1fd..f561e5dee84 100644
--- a/chromium/content/renderer/gamepad_shared_memory_reader.cc
+++ b/chromium/content/renderer/gamepad_shared_memory_reader.cc
@@ -7,7 +7,6 @@
#include "base/metrics/histogram.h"
#include "base/trace_event/trace_event.h"
#include "content/common/gamepad_hardware_buffer.h"
-#include "content/common/gamepad_user_gesture.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/renderer_blink_platform_impl.h"
#include "ipc/ipc_sync_message_filter.h"
diff --git a/chromium/content/renderer/gpu/compositor_dependencies.h b/chromium/content/renderer/gpu/compositor_dependencies.h
index cee05271378..9a886ddf948 100644
--- a/chromium/content/renderer/gpu/compositor_dependencies.h
+++ b/chromium/content/renderer/gpu/compositor_dependencies.h
@@ -54,6 +54,8 @@ class CompositorDependencies {
virtual cc::SharedBitmapManager* GetSharedBitmapManager() = 0;
virtual gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() = 0;
virtual scheduler::RendererScheduler* GetRendererScheduler() = 0;
+ // TODO(danakj): This should be part of RenderThreadImpl (or some API from it
+ // to RenderWidget). But RenderThreadImpl is null in RenderViewTest.
virtual std::unique_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource(
int routing_id) = 0;
virtual cc::ImageSerializationProcessor* GetImageSerializationProcessor() = 0;
diff --git a/chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc b/chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc
index aa4a456ac29..e2d13608ac7 100644
--- a/chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc
+++ b/chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc
@@ -32,19 +32,19 @@ CompositorExternalBeginFrameSource::~CompositorExternalBeginFrameSource() {
}
}
-void CompositorExternalBeginFrameSource::OnNeedsBeginFramesChanged(
- bool needs_begin_frames) {
- DCHECK(CalledOnValidThread());
- if (!needs_begin_frames)
- missed_begin_frame_args_ = cc::BeginFrameArgs();
- Send(new ViewHostMsg_SetNeedsBeginFrames(routing_id_, needs_begin_frames));
-}
-
void CompositorExternalBeginFrameSource::AddObserver(
cc::BeginFrameObserver* obs) {
DCHECK(CalledOnValidThread());
+ DCHECK(obs);
+ DCHECK(observers_.find(obs) == observers_.end());
+
SetClientReady();
- BeginFrameSourceBase::AddObserver(obs);
+ bool observers_was_empty = observers_.empty();
+ observers_.insert(obs);
+ obs->OnBeginFrameSourcePausedChanged(paused_);
+ if (observers_was_empty)
+ Send(new ViewHostMsg_SetNeedsBeginFrames(routing_id_, true));
+
// Send a MISSED begin frame if necessary.
if (missed_begin_frame_args_.IsValid()) {
cc::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
@@ -55,6 +55,18 @@ void CompositorExternalBeginFrameSource::AddObserver(
}
}
+void CompositorExternalBeginFrameSource::RemoveObserver(
+ cc::BeginFrameObserver* obs) {
+ DCHECK(obs);
+ DCHECK(observers_.find(obs) != observers_.end());
+
+ observers_.erase(obs);
+ if (observers_.empty()) {
+ missed_begin_frame_args_ = cc::BeginFrameArgs();
+ Send(new ViewHostMsg_SetNeedsBeginFrames(routing_id_, false));
+ }
+}
+
void CompositorExternalBeginFrameSource::SetClientReady() {
DCHECK(CalledOnValidThread());
if (begin_frame_source_proxy_)
@@ -74,16 +86,30 @@ void CompositorExternalBeginFrameSource::OnMessageReceived(
DCHECK(CalledOnValidThread());
DCHECK(begin_frame_source_proxy_.get());
IPC_BEGIN_MESSAGE_MAP(CompositorExternalBeginFrameSource, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_SetBeginFramePaused,
+ OnSetBeginFrameSourcePaused)
IPC_MESSAGE_HANDLER(ViewMsg_BeginFrame, OnBeginFrame)
IPC_END_MESSAGE_MAP()
}
+void CompositorExternalBeginFrameSource::OnSetBeginFrameSourcePaused(
+ bool paused) {
+ if (paused_ == paused)
+ return;
+ paused_ = paused;
+ std::unordered_set<cc::BeginFrameObserver*> observers(observers_);
+ for (auto* obs : observers)
+ obs->OnBeginFrameSourcePausedChanged(paused_);
+}
+
void CompositorExternalBeginFrameSource::OnBeginFrame(
const cc::BeginFrameArgs& args) {
DCHECK(CalledOnValidThread());
missed_begin_frame_args_ = args;
missed_begin_frame_args_.type = cc::BeginFrameArgs::MISSED;
- CallOnBeginFrame(args);
+ std::unordered_set<cc::BeginFrameObserver*> observers(observers_);
+ for (auto* obs : observers)
+ obs->OnBeginFrame(args);
}
bool CompositorExternalBeginFrameSource::Send(IPC::Message* message) {
diff --git a/chromium/content/renderer/gpu/compositor_external_begin_frame_source.h b/chromium/content/renderer/gpu/compositor_external_begin_frame_source.h
index 116529a229f..8a965772f36 100644
--- a/chromium/content/renderer/gpu/compositor_external_begin_frame_source.h
+++ b/chromium/content/renderer/gpu/compositor_external_begin_frame_source.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_RENDERER_GPU_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_
#define CONTENT_RENDERER_GPU_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_
+#include <unordered_set>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -21,7 +23,7 @@ namespace content {
// This class can be created only on the main thread, but then becomes pinned
// to a fixed thread where cc::Scheduler is running.
class CompositorExternalBeginFrameSource
- : public cc::BeginFrameSourceBase,
+ : public cc::BeginFrameSource,
public NON_EXPORTED_BASE(base::NonThreadSafe) {
public:
explicit CompositorExternalBeginFrameSource(
@@ -30,9 +32,11 @@ class CompositorExternalBeginFrameSource
int routing_id);
~CompositorExternalBeginFrameSource() override;
- // cc::BeginFrameSourceBase implementation.
+ // cc::BeginFrameSource implementation.
void AddObserver(cc::BeginFrameObserver* obs) override;
- void OnNeedsBeginFramesChanged(bool needs_begin_frames) override;
+ void RemoveObserver(cc::BeginFrameObserver* obs) override;
+ void DidFinishFrame(cc::BeginFrameObserver* obs,
+ size_t remaining_frames) override {}
private:
class CompositorExternalBeginFrameSourceProxy
@@ -61,6 +65,7 @@ class CompositorExternalBeginFrameSource
void SetClientReady();
void OnMessageReceived(const IPC::Message& message);
+ void OnSetBeginFrameSourcePaused(bool paused);
void OnBeginFrame(const cc::BeginFrameArgs& args);
bool Send(IPC::Message* message);
@@ -71,6 +76,8 @@ class CompositorExternalBeginFrameSource
int routing_id_;
CompositorForwardingMessageFilter::Handler begin_frame_source_filter_handler_;
cc::BeginFrameArgs missed_begin_frame_args_;
+ std::unordered_set<cc::BeginFrameObserver*> observers_;
+ bool paused_ = false;
DISALLOW_COPY_AND_ASSIGN(CompositorExternalBeginFrameSource);
};
diff --git a/chromium/content/renderer/gpu/compositor_forwarding_message_filter.cc b/chromium/content/renderer/gpu/compositor_forwarding_message_filter.cc
index ff657dc58f6..4914fd3fe63 100644
--- a/chromium/content/renderer/gpu/compositor_forwarding_message_filter.cc
+++ b/chromium/content/renderer/gpu/compositor_forwarding_message_filter.cc
@@ -47,6 +47,7 @@ void CompositorForwardingMessageFilter::RemoveHandlerOnCompositorThread(
bool CompositorForwardingMessageFilter::OnMessageReceived(
const IPC::Message& message) {
switch(message.type()) {
+ case ViewMsg_SetBeginFramePaused::ID: // Fall through.
case ViewMsg_BeginFrame::ID: // Fall through.
case ViewMsg_ReclaimCompositorResources::ID: // Fall through.
case ViewMsg_SwapCompositorFrameAck::ID: // Fall through.
diff --git a/chromium/content/renderer/gpu/compositor_output_surface.cc b/chromium/content/renderer/gpu/compositor_output_surface.cc
index 1284fe47d65..a240b19736e 100644
--- a/chromium/content/renderer/gpu/compositor_output_surface.cc
+++ b/chromium/content/renderer/gpu/compositor_output_surface.cc
@@ -30,31 +30,43 @@ namespace content {
CompositorOutputSurface::CompositorOutputSurface(
int32_t routing_id,
uint32_t output_surface_id,
- const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- const scoped_refptr<ContextProviderCommandBuffer>& worker_context_provider,
- const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
- std::unique_ptr<cc::SoftwareOutputDevice> software_device,
- scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
- bool use_swap_compositor_frame_message)
- : OutputSurface(context_provider,
- worker_context_provider,
- vulkan_context_provider,
- std::move(software_device)),
+ scoped_refptr<cc::ContextProvider> context_provider,
+ scoped_refptr<cc::ContextProvider> worker_context_provider,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue)
+ : OutputSurface(std::move(context_provider),
+ std::move(worker_context_provider),
+ nullptr),
output_surface_id_(output_surface_id),
- use_swap_compositor_frame_message_(use_swap_compositor_frame_message),
output_surface_filter_(
RenderThreadImpl::current()->compositor_message_filter()),
+ message_sender_(RenderThreadImpl::current()->sync_message_filter()),
frame_swap_message_queue_(swap_frame_message_queue),
- routing_id_(routing_id),
- layout_test_mode_(RenderThreadImpl::current()->layout_test_mode()),
- weak_ptrs_(this) {
- DCHECK(output_surface_filter_.get());
- DCHECK(frame_swap_message_queue_.get());
- message_sender_ = RenderThreadImpl::current()->sync_message_filter();
- DCHECK(message_sender_.get());
+ routing_id_(routing_id) {
+ DCHECK(output_surface_filter_);
+ DCHECK(frame_swap_message_queue_);
+ DCHECK(message_sender_);
+ capabilities_.delegated_rendering = true;
}
-CompositorOutputSurface::~CompositorOutputSurface() {}
+CompositorOutputSurface::CompositorOutputSurface(
+ int32_t routing_id,
+ uint32_t output_surface_id,
+ scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue)
+ : OutputSurface(std::move(vulkan_context_provider)),
+ output_surface_id_(output_surface_id),
+ output_surface_filter_(
+ RenderThreadImpl::current()->compositor_message_filter()),
+ message_sender_(RenderThreadImpl::current()->sync_message_filter()),
+ frame_swap_message_queue_(swap_frame_message_queue),
+ routing_id_(routing_id) {
+ DCHECK(output_surface_filter_);
+ DCHECK(frame_swap_message_queue_);
+ DCHECK(message_sender_);
+ capabilities_.delegated_rendering = true;
+}
+
+CompositorOutputSurface::~CompositorOutputSurface() = default;
bool CompositorOutputSurface::BindToClient(
cc::OutputSurfaceClient* client) {
@@ -91,70 +103,33 @@ void CompositorOutputSurface::DetachFromClient() {
cc::OutputSurface::DetachFromClient();
}
-void CompositorOutputSurface::ShortcutSwapAck(
- uint32_t output_surface_id,
- std::unique_ptr<cc::GLFrameData> gl_frame_data) {
- if (!layout_test_previous_frame_ack_) {
- layout_test_previous_frame_ack_.reset(new cc::CompositorFrameAck);
- layout_test_previous_frame_ack_->gl_frame_data.reset(new cc::GLFrameData);
+void CompositorOutputSurface::SwapBuffers(cc::CompositorFrame frame) {
+ {
+ std::unique_ptr<FrameSwapMessageQueue::SendMessageScope>
+ send_message_scope =
+ frame_swap_message_queue_->AcquireSendMessageScope();
+ std::vector<std::unique_ptr<IPC::Message>> messages;
+ std::vector<IPC::Message> messages_to_deliver_with_frame;
+ frame_swap_message_queue_->DrainMessages(&messages);
+ FrameSwapMessageQueue::TransferMessages(&messages,
+ &messages_to_deliver_with_frame);
+ Send(new ViewHostMsg_SwapCompositorFrame(routing_id_, output_surface_id_,
+ frame,
+ messages_to_deliver_with_frame));
+ // ~send_message_scope.
}
+ client_->DidSwapBuffers();
+}
- OnSwapAck(output_surface_id, *layout_test_previous_frame_ack_);
-
- layout_test_previous_frame_ack_->gl_frame_data = std::move(gl_frame_data);
+void CompositorOutputSurface::BindFramebuffer() {
+ // This is a delegating output surface, no framebuffer/direct drawing support.
+ NOTREACHED();
}
-void CompositorOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
- DCHECK(use_swap_compositor_frame_message_);
- if (layout_test_mode_) {
- // This code path is here to support layout tests that are currently
- // doing a readback in the renderer instead of the browser. So they
- // are using deprecated code paths in the renderer and don't need to
- // actually swap anything to the browser. We shortcut the swap to the
- // browser here and just ack directly within the renderer process.
- // Once crbug.com/311404 is fixed, this can be removed.
-
- // This would indicate that crbug.com/311404 is being fixed, and this
- // block needs to be removed.
- DCHECK(!frame->delegated_frame_data);
-
- base::Closure closure = base::Bind(
- &CompositorOutputSurface::ShortcutSwapAck, weak_ptrs_.GetWeakPtr(),
- output_surface_id_, base::Passed(&frame->gl_frame_data));
-
- if (context_provider()) {
- gpu::gles2::GLES2Interface* context = context_provider()->ContextGL();
- const uint64_t fence_sync = context->InsertFenceSyncCHROMIUM();
- context->Flush();
-
- gpu::SyncToken sync_token;
- context->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
-
- context_provider()->ContextSupport()->SignalSyncToken(sync_token,
- closure);
- } else {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure);
- }
- client_->DidSwapBuffers();
- return;
- } else {
- {
- std::vector<std::unique_ptr<IPC::Message>> messages;
- std::vector<IPC::Message> messages_to_deliver_with_frame;
- std::unique_ptr<FrameSwapMessageQueue::SendMessageScope>
- send_message_scope =
- frame_swap_message_queue_->AcquireSendMessageScope();
- frame_swap_message_queue_->DrainMessages(&messages);
- FrameSwapMessageQueue::TransferMessages(&messages,
- &messages_to_deliver_with_frame);
- Send(new ViewHostMsg_SwapCompositorFrame(routing_id_,
- output_surface_id_,
- *frame,
- messages_to_deliver_with_frame));
- // ~send_message_scope.
- }
- client_->DidSwapBuffers();
- }
+uint32_t CompositorOutputSurface::GetFramebufferCopyTextureFormat() {
+ // This is a delegating output surface, no framebuffer/direct drawing support.
+ NOTREACHED();
+ return 0;
}
void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) {
diff --git a/chromium/content/renderer/gpu/compositor_output_surface.h b/chromium/content/renderer/gpu/compositor_output_surface.h
index fc311698e98..d3e78b21400 100644
--- a/chromium/content/renderer/gpu/compositor_output_surface.h
+++ b/chromium/content/renderer/gpu/compositor_output_surface.h
@@ -29,15 +29,14 @@ class Message;
namespace cc {
class CompositorFrame;
class CompositorFrameAck;
-class GLFrameData;
+class ContextProvider;
}
namespace content {
-class ContextProviderCommandBuffer;
class FrameSwapMessageQueue;
// This class can be created only on the main thread, but then becomes pinned
-// to a fixed thread when bindToClient is called.
+// to a fixed thread when BindToClient is called.
class CompositorOutputSurface
: NON_EXPORTED_BASE(public cc::OutputSurface),
NON_EXPORTED_BASE(public base::NonThreadSafe) {
@@ -45,27 +44,24 @@ class CompositorOutputSurface
CompositorOutputSurface(
int32_t routing_id,
uint32_t output_surface_id,
- const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- const scoped_refptr<ContextProviderCommandBuffer>&
- worker_context_provider,
- const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
- std::unique_ptr<cc::SoftwareOutputDevice> software,
- scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
- bool use_swap_compositor_frame_message);
+ scoped_refptr<cc::ContextProvider> context_provider,
+ scoped_refptr<cc::ContextProvider> worker_context_provider,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue);
+ CompositorOutputSurface(
+ int32_t routing_id,
+ uint32_t output_surface_id,
+ scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue);
~CompositorOutputSurface() override;
// cc::OutputSurface implementation.
bool BindToClient(cc::OutputSurfaceClient* client) override;
void DetachFromClient() override;
- void SwapBuffers(cc::CompositorFrame* frame) override;
+ void SwapBuffers(cc::CompositorFrame frame) override;
+ void BindFramebuffer() override;
+ uint32_t GetFramebufferCopyTextureFormat() override;
protected:
- void ShortcutSwapAck(uint32_t output_surface_id,
- std::unique_ptr<cc::GLFrameData> gl_frame_data);
- virtual void OnSwapAck(uint32_t output_surface_id,
- const cc::CompositorFrameAck& ack);
- virtual void OnReclaimResources(uint32_t output_surface_id,
- const cc::CompositorFrameAck& ack);
uint32_t output_surface_id_;
private:
@@ -92,21 +88,17 @@ class CompositorOutputSurface
void OnMessageReceived(const IPC::Message& message);
void OnUpdateVSyncParametersFromBrowser(base::TimeTicks timebase,
base::TimeDelta interval);
+ void OnSwapAck(uint32_t output_surface_id, const cc::CompositorFrameAck& ack);
+ void OnReclaimResources(uint32_t output_surface_id,
+ const cc::CompositorFrameAck& ack);
bool Send(IPC::Message* message);
- bool use_swap_compositor_frame_message_;
-
scoped_refptr<CompositorForwardingMessageFilter> output_surface_filter_;
CompositorForwardingMessageFilter::Handler output_surface_filter_handler_;
scoped_refptr<CompositorOutputSurfaceProxy> output_surface_proxy_;
scoped_refptr<IPC::SyncMessageFilter> message_sender_;
scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
int routing_id_;
-
- // TODO(danakj): Remove this when crbug.com/311404
- bool layout_test_mode_;
- std::unique_ptr<cc::CompositorFrameAck> layout_test_previous_frame_ack_;
- base::WeakPtrFactory<CompositorOutputSurface> weak_ptrs_;
};
} // namespace content
diff --git a/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc b/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc
deleted file mode 100644
index 97d838ead7e..00000000000
--- a/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/gpu/delegated_compositor_output_surface.h"
-#include "content/renderer/gpu/frame_swap_message_queue.h"
-
-namespace content {
-
-DelegatedCompositorOutputSurface::DelegatedCompositorOutputSurface(
- int32_t routing_id,
- uint32_t output_surface_id,
- const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- const scoped_refptr<ContextProviderCommandBuffer>& worker_context_provider,
- const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
- scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue)
- : CompositorOutputSurface(routing_id,
- output_surface_id,
- context_provider,
- worker_context_provider,
- vulkan_context_provider,
- std::unique_ptr<cc::SoftwareOutputDevice>(),
- swap_frame_message_queue,
- true) {
- capabilities_.delegated_rendering = true;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/gpu/delegated_compositor_output_surface.h b/chromium/content/renderer/gpu/delegated_compositor_output_surface.h
deleted file mode 100644
index aca19155b8d..00000000000
--- a/chromium/content/renderer/gpu/delegated_compositor_output_surface.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_GPU_DELEGATED_COMPOSITOR_OUTPUT_SURFACE_H_
-#define CONTENT_RENDERER_GPU_DELEGATED_COMPOSITOR_OUTPUT_SURFACE_H_
-
-#include <stdint.h>
-
-#include "base/memory/ref_counted.h"
-#include "content/renderer/gpu/compositor_output_surface.h"
-
-namespace content {
-class FrameSwapMessageQueue;
-
-class DelegatedCompositorOutputSurface : public CompositorOutputSurface {
- public:
- DelegatedCompositorOutputSurface(
- int32_t routing_id,
- uint32_t output_surface_id,
- const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- const scoped_refptr<ContextProviderCommandBuffer>&
- worker_context_provider,
- const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
- scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue);
- ~DelegatedCompositorOutputSurface() override {}
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_GPU_DELEGATED_COMPOSITOR_OUTPUT_SURFACE_H_
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
index 8fe5bae7d48..42f6995ff23 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -910,7 +910,7 @@ int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
base::WrapUnique(V8ValueConverter::create());
v8::Local<v8::Context> v8_context = callback_and_context->GetContext();
std::unique_ptr<base::Value> value =
- base::WrapUnique(converter->FromV8Value(arguments, v8_context));
+ converter->FromV8Value(arguments, v8_context);
return context.compositor()->ScheduleMicroBenchmark(
name, std::move(value),
@@ -930,7 +930,7 @@ bool GpuBenchmarking::SendMessageToMicroBenchmark(
v8::Local<v8::Context> v8_context =
context.web_frame()->mainWorldScriptContext();
std::unique_ptr<base::Value> value =
- base::WrapUnique(converter->FromV8Value(message, v8_context));
+ converter->FromV8Value(message, v8_context);
return context.compositor()->SendMessageToMicroBenchmark(id,
std::move(value));
diff --git a/chromium/content/renderer/gpu/mailbox_output_surface.cc b/chromium/content/renderer/gpu/mailbox_output_surface.cc
deleted file mode 100644
index 4d90944759b..00000000000
--- a/chromium/content/renderer/gpu/mailbox_output_surface.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/gpu/mailbox_output_surface.h"
-
-#include "base/logging.h"
-#include "cc/output/compositor_frame.h"
-#include "cc/output/compositor_frame_ack.h"
-#include "cc/output/gl_frame_data.h"
-#include "cc/resources/resource_provider.h"
-#include "content/renderer/gpu/frame_swap_message_queue.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/khronos/GLES2/gl2ext.h"
-
-using cc::CompositorFrame;
-using cc::GLFrameData;
-using cc::ResourceProvider;
-using gpu::Mailbox;
-using gpu::gles2::GLES2Interface;
-
-namespace content {
-
-MailboxOutputSurface::MailboxOutputSurface(
- int32_t routing_id,
- uint32_t output_surface_id,
- const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- const scoped_refptr<ContextProviderCommandBuffer>& worker_context_provider,
- scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
- cc::ResourceFormat format)
- : CompositorOutputSurface(routing_id,
- output_surface_id,
- context_provider,
- worker_context_provider,
- nullptr,
- nullptr,
- swap_frame_message_queue,
- true),
- fbo_(0),
- is_backbuffer_discarded_(false),
- format_(format) {
- pending_textures_.push_back(TransferableFrame());
- capabilities_.uses_default_gl_framebuffer = false;
-}
-
-MailboxOutputSurface::~MailboxOutputSurface() {}
-
-void MailboxOutputSurface::DetachFromClient() {
- DiscardBackbuffer();
- while (!pending_textures_.empty()) {
- if (pending_textures_.front().texture_id) {
- context_provider_->ContextGL()->DeleteTextures(
- 1, &pending_textures_.front().texture_id);
- }
- pending_textures_.pop_front();
- }
- cc::OutputSurface::DetachFromClient();
-}
-
-void MailboxOutputSurface::EnsureBackbuffer() {
- is_backbuffer_discarded_ = false;
-
- GLES2Interface* gl = context_provider_->ContextGL();
-
- if (!current_backing_.texture_id) {
- // Find a texture of matching size to recycle.
- while (!returned_textures_.empty()) {
- TransferableFrame& texture = returned_textures_.front();
- if (texture.size == surface_size_) {
- current_backing_ = texture;
- if (current_backing_.sync_token.HasData())
- gl->WaitSyncTokenCHROMIUM(current_backing_.sync_token.GetConstData());
- returned_textures_.pop();
- break;
- }
-
- gl->DeleteTextures(1, &texture.texture_id);
- returned_textures_.pop();
- }
-
- if (!current_backing_.texture_id) {
- gl->GenTextures(1, &current_backing_.texture_id);
- current_backing_.size = surface_size_;
- gl->BindTexture(GL_TEXTURE_2D, current_backing_.texture_id);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl->TexImage2D(GL_TEXTURE_2D,
- 0,
- GLInternalFormat(format_),
- surface_size_.width(),
- surface_size_.height(),
- 0,
- GLDataFormat(format_),
- GLDataType(format_),
- NULL);
- gl->GenMailboxCHROMIUM(current_backing_.mailbox.name);
- gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, current_backing_.mailbox.name);
- }
- }
-}
-
-void MailboxOutputSurface::DiscardBackbuffer() {
- is_backbuffer_discarded_ = true;
-
- GLES2Interface* gl = context_provider_->ContextGL();
-
- if (current_backing_.texture_id) {
- gl->DeleteTextures(1, &current_backing_.texture_id);
- current_backing_ = TransferableFrame();
- }
-
- while (!returned_textures_.empty()) {
- const TransferableFrame& frame = returned_textures_.front();
- gl->DeleteTextures(1, &frame.texture_id);
- returned_textures_.pop();
- }
-
- if (fbo_) {
- gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
- gl->DeleteFramebuffers(1, &fbo_);
- fbo_ = 0;
- }
-}
-
-void MailboxOutputSurface::Reshape(const gfx::Size& size,
- float scale_factor,
- bool alpha) {
- if (size == surface_size_)
- return;
-
- surface_size_ = size;
- device_scale_factor_ = scale_factor;
- DiscardBackbuffer();
- EnsureBackbuffer();
-}
-
-void MailboxOutputSurface::BindFramebuffer() {
- EnsureBackbuffer();
- DCHECK(current_backing_.texture_id);
-
- GLES2Interface* gl = context_provider_->ContextGL();
-
- if (!fbo_)
- gl->GenFramebuffers(1, &fbo_);
- gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
- gl->FramebufferTexture2D(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- current_backing_.texture_id,
- 0);
-}
-
-void MailboxOutputSurface::OnSwapAck(uint32_t output_surface_id,
- const cc::CompositorFrameAck& ack) {
- // Ignore message if it's a stale one coming from a different output surface
- // (e.g. after a lost context).
- if (output_surface_id != output_surface_id_) {
- CompositorOutputSurface::OnSwapAck(output_surface_id, ack);
- return;
- }
- if (!ack.gl_frame_data->mailbox.IsZero()) {
- DCHECK(!ack.gl_frame_data->size.IsEmpty());
- // The browser could be returning the oldest or any other pending texture
- // if it decided to skip a frame.
- std::deque<TransferableFrame>::iterator it;
- for (it = pending_textures_.begin(); it != pending_textures_.end(); it++) {
- DCHECK(!it->mailbox.IsZero());
- if (!memcmp(it->mailbox.name,
- ack.gl_frame_data->mailbox.name,
- sizeof(it->mailbox.name))) {
- DCHECK(it->size == ack.gl_frame_data->size);
- break;
- }
- }
- DCHECK(it != pending_textures_.end());
- it->sync_token = ack.gl_frame_data->sync_token;
-
- if (!is_backbuffer_discarded_) {
- returned_textures_.push(*it);
- } else {
- context_provider_->ContextGL()->DeleteTextures(1, &it->texture_id);
- }
-
- pending_textures_.erase(it);
- } else {
- DCHECK(!pending_textures_.empty());
- // The browser always keeps one texture as the frontbuffer.
- // If it does not return a mailbox, it discarded the frontbuffer which is
- // the oldest texture we sent.
- uint32_t texture_id = pending_textures_.front().texture_id;
- if (texture_id)
- context_provider_->ContextGL()->DeleteTextures(1, &texture_id);
- pending_textures_.pop_front();
- }
- CompositorOutputSurface::OnSwapAck(output_surface_id, ack);
-}
-
-void MailboxOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
- DCHECK(frame->gl_frame_data);
- DCHECK(!surface_size_.IsEmpty());
- DCHECK(surface_size_ == current_backing_.size);
- DCHECK(frame->gl_frame_data->size == current_backing_.size);
- DCHECK(!current_backing_.mailbox.IsZero() ||
- context_provider_->ContextGL()->GetGraphicsResetStatusKHR() !=
- GL_NO_ERROR);
-
- frame->gl_frame_data->mailbox = current_backing_.mailbox;
-
- gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
-
- const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM();
- gl->Flush();
-
- gl->GenSyncTokenCHROMIUM(fence_sync,
- frame->gl_frame_data->sync_token.GetData());
-
- CompositorOutputSurface::SwapBuffers(frame);
-
- pending_textures_.push_back(current_backing_);
- current_backing_ = TransferableFrame();
-}
-
-size_t MailboxOutputSurface::GetNumAcksPending() {
- DCHECK(pending_textures_.size());
- return pending_textures_.size() - 1;
-}
-
-MailboxOutputSurface::TransferableFrame::TransferableFrame() : texture_id(0) {}
-
-MailboxOutputSurface::TransferableFrame::TransferableFrame(
- uint32_t texture_id,
- const gpu::Mailbox& mailbox,
- const gfx::Size size)
- : texture_id(texture_id), mailbox(mailbox), size(size) {}
-
-} // namespace content
diff --git a/chromium/content/renderer/gpu/mailbox_output_surface.h b/chromium/content/renderer/gpu/mailbox_output_surface.h
deleted file mode 100644
index 1d4b95559f8..00000000000
--- a/chromium/content/renderer/gpu/mailbox_output_surface.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_GPU_MAILBOX_OUTPUT_SURFACE_H_
-#define CONTENT_RENDERER_GPU_MAILBOX_OUTPUT_SURFACE_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <queue>
-
-#include "base/memory/ref_counted.h"
-#include "cc/resources/resource_format.h"
-#include "cc/resources/transferable_resource.h"
-#include "content/renderer/gpu/compositor_output_surface.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace cc {
-class CompositorFrameAck;
-}
-
-namespace content {
-class FrameSwapMessageQueue;
-
-// Implementation of CompositorOutputSurface that renders to textures which
-// are sent to the browser through the mailbox extension.
-// This class can be created only on the main thread, but then becomes pinned
-// to a fixed thread when bindToClient is called.
-class MailboxOutputSurface : public CompositorOutputSurface {
- public:
- MailboxOutputSurface(
- int32_t routing_id,
- uint32_t output_surface_id,
- const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- const scoped_refptr<ContextProviderCommandBuffer>&
- worker_context_provider,
- scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
- cc::ResourceFormat format);
- ~MailboxOutputSurface() override;
-
- // cc::OutputSurface implementation.
- void DetachFromClient() override;
- void EnsureBackbuffer() override;
- void DiscardBackbuffer() override;
- void Reshape(const gfx::Size& size, float scale_factor, bool alpha) override;
- void BindFramebuffer() override;
- void SwapBuffers(cc::CompositorFrame* frame) override;
-
- private:
- // CompositorOutputSurface overrides.
- void OnSwapAck(uint32_t output_surface_id,
- const cc::CompositorFrameAck& ack) override;
-
- size_t GetNumAcksPending();
-
- struct TransferableFrame {
- TransferableFrame();
- TransferableFrame(uint32_t texture_id,
- const gpu::Mailbox& mailbox,
- const gfx::Size size);
-
- uint32_t texture_id;
- gpu::Mailbox mailbox;
- gpu::SyncToken sync_token;
- gfx::Size size;
- };
-
- TransferableFrame current_backing_;
- std::deque<TransferableFrame> pending_textures_;
- std::queue<TransferableFrame> returned_textures_;
-
- uint32_t fbo_;
- bool is_backbuffer_discarded_;
- cc::ResourceFormat format_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_GPU_MAILBOX_OUTPUT_SURFACE_H_
diff --git a/chromium/content/renderer/gpu/queue_message_swap_promise.cc b/chromium/content/renderer/gpu/queue_message_swap_promise.cc
index 9653375e65c..8b99a17256c 100644
--- a/chromium/content/renderer/gpu/queue_message_swap_promise.cc
+++ b/chromium/content/renderer/gpu/queue_message_swap_promise.cc
@@ -4,6 +4,9 @@
#include "content/renderer/gpu/queue_message_swap_promise.h"
+#include "base/command_line.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/renderer/render_thread.h"
#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "ipc/ipc_sync_message_filter.h"
@@ -38,6 +41,20 @@ void QueueMessageSwapPromise::DidActivate() {
#endif
message_queue_->DidActivate(source_frame_number_);
// The OutputSurface will take care of the Drain+Send.
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseRemoteCompositing)) {
+ // The remote compositing mode doesn't have an output surface, so we need to
+ // Drain+Send on activation. Also, we can't use the SyncMessageFilter, since
+ // this call is actually made on the main thread.
+ std::vector<std::unique_ptr<IPC::Message>> messages_to_deliver;
+ std::unique_ptr<FrameSwapMessageQueue::SendMessageScope>
+ send_message_scope = message_queue_->AcquireSendMessageScope();
+ message_queue_->DrainMessages(&messages_to_deliver);
+ for (auto& message : messages_to_deliver)
+ RenderThread::Get()->Send(message.release());
+ PromiseCompleted();
+ }
}
void QueueMessageSwapPromise::DidSwap(cc::CompositorFrameMetadata* metadata) {
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.cc b/chromium/content/renderer/gpu/render_widget_compositor.cc
index 5d5a155fd8b..c73ca064a9d 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.cc
+++ b/chromium/content/renderer/gpu/render_widget_compositor.cc
@@ -23,6 +23,7 @@
#include "build/build_config.h"
#include "cc/animation/animation_host.h"
#include "cc/animation/animation_timeline.h"
+#include "cc/animation/layer_tree_mutator.h"
#include "cc/base/switches.h"
#include "cc/blink/web_layer_impl.h"
#include "cc/debug/layer_tree_debug_state.h"
@@ -43,7 +44,6 @@
#include "components/scheduler/renderer/renderer_scheduler.h"
#include "content/common/content_switches_internal.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/input/input_event_utils.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/gpu/render_widget_compositor_delegate.h"
@@ -51,6 +51,7 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "third_party/WebKit/public/platform/WebCompositeAndReadbackAsyncCallback.h"
+#include "third_party/WebKit/public/platform/WebCompositorMutatorClient.h"
#include "third_party/WebKit/public/platform/WebLayoutAndPaintAsyncCallback.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/web/WebKit.h"
@@ -109,14 +110,14 @@ cc::LayerSelectionBound ConvertWebSelectionBound(
const blink::WebSelectionBound& web_bound =
is_start ? web_selection.start() : web_selection.end();
DCHECK(web_bound.layerId);
- cc_bound.type = cc::SELECTION_BOUND_CENTER;
+ cc_bound.type = gfx::SelectionBound::CENTER;
if (web_selection.isRange()) {
if (is_start) {
- cc_bound.type = web_bound.isTextDirectionRTL ? cc::SELECTION_BOUND_RIGHT
- : cc::SELECTION_BOUND_LEFT;
+ cc_bound.type = web_bound.isTextDirectionRTL ? gfx::SelectionBound::RIGHT
+ : gfx::SelectionBound::LEFT;
} else {
- cc_bound.type = web_bound.isTextDirectionRTL ? cc::SELECTION_BOUND_LEFT
- : cc::SELECTION_BOUND_RIGHT;
+ cc_bound.type = web_bound.isTextDirectionRTL ? gfx::SelectionBound::LEFT
+ : gfx::SelectionBound::RIGHT;
}
}
cc_bound.layer_id = web_bound.layerId;
@@ -220,6 +221,7 @@ RenderWidgetCompositor::RenderWidgetCompositor(
: num_failed_recreate_attempts_(0),
delegate_(delegate),
compositor_deps_(compositor_deps),
+ threaded_(!!compositor_deps_->GetCompositorImplThreadTaskRunner()),
never_visible_(false),
layout_and_paint_async_callback_(nullptr),
remote_proto_channel_receiver_(nullptr),
@@ -227,16 +229,54 @@ RenderWidgetCompositor::RenderWidgetCompositor(
void RenderWidgetCompositor::Initialize(float device_scale_factor) {
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
+ cc::LayerTreeSettings settings =
+ GenerateLayerTreeSettings(*cmd, compositor_deps_, device_scale_factor);
+ cc::LayerTreeHost::InitParams params;
+ params.client = this;
+ params.shared_bitmap_manager = compositor_deps_->GetSharedBitmapManager();
+ params.gpu_memory_buffer_manager =
+ compositor_deps_->GetGpuMemoryBufferManager();
+ params.settings = &settings;
+ params.task_graph_runner = compositor_deps_->GetTaskGraphRunner();
+ params.main_task_runner =
+ compositor_deps_->GetCompositorMainThreadTaskRunner();
+ if (settings.use_external_begin_frame_source) {
+ params.external_begin_frame_source =
+ delegate_->CreateExternalBeginFrameSource();
+ }
+ params.animation_host = cc::AnimationHost::CreateMainInstance();
+
+ if (cmd->HasSwitch(switches::kUseRemoteCompositing)) {
+ DCHECK(!threaded_);
+ params.image_serialization_processor =
+ compositor_deps_->GetImageSerializationProcessor();
+ layer_tree_host_ = cc::LayerTreeHost::CreateRemoteServer(this, &params);
+ } else if (!threaded_) {
+ // Single-threaded layout tests.
+ layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
+ } else {
+ layer_tree_host_ = cc::LayerTreeHost::CreateThreaded(
+ compositor_deps_->GetCompositorImplThreadTaskRunner(), &params);
+ }
+ DCHECK(layer_tree_host_);
+}
+
+RenderWidgetCompositor::~RenderWidgetCompositor() = default;
+// static
+cc::LayerTreeSettings RenderWidgetCompositor::GenerateLayerTreeSettings(
+ const base::CommandLine& cmd,
+ CompositorDependencies* compositor_deps,
+ float device_scale_factor) {
cc::LayerTreeSettings settings;
// For web contents, layer transforms should scale up the contents of layers
// to keep content always crisp when possible.
settings.layer_transforms_should_scale_layer_contents = true;
- if (cmd->HasSwitch(switches::kDisableGpuVsync)) {
+ if (cmd.HasSwitch(switches::kDisableGpuVsync)) {
std::string display_vsync_string =
- cmd->GetSwitchValueASCII(switches::kDisableGpuVsync);
+ cmd.GetSwitchValueASCII(switches::kDisableGpuVsync);
if (display_vsync_string == "gpu") {
settings.renderer_settings.disable_display_vsync = true;
} else if (display_vsync_string == "beginframe") {
@@ -247,38 +287,33 @@ void RenderWidgetCompositor::Initialize(float device_scale_factor) {
}
}
settings.main_frame_before_activation_enabled =
- cmd->HasSwitch(cc::switches::kEnableMainFrameBeforeActivation);
- settings.use_mouse_wheel_gestures = UseGestureBasedWheelScrolling();
+ cmd.HasSwitch(cc::switches::kEnableMainFrameBeforeActivation);
+ // TODO(danakj): This should not be a setting O_O; it should change when the
+ // device scale factor on LayerTreeHost changes.
settings.default_tile_size = CalculateDefaultTileSize(device_scale_factor);
- if (cmd->HasSwitch(switches::kDefaultTileWidth)) {
+ if (cmd.HasSwitch(switches::kDefaultTileWidth)) {
int tile_width = 0;
- GetSwitchValueAsInt(*cmd,
- switches::kDefaultTileWidth,
- 1,
- std::numeric_limits<int>::max(),
- &tile_width);
+ GetSwitchValueAsInt(cmd, switches::kDefaultTileWidth, 1,
+ std::numeric_limits<int>::max(), &tile_width);
settings.default_tile_size.set_width(tile_width);
}
- if (cmd->HasSwitch(switches::kDefaultTileHeight)) {
+ if (cmd.HasSwitch(switches::kDefaultTileHeight)) {
int tile_height = 0;
- GetSwitchValueAsInt(*cmd,
- switches::kDefaultTileHeight,
- 1,
- std::numeric_limits<int>::max(),
- &tile_height);
+ GetSwitchValueAsInt(cmd, switches::kDefaultTileHeight, 1,
+ std::numeric_limits<int>::max(), &tile_height);
settings.default_tile_size.set_height(tile_height);
}
int max_untiled_layer_width = settings.max_untiled_layer_size.width();
- if (cmd->HasSwitch(switches::kMaxUntiledLayerWidth)) {
- GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerWidth, 1,
+ if (cmd.HasSwitch(switches::kMaxUntiledLayerWidth)) {
+ GetSwitchValueAsInt(cmd, switches::kMaxUntiledLayerWidth, 1,
std::numeric_limits<int>::max(),
&max_untiled_layer_width);
}
int max_untiled_layer_height = settings.max_untiled_layer_size.height();
- if (cmd->HasSwitch(switches::kMaxUntiledLayerHeight)) {
- GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerHeight, 1,
+ if (cmd.HasSwitch(switches::kMaxUntiledLayerHeight)) {
+ GetSwitchValueAsInt(cmd, switches::kMaxUntiledLayerHeight, 1,
std::numeric_limits<int>::max(),
&max_untiled_layer_height);
}
@@ -287,50 +322,50 @@ void RenderWidgetCompositor::Initialize(float device_scale_factor) {
max_untiled_layer_height);
settings.gpu_rasterization_msaa_sample_count =
- compositor_deps_->GetGpuRasterizationMSAASampleCount();
+ compositor_deps->GetGpuRasterizationMSAASampleCount();
settings.gpu_rasterization_forced =
- compositor_deps_->IsGpuRasterizationForced();
+ compositor_deps->IsGpuRasterizationForced();
settings.gpu_rasterization_enabled =
- compositor_deps_->IsGpuRasterizationEnabled();
+ compositor_deps->IsGpuRasterizationEnabled();
settings.async_worker_context_enabled =
- compositor_deps_->IsAsyncWorkerContextEnabled();
+ compositor_deps->IsAsyncWorkerContextEnabled();
- settings.can_use_lcd_text = compositor_deps_->IsLcdTextEnabled();
+ settings.can_use_lcd_text = compositor_deps->IsLcdTextEnabled();
settings.use_distance_field_text =
- compositor_deps_->IsDistanceFieldTextEnabled();
- settings.use_zero_copy = compositor_deps_->IsZeroCopyEnabled();
- settings.use_partial_raster = compositor_deps_->IsPartialRasterEnabled();
+ compositor_deps->IsDistanceFieldTextEnabled();
+ settings.use_zero_copy = compositor_deps->IsZeroCopyEnabled();
+ settings.use_partial_raster = compositor_deps->IsPartialRasterEnabled();
settings.enable_elastic_overscroll =
- compositor_deps_->IsElasticOverscrollEnabled();
+ compositor_deps->IsElasticOverscrollEnabled();
settings.renderer_settings.use_gpu_memory_buffer_resources =
- compositor_deps_->IsGpuMemoryBufferCompositorResourcesEnabled();
+ compositor_deps->IsGpuMemoryBufferCompositorResourcesEnabled();
settings.use_image_texture_targets =
- compositor_deps_->GetImageTextureTargets();
+ compositor_deps->GetImageTextureTargets();
settings.image_decode_tasks_enabled =
- compositor_deps_->AreImageDecodeTasksEnabled();
-
- if (cmd->HasSwitch(cc::switches::kTopControlsShowThreshold)) {
- std::string top_threshold_str =
- cmd->GetSwitchValueASCII(cc::switches::kTopControlsShowThreshold);
- double show_threshold;
- if (base::StringToDouble(top_threshold_str, &show_threshold) &&
- show_threshold >= 0.f && show_threshold <= 1.f)
- settings.top_controls_show_threshold = show_threshold;
+ compositor_deps->AreImageDecodeTasksEnabled();
+
+ if (cmd.HasSwitch(cc::switches::kTopControlsShowThreshold)) {
+ std::string top_threshold_str =
+ cmd.GetSwitchValueASCII(cc::switches::kTopControlsShowThreshold);
+ double show_threshold;
+ if (base::StringToDouble(top_threshold_str, &show_threshold) &&
+ show_threshold >= 0.f && show_threshold <= 1.f)
+ settings.top_controls_show_threshold = show_threshold;
}
- if (cmd->HasSwitch(cc::switches::kTopControlsHideThreshold)) {
- std::string top_threshold_str =
- cmd->GetSwitchValueASCII(cc::switches::kTopControlsHideThreshold);
- double hide_threshold;
- if (base::StringToDouble(top_threshold_str, &hide_threshold) &&
- hide_threshold >= 0.f && hide_threshold <= 1.f)
- settings.top_controls_hide_threshold = hide_threshold;
+ if (cmd.HasSwitch(cc::switches::kTopControlsHideThreshold)) {
+ std::string top_threshold_str =
+ cmd.GetSwitchValueASCII(cc::switches::kTopControlsHideThreshold);
+ double hide_threshold;
+ if (base::StringToDouble(top_threshold_str, &hide_threshold) &&
+ hide_threshold >= 0.f && hide_threshold <= 1.f)
+ settings.top_controls_hide_threshold = hide_threshold;
}
- settings.use_layer_lists = cmd->HasSwitch(cc::switches::kEnableLayerLists);
+ settings.use_layer_lists = cmd.HasSwitch(cc::switches::kEnableLayerLists);
settings.renderer_settings.allow_antialiasing &=
- !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
+ !cmd.HasSwitch(cc::switches::kDisableCompositedAntialiasing);
// The means the renderer compositor has 2 possible modes:
// - Threaded compositing with a scheduler.
// - Single threaded compositing without a scheduler (for layout tests only).
@@ -340,30 +375,28 @@ void RenderWidgetCompositor::Initialize(float device_scale_factor) {
// These flags should be mirrored by UI versions in ui/compositor/.
settings.initial_debug_state.show_debug_borders =
- cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders);
+ cmd.HasSwitch(cc::switches::kShowCompositedLayerBorders);
settings.initial_debug_state.show_layer_animation_bounds_rects =
- cmd->HasSwitch(cc::switches::kShowLayerAnimationBounds);
+ cmd.HasSwitch(cc::switches::kShowLayerAnimationBounds);
settings.initial_debug_state.show_paint_rects =
- cmd->HasSwitch(switches::kShowPaintRects);
+ cmd.HasSwitch(switches::kShowPaintRects);
settings.initial_debug_state.show_property_changed_rects =
- cmd->HasSwitch(cc::switches::kShowPropertyChangedRects);
+ cmd.HasSwitch(cc::switches::kShowPropertyChangedRects);
settings.initial_debug_state.show_surface_damage_rects =
- cmd->HasSwitch(cc::switches::kShowSurfaceDamageRects);
+ cmd.HasSwitch(cc::switches::kShowSurfaceDamageRects);
settings.initial_debug_state.show_screen_space_rects =
- cmd->HasSwitch(cc::switches::kShowScreenSpaceRects);
+ cmd.HasSwitch(cc::switches::kShowScreenSpaceRects);
settings.initial_debug_state.show_replica_screen_space_rects =
- cmd->HasSwitch(cc::switches::kShowReplicaScreenSpaceRects);
+ cmd.HasSwitch(cc::switches::kShowReplicaScreenSpaceRects);
settings.initial_debug_state.SetRecordRenderingStats(
- cmd->HasSwitch(cc::switches::kEnableGpuBenchmarking));
+ cmd.HasSwitch(cc::switches::kEnableGpuBenchmarking));
- if (cmd->HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) {
+ if (cmd.HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) {
const int kMinSlowDownScaleFactor = 0;
const int kMaxSlowDownScaleFactor = INT_MAX;
GetSwitchValueAsInt(
- *cmd,
- cc::switches::kSlowDownRasterScaleFactor,
- kMinSlowDownScaleFactor,
+ cmd, cc::switches::kSlowDownRasterScaleFactor, kMinSlowDownScaleFactor,
kMaxSlowDownScaleFactor,
&settings.initial_debug_state.slow_down_raster_scale_factor);
}
@@ -403,7 +436,7 @@ void RenderWidgetCompositor::Initialize(float device_scale_factor) {
// RGBA_4444 textures are only enabled by default for low end devices
// and are disabled for Android WebView as it doesn't support the format.
- if (!cmd->HasSwitch(switches::kDisableRGBA4444Textures))
+ if (!cmd.HasSwitch(switches::kDisableRGBA4444Textures))
settings.renderer_settings.preferred_tile_format = cc::RGBA_4444;
} else {
// On other devices we have increased memory excessively to avoid
@@ -420,7 +453,8 @@ void RenderWidgetCompositor::Initialize(float device_scale_factor) {
settings.use_external_begin_frame_source = true;
-#elif !defined(OS_MACOSX)
+#else // defined(OS_ANDROID)
+#if !defined(OS_MACOSX)
if (ui::IsOverlayScrollbarEnabled()) {
settings.scrollbar_animator = cc::LayerTreeSettings::THINNING;
settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
@@ -431,21 +465,36 @@ void RenderWidgetCompositor::Initialize(float device_scale_factor) {
settings.scrollbar_fade_delay_ms = 500;
settings.scrollbar_fade_resize_delay_ms = 500;
settings.scrollbar_fade_duration_ms = 300;
-#endif
+#endif // !defined(OS_MACOSX)
+
+ // On desktop, if there's over 4GB of memory on the machine, increase the
+ // image decode budget to 256MB for both gpu and software.
+ const int kImageDecodeMemoryThresholdMB = 4 * 1024;
+ if (base::SysInfo::AmountOfPhysicalMemoryMB() >=
+ kImageDecodeMemoryThresholdMB) {
+ settings.gpu_decoded_image_budget_bytes = 256 * 1024 * 1024;
+ settings.software_decoded_image_budget_bytes = 256 * 1024 * 1024;
+ } else {
+ // These are the defaults, but recorded here as well.
+ settings.gpu_decoded_image_budget_bytes = 96 * 1024 * 1024;
+ settings.software_decoded_image_budget_bytes = 128 * 1024 * 1024;
+ }
- if (cmd->HasSwitch(switches::kEnableLowResTiling))
+#endif // defined(OS_ANDROID)
+
+ if (cmd.HasSwitch(switches::kEnableLowResTiling))
settings.create_low_res_tiling = true;
- if (cmd->HasSwitch(switches::kDisableLowResTiling))
+ if (cmd.HasSwitch(switches::kDisableLowResTiling))
settings.create_low_res_tiling = false;
- if (cmd->HasSwitch(cc::switches::kEnableBeginFrameScheduling))
+ if (cmd.HasSwitch(cc::switches::kEnableBeginFrameScheduling))
settings.use_external_begin_frame_source = true;
- if (cmd->HasSwitch(switches::kEnableRGBA4444Textures) &&
- !cmd->HasSwitch(switches::kDisableRGBA4444Textures)) {
+ if (cmd.HasSwitch(switches::kEnableRGBA4444Textures) &&
+ !cmd.HasSwitch(switches::kDisableRGBA4444Textures)) {
settings.renderer_settings.preferred_tile_format = cc::RGBA_4444;
}
- if (cmd->HasSwitch(cc::switches::kEnableTileCompression)) {
+ if (cmd.HasSwitch(cc::switches::kEnableTileCompression)) {
settings.renderer_settings.preferred_tile_format = cc::ETC1;
}
@@ -457,55 +506,96 @@ void RenderWidgetCompositor::Initialize(float device_scale_factor) {
cc::ManagedMemoryPolicy current = settings.memory_policy_;
settings.memory_policy_ = GetGpuMemoryPolicy(current);
- settings.use_cached_picture_raster = !cmd->HasSwitch(
- cc::switches::kDisableCachedPictureRaster);
-
- scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_task_runner =
- compositor_deps_->GetCompositorImplThreadTaskRunner();
- scoped_refptr<base::SingleThreadTaskRunner>
- main_thread_compositor_task_runner =
- compositor_deps_->GetCompositorMainThreadTaskRunner();
- cc::SharedBitmapManager* shared_bitmap_manager =
- compositor_deps_->GetSharedBitmapManager();
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager =
- compositor_deps_->GetGpuMemoryBufferManager();
- cc::TaskGraphRunner* task_graph_runner =
- compositor_deps_->GetTaskGraphRunner();
-
- bool use_remote_compositing = cmd->HasSwitch(switches::kUseRemoteCompositing);
+ settings.use_cached_picture_raster =
+ !cmd.HasSwitch(cc::switches::kDisableCachedPictureRaster);
- if (use_remote_compositing)
+ if (cmd.HasSwitch(switches::kUseRemoteCompositing))
settings.use_external_begin_frame_source = false;
- std::unique_ptr<cc::BeginFrameSource> external_begin_frame_source;
- if (settings.use_external_begin_frame_source) {
- external_begin_frame_source = delegate_->CreateExternalBeginFrameSource();
+ return settings;
+}
+
+// static
+cc::ManagedMemoryPolicy RenderWidgetCompositor::GetGpuMemoryPolicy(
+ const cc::ManagedMemoryPolicy& policy) {
+ cc::ManagedMemoryPolicy actual = policy;
+ actual.bytes_limit_when_visible = 0;
+
+ // If the value was overridden on the command line, use the specified value.
+ static bool client_hard_limit_bytes_overridden =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kForceGpuMemAvailableMb);
+ if (client_hard_limit_bytes_overridden) {
+ if (base::StringToSizeT(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kForceGpuMemAvailableMb),
+ &actual.bytes_limit_when_visible))
+ actual.bytes_limit_when_visible *= 1024 * 1024;
+ return actual;
}
- cc::LayerTreeHost::InitParams params;
- params.client = this;
- params.shared_bitmap_manager = shared_bitmap_manager;
- params.gpu_memory_buffer_manager = gpu_memory_buffer_manager;
- params.settings = &settings;
- params.task_graph_runner = task_graph_runner;
- params.main_task_runner = main_thread_compositor_task_runner;
- params.external_begin_frame_source = std::move(external_begin_frame_source);
- if (use_remote_compositing) {
- DCHECK(!compositor_thread_task_runner.get());
- params.image_serialization_processor =
- compositor_deps_->GetImageSerializationProcessor();
- layer_tree_host_ = cc::LayerTreeHost::CreateRemoteServer(this, &params);
- } else if (compositor_thread_task_runner.get()) {
- layer_tree_host_ = cc::LayerTreeHost::CreateThreaded(
- compositor_thread_task_runner, &params);
- } else {
- layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
+#if defined(OS_ANDROID)
+ // We can't query available GPU memory from the system on Android.
+ // Physical memory is also mis-reported sometimes (eg. Nexus 10 reports
+ // 1262MB when it actually has 2GB, while Razr M has 1GB but only reports
+ // 128MB java heap size). First we estimate physical memory using both.
+ size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB();
+ size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB();
+ size_t physical_memory_mb = 0;
+ if (dalvik_mb >= 256)
+ physical_memory_mb = dalvik_mb * 4;
+ else
+ physical_memory_mb = std::max(dalvik_mb * 4, (physical_mb * 4) / 3);
+
+ // Now we take a default of 1/8th of memory on high-memory devices,
+ // and gradually scale that back for low-memory devices (to be nicer
+ // to other apps so they don't get killed). Examples:
+ // Nexus 4/10(2GB) 256MB (normally 128MB)
+ // Droid Razr M(1GB) 114MB (normally 57MB)
+ // Galaxy Nexus(1GB) 100MB (normally 50MB)
+ // Xoom(1GB) 100MB (normally 50MB)
+ // Nexus S(low-end) 8MB (normally 8MB)
+ // Note that the compositor now uses only some of this memory for
+ // pre-painting and uses the rest only for 'emergencies'.
+ if (actual.bytes_limit_when_visible == 0) {
+ // NOTE: Non-low-end devices use only 50% of these limits,
+ // except during 'emergencies' where 100% can be used.
+ if (!base::SysInfo::IsLowEndDevice()) {
+ if (physical_memory_mb >= 1536)
+ actual.bytes_limit_when_visible = physical_memory_mb / 8; // >192MB
+ else if (physical_memory_mb >= 1152)
+ actual.bytes_limit_when_visible = physical_memory_mb / 8; // >144MB
+ else if (physical_memory_mb >= 768)
+ actual.bytes_limit_when_visible = physical_memory_mb / 10; // >76MB
+ else
+ actual.bytes_limit_when_visible = physical_memory_mb / 12; // <64MB
+ } else {
+ // Low-end devices have 512MB or less memory by definition
+ // so we hard code the limit rather than relying on the heuristics
+ // above. Low-end devices use 4444 textures so we can use a lower limit.
+ actual.bytes_limit_when_visible = 8;
+ }
+ actual.bytes_limit_when_visible =
+ actual.bytes_limit_when_visible * 1024 * 1024;
+ // Clamp the observed value to a specific range on Android.
+ actual.bytes_limit_when_visible = std::max(
+ actual.bytes_limit_when_visible, static_cast<size_t>(8 * 1024 * 1024));
+ actual.bytes_limit_when_visible =
+ std::min(actual.bytes_limit_when_visible,
+ static_cast<size_t>(256 * 1024 * 1024));
}
- DCHECK(layer_tree_host_);
+ actual.priority_cutoff_when_visible =
+ gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
+#else
+ // Ignore what the system said and give all clients the same maximum
+ // allocation on desktop platforms.
+ actual.bytes_limit_when_visible = 512 * 1024 * 1024;
+ actual.priority_cutoff_when_visible =
+ gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
+#endif
+ return actual;
}
-RenderWidgetCompositor::~RenderWidgetCompositor() {}
-
void RenderWidgetCompositor::SetNeverVisible() {
DCHECK(!layer_tree_host_->visible());
never_visible_ = true;
@@ -657,6 +747,10 @@ void RenderWidgetCompositor::startPageScaleAnimation(
duration);
}
+bool RenderWidgetCompositor::hasPendingPageScaleAnimation() const {
+ return layer_tree_host_->HasPendingPageScaleAnimation();
+}
+
void RenderWidgetCompositor::heuristicsForGpuRasterizationUpdated(
bool matches_heuristics) {
layer_tree_host_->SetHasGpuRasterizationTrigger(matches_heuristics);
@@ -724,6 +818,12 @@ void RenderWidgetCompositor::clearSelection() {
layer_tree_host_->RegisterSelection(empty_selection);
}
+void RenderWidgetCompositor::setMutatorClient(
+ std::unique_ptr<blink::WebCompositorMutatorClient> client) {
+ TRACE_EVENT0("compositor-worker", "RenderWidgetCompositor::setMutatorClient");
+ layer_tree_host_->SetLayerTreeMutator(std::move(client));
+}
+
static_assert(static_cast<cc::EventListenerClass>(
blink::WebEventListenerClass::TouchStartOrMove) ==
cc::EventListenerClass::kTouchStartOrMove,
@@ -786,8 +886,11 @@ void CompositeAndReadbackAsyncCallback(
}
bool RenderWidgetCompositor::CompositeIsSynchronous() const {
- return !compositor_deps_->GetCompositorImplThreadTaskRunner().get() &&
- !layer_tree_host_->settings().single_thread_proxy_scheduler;
+ if (!threaded_) {
+ DCHECK(!layer_tree_host_->settings().single_thread_proxy_scheduler);
+ return true;
+ }
+ return false;
}
void RenderWidgetCompositor::layoutAndPaintAsync(
@@ -989,8 +1092,7 @@ void RenderWidgetCompositor::DidCommitAndDrawFrame() {
void RenderWidgetCompositor::DidCompleteSwapBuffers() {
delegate_->DidCompleteSwapBuffers();
- bool threaded = !!compositor_deps_->GetCompositorImplThreadTaskRunner().get();
- if (!threaded)
+ if (!threaded_)
delegate_->OnSwapBuffersComplete();
}
@@ -998,13 +1100,6 @@ void RenderWidgetCompositor::DidCompletePageScaleAnimation() {
delegate_->DidCompletePageScaleAnimation();
}
-void RenderWidgetCompositor::ReportFixedRasterScaleUseCounters(
- bool has_blurry_content,
- bool has_potential_performance_regression) {
- delegate_->ReportFixedRasterScaleUseCounters(
- has_blurry_content, has_potential_performance_regression);
-}
-
void RenderWidgetCompositor::RequestScheduleAnimation() {
delegate_->RequestScheduleAnimation();
}
@@ -1050,86 +1145,6 @@ void RenderWidgetCompositor::OnHandleCompositorProto(
remote_proto_channel_receiver_->OnProtoReceived(std::move(deserialized));
}
-cc::ManagedMemoryPolicy RenderWidgetCompositor::GetGpuMemoryPolicy(
- const cc::ManagedMemoryPolicy& policy) {
- cc::ManagedMemoryPolicy actual = policy;
- actual.bytes_limit_when_visible = 0;
-
- // If the value was overridden on the command line, use the specified value.
- static bool client_hard_limit_bytes_overridden =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kForceGpuMemAvailableMb);
- if (client_hard_limit_bytes_overridden) {
- if (base::StringToSizeT(
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kForceGpuMemAvailableMb),
- &actual.bytes_limit_when_visible))
- actual.bytes_limit_when_visible *= 1024 * 1024;
- return actual;
- }
-
-#if defined(OS_ANDROID)
- // We can't query available GPU memory from the system on Android.
- // Physical memory is also mis-reported sometimes (eg. Nexus 10 reports
- // 1262MB when it actually has 2GB, while Razr M has 1GB but only reports
- // 128MB java heap size). First we estimate physical memory using both.
- size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB();
- size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB();
- size_t physical_memory_mb = 0;
- if (dalvik_mb >= 256)
- physical_memory_mb = dalvik_mb * 4;
- else
- physical_memory_mb = std::max(dalvik_mb * 4, (physical_mb * 4) / 3);
-
- // Now we take a default of 1/8th of memory on high-memory devices,
- // and gradually scale that back for low-memory devices (to be nicer
- // to other apps so they don't get killed). Examples:
- // Nexus 4/10(2GB) 256MB (normally 128MB)
- // Droid Razr M(1GB) 114MB (normally 57MB)
- // Galaxy Nexus(1GB) 100MB (normally 50MB)
- // Xoom(1GB) 100MB (normally 50MB)
- // Nexus S(low-end) 8MB (normally 8MB)
- // Note that the compositor now uses only some of this memory for
- // pre-painting and uses the rest only for 'emergencies'.
- if (actual.bytes_limit_when_visible == 0) {
- // NOTE: Non-low-end devices use only 50% of these limits,
- // except during 'emergencies' where 100% can be used.
- if (!base::SysInfo::IsLowEndDevice()) {
- if (physical_memory_mb >= 1536)
- actual.bytes_limit_when_visible = physical_memory_mb / 8; // >192MB
- else if (physical_memory_mb >= 1152)
- actual.bytes_limit_when_visible = physical_memory_mb / 8; // >144MB
- else if (physical_memory_mb >= 768)
- actual.bytes_limit_when_visible = physical_memory_mb / 10; // >76MB
- else
- actual.bytes_limit_when_visible = physical_memory_mb / 12; // <64MB
- } else {
- // Low-end devices have 512MB or less memory by definition
- // so we hard code the limit rather than relying on the heuristics
- // above. Low-end devices use 4444 textures so we can use a lower limit.
- actual.bytes_limit_when_visible = 8;
- }
- actual.bytes_limit_when_visible =
- actual.bytes_limit_when_visible * 1024 * 1024;
- // Clamp the observed value to a specific range on Android.
- actual.bytes_limit_when_visible = std::max(
- actual.bytes_limit_when_visible, static_cast<size_t>(8 * 1024 * 1024));
- actual.bytes_limit_when_visible =
- std::min(actual.bytes_limit_when_visible,
- static_cast<size_t>(256 * 1024 * 1024));
- }
- actual.priority_cutoff_when_visible =
- gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
-#else
- // Ignore what the system said and give all clients the same maximum
- // allocation on desktop platforms.
- actual.bytes_limit_when_visible = 512 * 1024 * 1024;
- actual.priority_cutoff_when_visible =
- gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
-#endif
- return actual;
-}
-
void RenderWidgetCompositor::SetPaintedDeviceScaleFactor(
float device_scale) {
layer_tree_host_->SetPaintedDeviceScaleFactor(device_scale);
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.h b/chromium/content/renderer/gpu/render_widget_compositor.h
index 3b8637ebf8e..68349ec2b9a 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.h
+++ b/chromium/content/renderer/gpu/render_widget_compositor.h
@@ -22,11 +22,10 @@
#include "content/common/content_export.h"
#include "content/renderer/gpu/compositor_dependencies.h"
#include "third_party/WebKit/public/platform/WebLayerTreeView.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/rect.h"
-namespace ui {
-class LatencyInfo;
+namespace base {
+class CommandLine;
}
namespace cc {
@@ -34,11 +33,13 @@ class CopyOutputRequest;
class InputHandler;
class Layer;
class LayerTreeHost;
-
namespace proto {
class CompositorMessage;
}
+}
+namespace ui {
+class LatencyInfo;
}
namespace content {
@@ -60,6 +61,13 @@ class CONTENT_EXPORT RenderWidgetCompositor
~RenderWidgetCompositor() override;
+ static cc::LayerTreeSettings GenerateLayerTreeSettings(
+ const base::CommandLine& cmd,
+ CompositorDependencies* compositor_deps,
+ float device_scale_factor);
+ static cc::ManagedMemoryPolicy GetGpuMemoryPolicy(
+ const cc::ManagedMemoryPolicy& policy);
+
void SetNeverVisible();
const base::WeakPtr<cc::InputHandler>& GetInputHandler();
bool BeginMainFrameRequested() const;
@@ -91,8 +99,6 @@ class CONTENT_EXPORT RenderWidgetCompositor
bool SendMessageToMicroBenchmark(int id, std::unique_ptr<base::Value> value);
void SetSurfaceIdNamespace(uint32_t surface_id_namespace);
void OnHandleCompositorProto(const std::vector<uint8_t>& proto);
- cc::ManagedMemoryPolicy GetGpuMemoryPolicy(
- const cc::ManagedMemoryPolicy& policy);
void SetPaintedDeviceScaleFactor(float device_scale);
// WebLayerTreeView implementation.
@@ -116,6 +122,7 @@ class CONTENT_EXPORT RenderWidgetCompositor
bool use_anchor,
float new_page_scale,
double duration_sec) override;
+ bool hasPendingPageScaleAnimation() const override;
void heuristicsForGpuRasterizationUpdated(bool matches_heuristics) override;
void setNeedsAnimate() override;
void setNeedsBeginFrame() override;
@@ -134,6 +141,8 @@ class CONTENT_EXPORT RenderWidgetCompositor
void clearViewportLayers() override;
void registerSelection(const blink::WebSelection& selection) override;
void clearSelection() override;
+ void setMutatorClient(
+ std::unique_ptr<blink::WebCompositorMutatorClient>) override;
void setEventListenerProperties(
blink::WebEventListenerClass eventClass,
blink::WebEventListenerProperties properties) override;
@@ -172,9 +181,6 @@ class CONTENT_EXPORT RenderWidgetCompositor
void DidCommitAndDrawFrame() override;
void DidCompleteSwapBuffers() override;
void DidCompletePageScaleAnimation() override;
- void ReportFixedRasterScaleUseCounters(
- bool has_blurry_content,
- bool has_potential_performance_regression) override;
// cc::LayerTreeHostSingleThreadClient implementation.
void RequestScheduleAnimation() override;
@@ -208,6 +214,7 @@ class CONTENT_EXPORT RenderWidgetCompositor
int num_failed_recreate_attempts_;
RenderWidgetCompositorDelegate* const delegate_;
CompositorDependencies* const compositor_deps_;
+ const bool threaded_;
std::unique_ptr<cc::LayerTreeHost> layer_tree_host_;
bool never_visible_;
diff --git a/chromium/content/renderer/gpu/render_widget_compositor_delegate.h b/chromium/content/renderer/gpu/render_widget_compositor_delegate.h
index c688ef9fdad..e31e19e26b5 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor_delegate.h
+++ b/chromium/content/renderer/gpu/render_widget_compositor_delegate.h
@@ -83,12 +83,6 @@ class CONTENT_EXPORT RenderWidgetCompositorDelegate {
// perform actual painting work.
virtual void WillBeginCompositorFrame() = 0;
- // Indicates that the last commit would have a blurry content or potential
- // performance regression in a fixed raster scale layer.
- virtual void ReportFixedRasterScaleUseCounters(
- bool has_blurry_content,
- bool has_potential_performance_regression) = 0;
-
protected:
virtual ~RenderWidgetCompositorDelegate() {}
};
diff --git a/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc b/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
index 11c3a575a4c..6dae54c12f7 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
+++ b/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
@@ -13,6 +13,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "cc/output/begin_frame_args.h"
#include "cc/test/failure_output_surface.h"
+#include "cc/test/fake_external_begin_frame_source.h"
#include "cc/trees/layer_tree_host.h"
#include "components/scheduler/renderer/renderer_scheduler.h"
#include "content/public/test/mock_render_thread.h"
@@ -29,89 +30,112 @@ using testing::Field;
namespace content {
namespace {
-class MockWebWidget : public blink::WebWidget {
+class StubRenderWidgetCompositorDelegate
+ : public RenderWidgetCompositorDelegate {
public:
- MOCK_METHOD1(beginFrame, void(double lastFrameTimeMonotonic));
-};
-
-class TestRenderWidget : public RenderWidget {
- public:
- explicit TestRenderWidget(CompositorDependencies* compositor_deps)
- : RenderWidget(compositor_deps,
- blink::WebPopupTypeNone,
- blink::WebScreenInfo(),
- true,
- false,
- false) {
- webwidget_ = &mock_webwidget_;
- SetRoutingID(++next_routing_id_);
+ // RenderWidgetCompositorDelegate implementation.
+ void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
+ const gfx::Vector2dF& elastic_overscroll_delta,
+ float page_scale,
+ float top_controls_delta) override {}
+ void BeginMainFrame(double frame_time_sec) override {}
+ std::unique_ptr<cc::OutputSurface> CreateOutputSurface(
+ bool fallback) override {
+ return nullptr;
}
-
- MockWebWidget mock_webwidget_;
-
- protected:
- ~TestRenderWidget() override { webwidget_ = NULL; }
- static int next_routing_id_;
-
- DISALLOW_COPY_AND_ASSIGN(TestRenderWidget);
+ std::unique_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource()
+ override {
+ return nullptr;
+ }
+ void DidCommitAndDrawCompositorFrame() override {}
+ void DidCommitCompositorFrame() override {}
+ void DidCompletePageScaleAnimation() override {}
+ void DidCompleteSwapBuffers() override {}
+ void ForwardCompositorProto(const std::vector<uint8_t>& proto) override {}
+ bool IsClosing() const override { return false; }
+ void OnSwapBuffersAborted() override {}
+ void OnSwapBuffersComplete() override {}
+ void OnSwapBuffersPosted() override {}
+ void RequestScheduleAnimation() override {}
+ void UpdateVisualState() override {}
+ void WillBeginCompositorFrame() override {}
};
-int TestRenderWidget::next_routing_id_ = 0;
-
-class RenderWidgetCompositorTest : public testing::Test {
+class FakeRenderWidgetCompositorDelegate
+ : public StubRenderWidgetCompositorDelegate {
public:
- RenderWidgetCompositorTest()
- : compositor_deps_(new FakeCompositorDependencies),
- render_widget_(new TestRenderWidget(compositor_deps_.get())),
- render_widget_compositor_(RenderWidgetCompositor::Create(
- render_widget_.get(),
- 1.f /* initial_device_scale_factor */,
- compositor_deps_.get())) {}
- ~RenderWidgetCompositorTest() override {}
+ FakeRenderWidgetCompositorDelegate() = default;
- protected:
- base::MessageLoop loop_;
- MockRenderThread render_thread_;
- std::unique_ptr<FakeCompositorDependencies> compositor_deps_;
- scoped_refptr<TestRenderWidget> render_widget_;
- std::unique_ptr<RenderWidgetCompositor> render_widget_compositor_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorTest);
-};
-
-TEST_F(RenderWidgetCompositorTest, BeginMainFrame) {
- base::TimeTicks frame_time(base::TimeTicks() +
- base::TimeDelta::FromSeconds(1));
- base::TimeTicks deadline(base::TimeTicks() + base::TimeDelta::FromSeconds(2));
- base::TimeDelta interval(base::TimeDelta::FromSeconds(3));
- cc::BeginFrameArgs args(
- cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
- interval, cc::BeginFrameArgs::NORMAL));
+ std::unique_ptr<cc::OutputSurface> CreateOutputSurface(
+ bool fallback) override {
+ EXPECT_EQ(
+ num_requests_since_last_success_ >
+ RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
+ fallback);
+ last_create_was_fallback_ = fallback;
+ bool success = num_failures_ >= num_failures_before_success_;
+ if (success) {
+ std::unique_ptr<cc::TestWebGraphicsContext3D> context =
+ cc::TestWebGraphicsContext3D::Create();
+ // Image support required for synchronous compositing.
+ context->set_support_image(true);
+ // Create delegating surface so that max_pending_frames = 1.
+ return cc::FakeOutputSurface::CreateDelegating3d(std::move(context));
+ }
+ return use_null_output_surface_
+ ? nullptr
+ : base::WrapUnique(new cc::FailureOutputSurface(true));
+ }
- EXPECT_CALL(render_widget_->mock_webwidget_, beginFrame(1));
+ std::unique_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource()
+ override {
+ double refresh_rate = 200.0;
+ bool tick_automatically = true;
+ return base::MakeUnique<cc::FakeExternalBeginFrameSource>(
+ refresh_rate, tick_automatically);
+ }
- render_widget_compositor_->BeginMainFrame(args);
-}
+ void add_success() {
+ if (last_create_was_fallback_)
+ ++num_fallback_successes_;
+ else
+ ++num_successes_;
+ num_requests_since_last_success_ = 0;
+ }
+ int num_successes() const { return num_successes_; }
+ int num_fallback_successes() const { return num_fallback_successes_; }
-class RenderWidgetCompositorOutputSurface;
+ void add_request() {
+ ++num_requests_since_last_success_;
+ ++num_requests_;
+ }
+ int num_requests() const { return num_requests_; }
-class RenderWidgetOutputSurface : public TestRenderWidget {
- public:
- explicit RenderWidgetOutputSurface(CompositorDependencies* compositor_deps)
- : TestRenderWidget(compositor_deps), compositor_(NULL) {}
- void SetCompositor(RenderWidgetCompositorOutputSurface* compositor);
+ void add_failure() { ++num_failures_; }
+ int num_failures() const { return num_failures_; }
- std::unique_ptr<cc::OutputSurface> CreateOutputSurface(
- bool fallback) override;
+ void set_num_failures_before_success(int n) {
+ num_failures_before_success_ = n;
+ }
+ int num_failures_before_success() const {
+ return num_failures_before_success_;
+ }
- protected:
- ~RenderWidgetOutputSurface() override {}
+ void set_use_null_output_surface(bool u) { use_null_output_surface_ = u; }
+ bool use_null_output_surface() const { return use_null_output_surface_; }
private:
- RenderWidgetCompositorOutputSurface* compositor_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderWidgetOutputSurface);
+ int num_requests_ = 0;
+ int num_requests_since_last_success_ = 0;
+ int num_failures_ = 0;
+ int num_failures_before_success_ = 0;
+ int num_fallback_successes_ = 0;
+ int num_successes_ = 0;
+ bool last_create_was_fallback_ = false;
+ bool use_null_output_surface_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeRenderWidgetCompositorDelegate);
};
// Verify that failing to create an output surface will cause the compositor
@@ -122,42 +146,14 @@ class RenderWidgetOutputSurface : public TestRenderWidget {
// the compositor (couldn't bind the output surface) are handled identically.
class RenderWidgetCompositorOutputSurface : public RenderWidgetCompositor {
public:
- RenderWidgetCompositorOutputSurface(RenderWidget* widget,
- CompositorDependencies* compositor_deps)
- : RenderWidgetCompositor(widget, compositor_deps),
- num_failures_before_success_(0),
- expected_successes_(0),
- expected_fallback_successes_(0),
- expected_requests_(0),
- num_requests_(0),
- num_requests_since_last_success_(0),
- num_successes_(0),
- num_fallback_successes_(0),
- num_failures_(0),
- last_create_was_fallback_(false),
- use_null_output_surface_(true) {}
+ RenderWidgetCompositorOutputSurface(
+ FakeRenderWidgetCompositorDelegate* delegate,
+ CompositorDependencies* compositor_deps)
+ : RenderWidgetCompositor(delegate, compositor_deps),
+ delegate_(delegate) {}
using RenderWidgetCompositor::Initialize;
- std::unique_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback) {
- EXPECT_EQ(num_requests_since_last_success_ >
- OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
- fallback);
- last_create_was_fallback_ = fallback;
- bool success = num_failures_ >= num_failures_before_success_;
- if (success) {
- std::unique_ptr<cc::TestWebGraphicsContext3D> context =
- cc::TestWebGraphicsContext3D::Create();
- // Image support required for synchronous compositing.
- context->set_support_image(true);
- // Create delegating surface so that max_pending_frames = 1.
- return cc::FakeOutputSurface::CreateDelegating3d(std::move(context));
- }
- return use_null_output_surface_
- ? nullptr
- : base::WrapUnique(new cc::FailureOutputSurface(true));
- }
-
// Force a new output surface to be created.
void SynchronousComposite() {
layer_tree_host()->DidLoseOutputSurface();
@@ -167,21 +163,15 @@ class RenderWidgetCompositorOutputSurface : public RenderWidgetCompositor {
}
void RequestNewOutputSurface() override {
- ++num_requests_;
- ++num_requests_since_last_success_;
+ delegate_->add_request();
RenderWidgetCompositor::RequestNewOutputSurface();
}
void DidInitializeOutputSurface() override {
- if (last_create_was_fallback_)
- ++num_fallback_successes_;
- else
- ++num_successes_;
-
- if (num_requests_ == expected_requests_) {
+ delegate_->add_success();
+ if (delegate_->num_requests() == expected_requests_) {
EndTest();
} else {
- num_requests_since_last_success_ = 0;
RenderWidgetCompositor::DidInitializeOutputSurface();
// Post the synchronous composite task so that it is not called
// reentrantly as a part of RequestNewOutputSurface.
@@ -193,8 +183,8 @@ class RenderWidgetCompositorOutputSurface : public RenderWidgetCompositor {
}
void DidFailToInitializeOutputSurface() override {
- ++num_failures_;
- if (num_requests_ == expected_requests_) {
+ delegate_->add_failure();
+ if (delegate_->num_requests() == expected_requests_) {
EndTest();
return;
}
@@ -202,39 +192,29 @@ class RenderWidgetCompositorOutputSurface : public RenderWidgetCompositor {
RenderWidgetCompositor::DidFailToInitializeOutputSurface();
}
- void SetUp(bool use_null_output_surface,
- int num_failures_before_success,
- int expected_successes,
- int expected_fallback_succeses) {
- use_null_output_surface_ = use_null_output_surface;
- num_failures_before_success_ = num_failures_before_success;
+ void SetUp(int expected_successes, int expected_fallback_succeses) {
expected_successes_ = expected_successes;
expected_fallback_successes_ = expected_fallback_succeses;
- expected_requests_ = num_failures_before_success_ + expected_successes_ +
- expected_fallback_successes_;
+ expected_requests_ = delegate_->num_failures_before_success() +
+ expected_successes_ + expected_fallback_successes_;
}
void EndTest() { base::MessageLoop::current()->QuitWhenIdle(); }
void AfterTest() {
- EXPECT_EQ(num_failures_before_success_, num_failures_);
- EXPECT_EQ(expected_successes_, num_successes_);
- EXPECT_EQ(expected_fallback_successes_, num_fallback_successes_);
- EXPECT_EQ(expected_requests_, num_requests_);
+ EXPECT_EQ(delegate_->num_failures_before_success(),
+ delegate_->num_failures());
+ EXPECT_EQ(expected_successes_, delegate_->num_successes());
+ EXPECT_EQ(expected_fallback_successes_,
+ delegate_->num_fallback_successes());
+ EXPECT_EQ(expected_requests_, delegate_->num_requests());
}
private:
- int num_failures_before_success_;
- int expected_successes_;
- int expected_fallback_successes_;
- int expected_requests_;
- int num_requests_;
- int num_requests_since_last_success_;
- int num_successes_;
- int num_fallback_successes_;
- int num_failures_;
- bool last_create_was_fallback_;
- bool use_null_output_surface_;
+ FakeRenderWidgetCompositorDelegate* delegate_;
+ int expected_successes_ = 0;
+ int expected_fallback_successes_ = 0;
+ int expected_requests_ = 0;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorOutputSurface);
};
@@ -242,53 +222,39 @@ class RenderWidgetCompositorOutputSurface : public RenderWidgetCompositor {
class RenderWidgetCompositorOutputSurfaceTest : public testing::Test {
public:
RenderWidgetCompositorOutputSurfaceTest()
- : compositor_deps_(new FakeCompositorDependencies),
- render_widget_(new RenderWidgetOutputSurface(compositor_deps_.get())) {
- render_widget_compositor_.reset(new RenderWidgetCompositorOutputSurface(
- render_widget_.get(), compositor_deps_.get()));
- render_widget_compositor_->Initialize(
- 1.f /* initial_device_scale_factor */);
- render_widget_->SetCompositor(render_widget_compositor_.get());
+ : render_widget_compositor_(&compositor_delegate_, &compositor_deps_) {
+ render_widget_compositor_.Initialize(1.f /* initial_device_scale_factor */);
}
void RunTest(bool use_null_output_surface,
int num_failures_before_success,
int expected_successes,
int expected_fallback_succeses) {
- render_widget_compositor_->SetUp(
- use_null_output_surface, num_failures_before_success,
- expected_successes, expected_fallback_succeses);
- render_widget_compositor_->setVisible(true);
+ compositor_delegate_.set_use_null_output_surface(use_null_output_surface);
+ compositor_delegate_.set_num_failures_before_success(
+ num_failures_before_success);
+ render_widget_compositor_.SetUp(expected_successes,
+ expected_fallback_succeses);
+ render_widget_compositor_.setVisible(true);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&RenderWidgetCompositorOutputSurface::SynchronousComposite,
- base::Unretained(render_widget_compositor_.get())));
+ base::Unretained(&render_widget_compositor_)));
base::MessageLoop::current()->Run();
- render_widget_compositor_->AfterTest();
+ render_widget_compositor_.AfterTest();
}
protected:
base::MessageLoop ye_olde_message_loope_;
MockRenderThread render_thread_;
- std::unique_ptr<FakeCompositorDependencies> compositor_deps_;
- scoped_refptr<RenderWidgetOutputSurface> render_widget_;
- std::unique_ptr<RenderWidgetCompositorOutputSurface>
- render_widget_compositor_;
+ FakeCompositorDependencies compositor_deps_;
+ FakeRenderWidgetCompositorDelegate compositor_delegate_;
+ RenderWidgetCompositorOutputSurface render_widget_compositor_;
private:
DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorOutputSurfaceTest);
};
-std::unique_ptr<cc::OutputSurface>
-RenderWidgetOutputSurface::CreateOutputSurface(bool fallback) {
- return compositor_->CreateOutputSurface(fallback);
-}
-
-void RenderWidgetOutputSurface::SetCompositor(
- RenderWidgetCompositorOutputSurface* compositor) {
- compositor_ = compositor;
-}
-
TEST_F(RenderWidgetCompositorOutputSurfaceTest, SucceedOnce) {
RunTest(false, 0, 1, 0);
}
diff --git a/chromium/content/renderer/history_controller.cc b/chromium/content/renderer/history_controller.cc
index 8f1bc3462f7..14ced356b88 100644
--- a/chromium/content/renderer/history_controller.cc
+++ b/chromium/content/renderer/history_controller.cc
@@ -196,8 +196,32 @@ void HistoryController::UpdateForCommit(RenderFrameImpl* frame,
bool navigation_within_page) {
switch (commit_type) {
case blink::WebBackForwardCommit:
- if (!provisional_entry_)
+ if (!provisional_entry_) {
+ // The provisional entry may have been discarded due to a navigation in
+ // a different frame. For main frames, it is not safe to leave the
+ // current_entry_ in place, which may have a cross-site page and will be
+ // included in the PageState for this commit. Replace it with a new
+ // HistoryEntry corresponding to the commit, and clear any stale
+ // NavigationParams which might point to the wrong entry.
+ //
+ // This will lack any subframe history items that were in the original
+ // provisional entry, but we don't know what those were after discarding
+ // it. We'll load the default URL in those subframes instead.
+ //
+ // TODO(creis): It's also possible to get here for subframe commits.
+ // We'll leave a stale current_entry_ in that case, but that only causes
+ // an earlier URL to load in the subframe when leaving and coming back,
+ // and only in rare cases. It does not risk a URL spoof, unlike the
+ // main frame case. Since this bug is not present in the new
+ // FrameNavigationEntry-based navigation path (https://crbug.com/236848)
+ // we'll wait for that to fix the subframe case.
+ if (frame->IsMainFrame()) {
+ current_entry_.reset(new HistoryEntry(item));
+ navigation_params_.reset();
+ }
+
return;
+ }
// If the current entry is null, this must be a main frame commit.
DCHECK(current_entry_ || frame->IsMainFrame());
@@ -230,6 +254,13 @@ void HistoryController::UpdateForCommit(RenderFrameImpl* frame,
if (HistoryEntry::HistoryNode* node =
current_entry_->GetHistoryNodeForFrame(frame)) {
+ // Clear the children and any NavigationParams if this commit isn't for
+ // the same item. Otherwise we might have stale data from a race.
+ if (node->item().itemSequenceNumber() != item.itemSequenceNumber()) {
+ node->RemoveChildren();
+ navigation_params_.reset();
+ }
+
node->set_item(item);
}
break;
diff --git a/chromium/content/renderer/history_controller.h b/chromium/content/renderer/history_controller.h
index ff205967014..ac522418889 100644
--- a/chromium/content/renderer/history_controller.h
+++ b/chromium/content/renderer/history_controller.h
@@ -153,11 +153,15 @@ class CONTENT_EXPORT HistoryController {
// A HistoryEntry representing the page that is being loaded, or an empty
// scoped_ptr if no page is being loaded.
std::unique_ptr<HistoryEntry> provisional_entry_;
- // The NavigationParams corresponding to the last load that was initiated by
- // |GoToEntry|. This is kept around so that it can be passed into existing
- // frames modified during a history navigation in GoToEntry(), and can be
+
+ // The NavigationParams corresponding to the last back/forward load that was
+ // initiated by |GoToEntry|. This is kept around so that it can be passed into
+ // existing frames affected by a history navigation in GoToEntry(), and can be
// passed into frames created after the commit that resulted from the
// navigation in GetItemForNewChildFrame().
+ //
+ // This is reset in UpdateForCommit if we see a commit from a different
+ // navigation, to avoid using stale parameters.
std::unique_ptr<NavigationParams> navigation_params_;
DISALLOW_COPY_AND_ASSIGN(HistoryController);
diff --git a/chromium/content/renderer/history_entry.cc b/chromium/content/renderer/history_entry.cc
index edc21f94a08..61bcb3acf9f 100644
--- a/chromium/content/renderer/history_entry.cc
+++ b/chromium/content/renderer/history_entry.cc
@@ -69,8 +69,10 @@ HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::CloneAndReplace(
// the frame. See https://crbug.com/612713#c12.
const WebHistoryItem& current_item = current_frame->current_history_item();
if (is_target_frame && clone_children_of_target && !current_item.isNull()) {
- new_history_node->item().setDocumentSequenceNumber(
- current_item.documentSequenceNumber());
+ // TODO(creis): Setting the document sequence number here appears to be
+ // unnecessary. Remove this block if this DCHECK never fires.
+ DCHECK_EQ(current_item.documentSequenceNumber(),
+ new_history_node->item().documentSequenceNumber());
}
// TODO(creis): This needs to be updated to handle HistoryEntry in
diff --git a/chromium/content/renderer/history_serialization.cc b/chromium/content/renderer/history_serialization.cc
index 0a4376c023c..ee5981afa3f 100644
--- a/chromium/content/renderer/history_serialization.cc
+++ b/chromium/content/renderer/history_serialization.cc
@@ -6,9 +6,12 @@
#include <stddef.h>
+#include "base/strings/nullable_string16.h"
+#include "content/child/web_url_request_util.h"
#include "content/common/page_state_serialization.h"
#include "content/public/common/page_state.h"
#include "content/renderer/history_entry.h"
+#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebFloatPoint.h"
#include "third_party/WebKit/public/platform/WebHTTPBody.h"
#include "third_party/WebKit/public/platform/WebPoint.h"
@@ -17,6 +20,7 @@
#include "third_party/WebKit/public/web/WebHistoryItem.h"
#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
+using blink::WebData;
using blink::WebHTTPBody;
using blink::WebHistoryItem;
using blink::WebSerializedScriptValue;
@@ -33,56 +37,6 @@ void ToNullableString16Vector(const WebVector<WebString>& input,
output->push_back(input[i]);
}
-void ToExplodedHttpBodyElement(const WebHTTPBody::Element& input,
- ExplodedHttpBodyElement* output) {
- switch (input.type) {
- case WebHTTPBody::Element::TypeData:
- output->data.assign(input.data.data(), input.data.size());
- break;
- case WebHTTPBody::Element::TypeFile:
- output->file_path = input.filePath;
- output->file_start = input.fileStart;
- output->file_length = input.fileLength;
- output->file_modification_time = input.modificationTime;
- break;
- case WebHTTPBody::Element::TypeFileSystemURL:
- output->filesystem_url = input.fileSystemURL;
- output->file_start = input.fileStart;
- output->file_length = input.fileLength;
- output->file_modification_time = input.modificationTime;
- break;
- case WebHTTPBody::Element::TypeBlob:
- output->blob_uuid = input.blobUUID.utf8();
- break;
- }
-}
-
-void AppendHTTPBodyElement(const ExplodedHttpBodyElement& element,
- WebHTTPBody* http_body) {
- switch (element.type) {
- case WebHTTPBody::Element::TypeData:
- http_body->appendData(element.data);
- break;
- case WebHTTPBody::Element::TypeFile:
- http_body->appendFileRange(
- element.file_path,
- element.file_start,
- element.file_length,
- element.file_modification_time);
- break;
- case WebHTTPBody::Element::TypeFileSystemURL:
- http_body->appendFileSystemURLRange(
- element.filesystem_url,
- element.file_start,
- element.file_length,
- element.file_modification_time);
- break;
- case WebHTTPBody::Element::TypeBlob:
- http_body->appendBlob(WebString::fromUTF8(element.blob_uuid));
- break;
- }
-}
-
void GenerateFrameStateFromItem(const WebHistoryItem& item,
ExplodedFrameState* state) {
state->url_string = item.urlString();
@@ -102,15 +56,8 @@ void GenerateFrameStateFromItem(const WebHistoryItem& item,
state->http_body.http_content_type = item.httpContentType();
const WebHTTPBody& http_body = item.httpBody();
- state->http_body.is_null = http_body.isNull();
- if (!state->http_body.is_null) {
- state->http_body.identifier = http_body.identifier();
- state->http_body.elements.resize(http_body.elementCount());
- for (size_t i = 0; i < http_body.elementCount(); ++i) {
- WebHTTPBody::Element element;
- http_body.elementAt(i, element);
- ToExplodedHttpBodyElement(element, &state->http_body.elements[i]);
- }
+ if (!http_body.isNull()) {
+ state->http_body.request_body = GetRequestBodyForWebHTTPBody(http_body);
state->http_body.contains_passwords = http_body.containsPasswordData();
}
}
@@ -157,13 +104,9 @@ void RecursivelyGenerateHistoryItem(const ExplodedFrameState& state,
item.setDocumentSequenceNumber(state.document_sequence_number);
item.setHTTPContentType(state.http_body.http_content_type);
- if (!state.http_body.is_null) {
- WebHTTPBody http_body;
- http_body.initialize();
- http_body.setIdentifier(state.http_body.identifier);
- for (size_t i = 0; i < state.http_body.elements.size(); ++i)
- AppendHTTPBodyElement(state.http_body.elements[i], &http_body);
- item.setHTTPBody(http_body);
+ if (state.http_body.request_body != nullptr) {
+ item.setHTTPBody(
+ GetWebHTTPBodyForRequestBody(state.http_body.request_body));
}
node->set_item(item);
diff --git a/chromium/content/renderer/idle_user_detector.cc b/chromium/content/renderer/idle_user_detector.cc
index 9ca35709fbc..a2f2fd0d2b8 100644
--- a/chromium/content/renderer/idle_user_detector.cc
+++ b/chromium/content/renderer/idle_user_detector.cc
@@ -37,4 +37,8 @@ void IdleUserDetector::OnHandleInputEvent(
}
}
+void IdleUserDetector::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/idle_user_detector.h b/chromium/content/renderer/idle_user_detector.h
index cbe85a0f697..8d55af7ddc6 100644
--- a/chromium/content/renderer/idle_user_detector.h
+++ b/chromium/content/renderer/idle_user_detector.h
@@ -29,6 +29,7 @@ class IdleUserDetector : public RenderViewObserver {
private:
// RenderViewObserver implementation:
bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() override;
void OnHandleInputEvent(const blink::WebInputEvent* event,
const ui::LatencyInfo& latency_info,
diff --git a/chromium/content/renderer/image_downloader/image_downloader_impl.cc b/chromium/content/renderer/image_downloader/image_downloader_impl.cc
index 0fd476c1ecd..84c13a5f72a 100644
--- a/chromium/content/renderer/image_downloader/image_downloader_impl.cc
+++ b/chromium/content/renderer/image_downloader/image_downloader_impl.cc
@@ -7,17 +7,16 @@
#include <utility>
#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/child/image_decoder.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/fetchers/multi_resolution_image_resource_fetcher.h"
-#include "mojo/common/url_type_converters.h"
-#include "mojo/converters/geometry/geometry_type_converters.h"
#include "net/base/data_url.h"
#include "skia/ext/image_operations.h"
-#include "skia/public/type_converters.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
@@ -145,13 +144,11 @@ void ImageDownloaderImpl::OnRenderProcessShutdown() {
}
// ImageDownloader methods:
-void ImageDownloaderImpl::DownloadImage(const mojo::String& url,
+void ImageDownloaderImpl::DownloadImage(const GURL& image_url,
bool is_favicon,
uint32_t max_bitmap_size,
bool bypass_cache,
const DownloadImageCallback& callback) {
- const GURL image_url = url.To<GURL>();
-
std::vector<SkBitmap> result_images;
std::vector<gfx::Size> result_original_image_sizes;
@@ -211,7 +208,7 @@ void ImageDownloaderImpl::DidFetchImage(
std::find(image_fetchers_.begin(), image_fetchers_.end(), fetcher);
if (iter != image_fetchers_.end()) {
image_fetchers_.weak_erase(iter);
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher);
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, fetcher);
}
}
@@ -220,9 +217,12 @@ void ImageDownloaderImpl::ReplyDownloadResult(
const std::vector<SkBitmap>& result_images,
const std::vector<gfx::Size>& result_original_image_sizes,
const DownloadImageCallback& callback) {
- callback.Run(http_status_code,
- mojo::Array<skia::mojom::BitmapPtr>::From(result_images),
- mojo::Array<mojo::SizePtr>::From(result_original_image_sizes));
+ callback.Run(http_status_code, mojo::Array<SkBitmap>::From(result_images),
+ result_original_image_sizes);
+}
+
+void ImageDownloaderImpl::OnDestruct() {
+ delete this;
}
} // namespace content
diff --git a/chromium/content/renderer/image_downloader/image_downloader_impl.h b/chromium/content/renderer/image_downloader/image_downloader_impl.h
index 07ba01516fc..cc4a11aba5c 100644
--- a/chromium/content/renderer/image_downloader/image_downloader_impl.h
+++ b/chromium/content/renderer/image_downloader/image_downloader_impl.h
@@ -45,8 +45,11 @@ class ImageDownloaderImpl : public content::mojom::ImageDownloader,
mojo::InterfaceRequest<content::mojom::ImageDownloader> request);
~ImageDownloaderImpl() override;
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
// ImageDownloader methods:
- void DownloadImage(const mojo::String& url,
+ void DownloadImage(const GURL& url,
bool is_favicon,
uint32_t max_bitmap_size,
bool bypass_cache,
diff --git a/chromium/content/renderer/input/input_event_filter.cc b/chromium/content/renderer/input/input_event_filter.cc
index 94e5ba2758c..7f7b09fa6c3 100644
--- a/chromium/content/renderer/input/input_event_filter.cc
+++ b/chromium/content/renderer/input/input_event_filter.cc
@@ -4,6 +4,7 @@
#include "content/renderer/input/input_event_filter.h"
+#include <tuple>
#include <utility>
#include "base/auto_reset.h"
@@ -174,9 +175,9 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
InputMsg_HandleInputEvent::Param params;
if (!InputMsg_HandleInputEvent::Read(&message, &params))
return;
- const WebInputEvent* event = base::get<0>(params);
- ui::LatencyInfo latency_info = base::get<1>(params);
- InputEventDispatchType dispatch_type = base::get<2>(params);
+ const WebInputEvent* event = std::get<0>(params);
+ ui::LatencyInfo latency_info = std::get<1>(params);
+ InputEventDispatchType dispatch_type = std::get<2>(params);
DCHECK(event);
DCHECK(dispatch_type == DISPATCH_TYPE_BLOCKING ||
dispatch_type == DISPATCH_TYPE_NON_BLOCKING);
diff --git a/chromium/content/renderer/input/input_event_filter_unittest.cc b/chromium/content/renderer/input/input_event_filter_unittest.cc
index 9692720a81b..39547e27514 100644
--- a/chromium/content/renderer/input/input_event_filter_unittest.cc
+++ b/chromium/content/renderer/input/input_event_filter_unittest.cc
@@ -5,11 +5,13 @@
#include <stddef.h>
#include <new>
+#include <tuple>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
@@ -114,7 +116,7 @@ void AddMessagesToFilter(IPC::MessageFilter* message_filter,
for (size_t i = 0; i < events.size(); ++i)
message_filter->OnMessageReceived(events[i]);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
template <typename T>
@@ -191,8 +193,8 @@ TEST_F(InputEventFilterTest, Basic) {
InputHostMsg_HandleInputEvent_ACK::Param params;
EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message, &params));
- WebInputEvent::Type event_type = base::get<0>(params).type;
- InputEventAckState ack_result = base::get<0>(params).state;
+ WebInputEvent::Type event_type = std::get<0>(params).type;
+ InputEventAckState ack_result = std::get<0>(params).state;
EXPECT_EQ(kEvents[i].type, event_type);
EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
@@ -217,7 +219,7 @@ TEST_F(InputEventFilterTest, Basic) {
ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
- const WebInputEvent* event = base::get<0>(params);
+ const WebInputEvent* event = std::get<0>(params);
EXPECT_EQ(kEvents[i].size, event->size);
EXPECT_TRUE(memcmp(&kEvents[i], event, event->size) == 0);
@@ -243,8 +245,8 @@ TEST_F(InputEventFilterTest, Basic) {
InputHostMsg_HandleInputEvent_ACK::Param params;
EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message, &params));
- WebInputEvent::Type event_type = base::get<0>(params).type;
- InputEventAckState ack_result = base::get<0>(params).state;
+ WebInputEvent::Type event_type = std::get<0>(params).type;
+ InputEventAckState ack_result = std::get<0>(params).state;
EXPECT_EQ(kEvents[i].type, event_type);
EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_CONSUMED);
}
@@ -330,7 +332,7 @@ TEST_F(InputEventFilterTest, NonBlockingWheel) {
// Second event was queued; ack the first.
filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(4u, ipc_sink_.message_count());
EXPECT_EQ(2u, message_recorder_.message_count());
@@ -338,13 +340,13 @@ TEST_F(InputEventFilterTest, NonBlockingWheel) {
// different.
filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(3u, message_recorder_.message_count());
// The last events will be coalesced.
filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(3u, message_recorder_.message_count());
// First two messages should be identical.
@@ -354,8 +356,8 @@ TEST_F(InputEventFilterTest, NonBlockingWheel) {
ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
- const WebInputEvent* event = base::get<0>(params);
- InputEventDispatchType dispatch_type = base::get<2>(params);
+ const WebInputEvent* event = std::get<0>(params);
+ InputEventDispatchType dispatch_type = std::get<2>(params);
EXPECT_EQ(kEvents[i].size, event->size);
kEvents[i].dispatchType =
@@ -373,8 +375,8 @@ TEST_F(InputEventFilterTest, NonBlockingWheel) {
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
const WebMouseWheelEvent* event =
- static_cast<const WebMouseWheelEvent*>(base::get<0>(params));
- InputEventDispatchType dispatch_type = base::get<2>(params);
+ static_cast<const WebMouseWheelEvent*>(std::get<0>(params));
+ InputEventDispatchType dispatch_type = std::get<2>(params);
kEvents[2].dispatchType =
WebInputEvent::DispatchType::ListenersNonBlockingPassive;
@@ -411,7 +413,7 @@ TEST_F(InputEventFilterTest, NonBlockingTouch) {
// Second event was queued; ack the first.
filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(4u, ipc_sink_.message_count());
EXPECT_EQ(2u, message_recorder_.message_count());
@@ -419,13 +421,13 @@ TEST_F(InputEventFilterTest, NonBlockingTouch) {
// different.
filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(3u, message_recorder_.message_count());
// The last events will be coalesced.
filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(3u, message_recorder_.message_count());
// First two messages should be identical.
@@ -435,8 +437,8 @@ TEST_F(InputEventFilterTest, NonBlockingTouch) {
ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
- const WebInputEvent* event = base::get<0>(params);
- InputEventDispatchType dispatch_type = base::get<2>(params);
+ const WebInputEvent* event = std::get<0>(params);
+ InputEventDispatchType dispatch_type = std::get<2>(params);
EXPECT_EQ(kEvents[i].size, event->size);
kEvents[i].dispatchType =
@@ -454,8 +456,8 @@ TEST_F(InputEventFilterTest, NonBlockingTouch) {
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
const WebTouchEvent* event =
- static_cast<const WebTouchEvent*>(base::get<0>(params));
- InputEventDispatchType dispatch_type = base::get<2>(params);
+ static_cast<const WebTouchEvent*>(std::get<0>(params));
+ InputEventDispatchType dispatch_type = std::get<2>(params);
EXPECT_EQ(kEvents[3].size, event->size);
EXPECT_EQ(1u, kEvents[3].touchesLength);
@@ -494,8 +496,8 @@ TEST_F(InputEventFilterTest, IntermingledNonBlockingTouch) {
ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
- const WebInputEvent* event = base::get<0>(params);
- InputEventDispatchType dispatch_type = base::get<2>(params);
+ const WebInputEvent* event = std::get<0>(params);
+ InputEventDispatchType dispatch_type = std::get<2>(params);
EXPECT_EQ(kEvents[0].size, event->size);
kEvents[0].dispatchType =
@@ -509,15 +511,15 @@ TEST_F(InputEventFilterTest, IntermingledNonBlockingTouch) {
// Second event was queued; ack the first.
filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(2u, message_recorder_.message_count());
const IPC::Message& message = message_recorder_.message_at(1);
ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
- const WebInputEvent* event = base::get<0>(params);
- InputEventDispatchType dispatch_type = base::get<2>(params);
+ const WebInputEvent* event = std::get<0>(params);
+ InputEventDispatchType dispatch_type = std::get<2>(params);
EXPECT_EQ(kEvents[1].size, event->size);
kEvents[1].dispatchType =
@@ -531,15 +533,15 @@ TEST_F(InputEventFilterTest, IntermingledNonBlockingTouch) {
// Third event should be put in the queue.
filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchEnd,
INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(3u, message_recorder_.message_count());
const IPC::Message& message = message_recorder_.message_at(2);
ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
- const WebInputEvent* event = base::get<0>(params);
- InputEventDispatchType dispatch_type = base::get<2>(params);
+ const WebInputEvent* event = std::get<0>(params);
+ InputEventDispatchType dispatch_type = std::get<2>(params);
EXPECT_EQ(kBlockingEvents[0].size, event->size);
EXPECT_TRUE(memcmp(&kBlockingEvents[0], event, event->size) == 0);
diff --git a/chromium/content/renderer/input/input_handler_manager.cc b/chromium/content/renderer/input/input_handler_manager.cc
index 2e28534089f..0821d8225fc 100644
--- a/chromium/content/renderer/input/input_handler_manager.cc
+++ b/chromium/content/renderer/input/input_handler_manager.cc
@@ -67,20 +67,18 @@ void InputHandlerManager::AddInputHandler(
int routing_id,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling,
- bool enable_wheel_gestures) {
+ bool enable_smooth_scrolling) {
if (task_runner_->BelongsToCurrentThread()) {
AddInputHandlerOnCompositorThread(
routing_id, base::ThreadTaskRunnerHandle::Get(), input_handler,
- render_view_impl, enable_smooth_scrolling, enable_wheel_gestures);
+ render_view_impl, enable_smooth_scrolling);
} else {
task_runner_->PostTask(
FROM_HERE,
base::Bind(&InputHandlerManager::AddInputHandlerOnCompositorThread,
base::Unretained(this), routing_id,
base::ThreadTaskRunnerHandle::Get(), input_handler,
- render_view_impl, enable_smooth_scrolling,
- enable_wheel_gestures));
+ render_view_impl, enable_smooth_scrolling));
}
}
@@ -89,8 +87,7 @@ void InputHandlerManager::AddInputHandlerOnCompositorThread(
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling,
- bool enable_wheel_gestures) {
+ bool enable_smooth_scrolling) {
DCHECK(task_runner_->BelongsToCurrentThread());
// The handler could be gone by this point if the compositor has shut down.
@@ -104,9 +101,9 @@ void InputHandlerManager::AddInputHandlerOnCompositorThread(
TRACE_EVENT1("input",
"InputHandlerManager::AddInputHandlerOnCompositorThread",
"result", "AddingRoute");
- std::unique_ptr<InputHandlerWrapper> wrapper(new InputHandlerWrapper(
- this, routing_id, main_task_runner, input_handler, render_view_impl,
- enable_smooth_scrolling, enable_wheel_gestures));
+ std::unique_ptr<InputHandlerWrapper> wrapper(
+ new InputHandlerWrapper(this, routing_id, main_task_runner, input_handler,
+ render_view_impl, enable_smooth_scrolling));
client_->RegisterRoutingID(routing_id);
if (synchronous_handler_proxy_client_) {
synchronous_handler_proxy_client_->DidAddSynchronousHandlerProxy(
@@ -162,32 +159,6 @@ void InputHandlerManager::UnregisterRoutingIDOnCompositorThread(
client_->UnregisterRoutingID(routing_id);
}
-void InputHandlerManager::ObserveWheelEventAndResultOnMainThread(
- int routing_id,
- const blink::WebMouseWheelEvent& wheel_event,
- const cc::InputHandlerScrollResult& scroll_result) {
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(
- &InputHandlerManager::ObserveWheelEventAndResultOnCompositorThread,
- base::Unretained(this), routing_id, wheel_event, scroll_result));
-}
-
-void InputHandlerManager::ObserveWheelEventAndResultOnCompositorThread(
- int routing_id,
- const blink::WebMouseWheelEvent& wheel_event,
- const cc::InputHandlerScrollResult& scroll_result) {
- DCHECK(task_runner_->BelongsToCurrentThread());
- auto it = input_handlers_.find(routing_id);
- if (it == input_handlers_.end())
- return;
-
- InputHandlerProxy* proxy = it->second->input_handler_proxy();
- DCHECK(proxy->scroll_elasticity_controller());
- proxy->scroll_elasticity_controller()->ObserveWheelEventAndResult(
- wheel_event, scroll_result);
-}
-
void InputHandlerManager::ObserveGestureEventAndResultOnMainThread(
int routing_id,
const blink::WebGestureEvent& gesture_event,
diff --git a/chromium/content/renderer/input/input_handler_manager.h b/chromium/content/renderer/input/input_handler_manager.h
index bb3ef894820..1935a2e04a3 100644
--- a/chromium/content/renderer/input/input_handler_manager.h
+++ b/chromium/content/renderer/input/input_handler_manager.h
@@ -56,17 +56,11 @@ class CONTENT_EXPORT InputHandlerManager {
void AddInputHandler(int routing_id,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling,
- bool enable_wheel_gestures);
+ bool enable_smooth_scrolling);
void RegisterRoutingID(int routing_id);
void UnregisterRoutingID(int routing_id);
- void ObserveWheelEventAndResultOnMainThread(
- int routing_id,
- const blink::WebMouseWheelEvent& wheel_event,
- const cc::InputHandlerScrollResult& scroll_result);
-
void ObserveGestureEventAndResultOnMainThread(
int routing_id,
const blink::WebGestureEvent& gesture_event,
@@ -102,8 +96,7 @@ class CONTENT_EXPORT InputHandlerManager {
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling,
- bool enable_wheel_gestures);
+ bool enable_smooth_scrolling);
void RegisterRoutingIDOnCompositorThread(int routing_id);
void UnregisterRoutingIDOnCompositorThread(int routing_id);
diff --git a/chromium/content/renderer/input/input_handler_wrapper.cc b/chromium/content/renderer/input/input_handler_wrapper.cc
index 7678f9337c1..77416f37212 100644
--- a/chromium/content/renderer/input/input_handler_wrapper.cc
+++ b/chromium/content/renderer/input/input_handler_wrapper.cc
@@ -20,8 +20,7 @@ InputHandlerWrapper::InputHandlerWrapper(
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling,
- bool enable_wheel_gestures)
+ bool enable_smooth_scrolling)
: input_handler_manager_(input_handler_manager),
routing_id_(routing_id),
input_handler_proxy_(input_handler.get(), this),
@@ -29,8 +28,6 @@ InputHandlerWrapper::InputHandlerWrapper(
render_view_impl_(render_view_impl) {
DCHECK(input_handler);
input_handler_proxy_.set_smooth_scroll_enabled(enable_smooth_scrolling);
- input_handler_proxy_.set_use_gesture_events_for_mouse_wheel(
- enable_wheel_gestures);
}
InputHandlerWrapper::~InputHandlerWrapper() {
diff --git a/chromium/content/renderer/input/input_handler_wrapper.h b/chromium/content/renderer/input/input_handler_wrapper.h
index 35c96e97dfb..5a9248ed74e 100644
--- a/chromium/content/renderer/input/input_handler_wrapper.h
+++ b/chromium/content/renderer/input/input_handler_wrapper.h
@@ -28,8 +28,7 @@ class InputHandlerWrapper : public ui::InputHandlerProxyClient {
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling,
- bool enable_wheel_gestures);
+ bool enable_smooth_scrolling);
~InputHandlerWrapper() override;
int routing_id() const { return routing_id_; }
diff --git a/chromium/content/renderer/input/render_widget_input_handler.cc b/chromium/content/renderer/input/render_widget_input_handler.cc
index 25bd40139ca..878f087f78c 100644
--- a/chromium/content/renderer/input/render_widget_input_handler.cc
+++ b/chromium/content/renderer/input/render_widget_input_handler.cc
@@ -387,21 +387,11 @@ void RenderWidgetInputHandler::HandleInputEvent(
}
}
- // Send mouse wheel events and their disposition to the compositor thread, so
- // that they can be used to produce the elastic overscroll effect on Mac.
- if (input_event.type == WebInputEvent::MouseWheel) {
- const WebMouseWheelEvent& wheel_event =
- static_cast<const WebMouseWheelEvent&>(input_event);
- if (wheel_event.canScroll) {
- delegate_->ObserveWheelEventAndResult(
- wheel_event,
- event_overscroll ? event_overscroll->latest_overscroll_delta
- : gfx::Vector2dF(),
- processed != WebInputEventResult::NotHandled);
- }
- } else if (input_event.type == WebInputEvent::GestureScrollBegin ||
- input_event.type == WebInputEvent::GestureScrollEnd ||
- input_event.type == WebInputEvent::GestureScrollUpdate) {
+ // Send gesture scroll events and their dispositions to the compositor thread,
+ // so that they can be used to produce the elastic overscroll effect on Mac.
+ if (input_event.type == WebInputEvent::GestureScrollBegin ||
+ input_event.type == WebInputEvent::GestureScrollEnd ||
+ input_event.type == WebInputEvent::GestureScrollUpdate) {
const WebGestureEvent& gesture_event =
static_cast<const WebGestureEvent&>(input_event);
if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad) {
diff --git a/chromium/content/renderer/input/render_widget_input_handler_delegate.h b/chromium/content/renderer/input/render_widget_input_handler_delegate.h
index 55465fd5787..bbb58d006be 100644
--- a/chromium/content/renderer/input/render_widget_input_handler_delegate.h
+++ b/chromium/content/renderer/input/render_widget_input_handler_delegate.h
@@ -43,13 +43,6 @@ class CONTENT_EXPORT RenderWidgetInputHandlerDelegate {
// at the given point.
virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const = 0;
- // Called to forward a mouse wheel event to the compositor thread, to effect
- // the elastic overscroll effect.
- virtual void ObserveWheelEventAndResult(
- const blink::WebMouseWheelEvent& wheel_event,
- const gfx::Vector2dF& wheel_unused_delta,
- bool event_processed) = 0;
-
// Called to forward a gesture event to the compositor thread, to effect
// the elastic overscroll effect.
virtual void ObserveGestureEventAndResult(
diff --git a/chromium/content/renderer/java/gin_java_bridge_dispatcher.cc b/chromium/content/renderer/java/gin_java_bridge_dispatcher.cc
index 0d6d07350d1..a7a9a449887 100644
--- a/chromium/content/renderer/java/gin_java_bridge_dispatcher.cc
+++ b/chromium/content/renderer/java/gin_java_bridge_dispatcher.cc
@@ -133,4 +133,8 @@ void GinJavaBridgeDispatcher::OnGinJavaBridgeObjectDeleted(
new GinJavaBridgeHostMsg_ObjectWrapperDeleted(routing_id(), object_id));
}
+void GinJavaBridgeDispatcher::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/java/gin_java_bridge_dispatcher.h b/chromium/content/renderer/java/gin_java_bridge_dispatcher.h
index f795c288f78..297da75247d 100644
--- a/chromium/content/renderer/java/gin_java_bridge_dispatcher.h
+++ b/chromium/content/renderer/java/gin_java_bridge_dispatcher.h
@@ -59,6 +59,9 @@ class GinJavaBridgeDispatcher
void OnGinJavaBridgeObjectDeleted(GinJavaBridgeObject* object);
private:
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
void OnAddNamedObject(const std::string& name,
ObjectID object_id);
void OnRemoveNamedObject(const std::string& name);
diff --git a/chromium/content/renderer/java/gin_java_bridge_value_converter.cc b/chromium/content/renderer/java/gin_java_bridge_value_converter.cc
index 527b541c5b3..309d77d43d8 100644
--- a/chromium/content/renderer/java/gin_java_bridge_value_converter.cc
+++ b/chromium/content/renderer/java/gin_java_bridge_value_converter.cc
@@ -38,20 +38,19 @@ v8::Local<v8::Value> GinJavaBridgeValueConverter::ToV8Value(
std::unique_ptr<base::Value> GinJavaBridgeValueConverter::FromV8Value(
v8::Local<v8::Value> value,
v8::Local<v8::Context> context) const {
- return base::WrapUnique(converter_->FromV8Value(value, context));
+ return converter_->FromV8Value(value, context);
}
bool GinJavaBridgeValueConverter::FromV8Object(
v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const {
GinJavaBridgeObject* unwrapped;
if (!gin::ConvertFromV8(isolate, value, &unwrapped)) {
return false;
}
- *out =
- GinJavaBridgeValue::CreateObjectIDValue(unwrapped->object_id()).release();
+ *out = GinJavaBridgeValue::CreateObjectIDValue(unwrapped->object_id());
return true;
}
@@ -124,10 +123,10 @@ std::unique_ptr<TypedArraySerializer> TypedArraySerializer::Create(
bool GinJavaBridgeValueConverter::FromV8ArrayBuffer(
v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate) const {
if (!value->IsTypedArray()) {
- *out = GinJavaBridgeValue::CreateUndefinedValue().release();
+ *out = GinJavaBridgeValue::CreateUndefinedValue();
return true;
}
@@ -139,29 +138,31 @@ bool GinJavaBridgeValueConverter::FromV8ArrayBuffer(
data_length = view.num_bytes();
}
if (!data) {
- *out = GinJavaBridgeValue::CreateUndefinedValue().release();
+ *out = GinJavaBridgeValue::CreateUndefinedValue();
return true;
}
- base::ListValue* result = new base::ListValue();
- *out = result;
+ std::unique_ptr<base::ListValue> result(new base::ListValue);
std::unique_ptr<TypedArraySerializer> serializer(
TypedArraySerializer::Create(value.As<v8::TypedArray>()));
- serializer->serializeTo(data, data_length, result);
+ serializer->serializeTo(data, data_length, result.get());
+ *out = std::move(result);
return true;
}
-bool GinJavaBridgeValueConverter::FromV8Number(v8::Local<v8::Number> value,
- base::Value** out) const {
+bool GinJavaBridgeValueConverter::FromV8Number(
+ v8::Local<v8::Number> value,
+ std::unique_ptr<base::Value>* out) const {
double double_value = value->Value();
if (std::isfinite(double_value))
return false;
- *out = GinJavaBridgeValue::CreateNonFiniteValue(double_value).release();
+ *out = GinJavaBridgeValue::CreateNonFiniteValue(double_value);
return true;
}
-bool GinJavaBridgeValueConverter::FromV8Undefined(base::Value** out) const {
- *out = GinJavaBridgeValue::CreateUndefinedValue().release();
+bool GinJavaBridgeValueConverter::FromV8Undefined(
+ std::unique_ptr<base::Value>* out) const {
+ *out = GinJavaBridgeValue::CreateUndefinedValue();
return true;
}
diff --git a/chromium/content/renderer/java/gin_java_bridge_value_converter.h b/chromium/content/renderer/java/gin_java_bridge_value_converter.h
index 2e48f199db3..9ab3849a3f5 100644
--- a/chromium/content/renderer/java/gin_java_bridge_value_converter.h
+++ b/chromium/content/renderer/java/gin_java_bridge_value_converter.h
@@ -27,15 +27,15 @@ class GinJavaBridgeValueConverter : public content::V8ValueConverter::Strategy {
// content::V8ValueConverter::Strategy
bool FromV8Object(v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate,
const FromV8ValueCallback& callback) const override;
bool FromV8ArrayBuffer(v8::Local<v8::Object> value,
- base::Value** out,
+ std::unique_ptr<base::Value>* out,
v8::Isolate* isolate) const override;
bool FromV8Number(v8::Local<v8::Number> value,
- base::Value** out) const override;
- bool FromV8Undefined(base::Value** out) const override;
+ std::unique_ptr<base::Value>* out) const override;
+ bool FromV8Undefined(std::unique_ptr<base::Value>* out) const override;
private:
std::unique_ptr<V8ValueConverter> converter_;
diff --git a/chromium/content/renderer/layout_test_dependencies.h b/chromium/content/renderer/layout_test_dependencies.h
new file mode 100644
index 00000000000..743c61d2c7a
--- /dev/null
+++ b/chromium/content/renderer/layout_test_dependencies.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_RENDER_LAYOUT_TEST_DEPENDENCIES_H_
+#define CONTENT_RENDER_LAYOUT_TEST_DEPENDENCIES_H_
+
+#include <stdint.h>
+#include <memory>
+
+#include "base/memory/ref_counted.h"
+
+namespace cc {
+class ContextProvider;
+class OutputSurface;
+}
+
+namespace gpu {
+class GpuChannelHost;
+}
+
+namespace content {
+class CompositorDependencies;
+
+// This class allows injection of LayoutTest-specific behaviour to the
+// RenderThreadImpl.
+class LayoutTestDependencies {
+ public:
+ virtual std::unique_ptr<cc::OutputSurface> CreateOutputSurface(
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel,
+ scoped_refptr<cc::ContextProvider> compositor_context_provider,
+ scoped_refptr<cc::ContextProvider> worker_context_provider,
+ CompositorDependencies* deps) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDER_LAYOUT_TEST_DEPENDENCIES_H_
diff --git a/chromium/content/renderer/manifest/manifest_manager.cc b/chromium/content/renderer/manifest/manifest_manager.cc
index 1f9d4ed9bbc..69a75de2500 100644
--- a/chromium/content/renderer/manifest/manifest_manager.cc
+++ b/chromium/content/renderer/manifest/manifest_manager.cc
@@ -206,4 +206,8 @@ void ManifestManager::ResolveCallbacks(ResolveState state) {
}
}
+void ManifestManager::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/manifest/manifest_manager.h b/chromium/content/renderer/manifest/manifest_manager.h
index 6ed61226ef3..554617cdcbe 100644
--- a/chromium/content/renderer/manifest/manifest_manager.h
+++ b/chromium/content/renderer/manifest/manifest_manager.h
@@ -54,6 +54,9 @@ class ManifestManager : public RenderFrameObserver {
ResolveStateFailure
};
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
// Called when receiving a ManifestManagerMsg_RequestManifest from the browser
// process.
void OnHasManifest(int request_id);
diff --git a/chromium/content/renderer/manifest/manifest_parser.cc b/chromium/content/renderer/manifest/manifest_parser.cc
index 1222a556c48..23dca88bb9b 100644
--- a/chromium/content/renderer/manifest/manifest_parser.cc
+++ b/chromium/content/renderer/manifest/manifest_parser.cc
@@ -17,76 +17,14 @@
#include "content/public/common/manifest.h"
#include "content/renderer/manifest/manifest_uma_util.h"
#include "third_party/WebKit/public/platform/WebColor.h"
+#include "third_party/WebKit/public/platform/WebIconSizesParser.h"
+#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebCSSParser.h"
#include "ui/gfx/geometry/size.h"
namespace content {
-namespace {
-
-// Helper function that returns whether the given |str| is a valid width or
-// height value for an icon sizes per:
-// https://html.spec.whatwg.org/multipage/semantics.html#attr-link-sizes
-bool IsValidIconWidthOrHeight(const std::string& str) {
- if (str.empty() || str[0] == '0')
- return false;
- for (size_t i = 0; i < str.size(); ++i)
- if (!base::IsAsciiDigit(str[i]))
- return false;
- return true;
-}
-
-// Parses the 'sizes' attribute of an icon as described in the HTML spec:
-// https://html.spec.whatwg.org/multipage/semantics.html#attr-link-sizes
-// Return a vector of gfx::Size that contains the valid sizes found. "Any" is
-// represented by gfx::Size(0, 0).
-// TODO(mlamouri): this is implemented as a separate function because it should
-// be refactored with the other icon sizes parsing implementations, see
-// http://crbug.com/416477
-std::vector<gfx::Size> ParseIconSizesHTML(const base::string16& sizes_str16) {
- if (!base::IsStringASCII(sizes_str16))
- return std::vector<gfx::Size>();
-
- std::vector<gfx::Size> sizes;
- std::string sizes_str =
- base::ToLowerASCII(base::UTF16ToUTF8(sizes_str16));
- std::vector<std::string> sizes_str_list = base::SplitString(
- sizes_str, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
-
- for (size_t i = 0; i < sizes_str_list.size(); ++i) {
- std::string& size_str = sizes_str_list[i];
- if (size_str == "any") {
- sizes.push_back(gfx::Size(0, 0));
- continue;
- }
-
- // It is expected that [0] => width and [1] => height after the split.
- std::vector<std::string> size_list = base::SplitString(
- size_str, "x", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
- if (size_list.size() != 2)
- continue;
- if (!IsValidIconWidthOrHeight(size_list[0]) ||
- !IsValidIconWidthOrHeight(size_list[1])) {
- continue;
- }
-
- int width, height;
- if (!base::StringToInt(size_list[0], &width) ||
- !base::StringToInt(size_list[1], &height)) {
- continue;
- }
-
- sizes.push_back(gfx::Size(width, height));
- }
-
- return sizes;
-}
-
-} // anonymous namespace
-
-
ManifestParser::ManifestParser(const base::StringPiece& data,
const GURL& manifest_url,
const GURL& document_url)
@@ -126,6 +64,7 @@ void ManifestParser::Parse() {
manifest_.name = ParseName(*dictionary);
manifest_.short_name = ParseShortName(*dictionary);
manifest_.start_url = ParseStartURL(*dictionary);
+ manifest_.scope = ParseScope(*dictionary, manifest_.start_url);
manifest_.display = ParseDisplay(*dictionary);
manifest_.orientation = ParseOrientation(*dictionary);
manifest_.icons = ParseIcons(*dictionary);
@@ -218,7 +157,10 @@ GURL ManifestParser::ParseURL(const base::DictionaryValue& dictionary,
if (url_str.is_null())
return GURL();
- return base_url.Resolve(url_str.string());
+ GURL resolved = base_url.Resolve(url_str.string());
+ if (!resolved.is_valid())
+ AddErrorInfo("property '" + key + "' ignored, URL is invalid.");
+ return resolved;
}
base::NullableString16 ManifestParser::ParseName(
@@ -245,6 +187,34 @@ GURL ManifestParser::ParseStartURL(const base::DictionaryValue& dictionary) {
return start_url;
}
+GURL ManifestParser::ParseScope(const base::DictionaryValue& dictionary,
+ const GURL& start_url) {
+ GURL scope = ParseURL(dictionary, "scope", manifest_url_);
+ if (!scope.is_valid()) {
+ return GURL();
+ }
+
+ if (scope.GetOrigin() != document_url_.GetOrigin()) {
+ AddErrorInfo("property 'scope' ignored, should be "
+ "same origin as document.");
+ return GURL();
+ }
+
+ // According to the spec, if the start_url cannot be parsed, the document URL
+ // should be used as the start URL. If the start_url could not be parsed,
+ // check that the document URL is within scope.
+ GURL check_in_scope = start_url.is_empty() ? document_url_ : start_url;
+ if (check_in_scope.GetOrigin() != scope.GetOrigin() ||
+ !base::StartsWith(check_in_scope.path(), scope.path(),
+ base::CompareCase::SENSITIVE)) {
+ AddErrorInfo(
+ "property 'scope' ignored. Start url should be within scope "
+ "of scope URL.");
+ return GURL();
+ }
+ return scope;
+}
+
blink::WebDisplayMode ManifestParser::ParseDisplay(
const base::DictionaryValue& dictionary) {
base::NullableString16 display = ParseString(dictionary, "display", Trim);
@@ -311,11 +281,16 @@ base::NullableString16 ManifestParser::ParseIconType(
std::vector<gfx::Size> ManifestParser::ParseIconSizes(
const base::DictionaryValue& icon) {
base::NullableString16 sizes_str = ParseString(icon, "sizes", NoTrim);
+ std::vector<gfx::Size> sizes;
if (sizes_str.is_null())
- return std::vector<gfx::Size>();
+ return sizes;
- std::vector<gfx::Size> sizes = ParseIconSizesHTML(sizes_str.string());
+ blink::WebVector<blink::WebSize> web_sizes =
+ blink::WebIconSizesParser::parseIconSizes(sizes_str.string());
+ sizes.resize(web_sizes.size());
+ for (size_t i = 0; i < web_sizes.size(); ++i)
+ sizes[i] = web_sizes[i];
if (sizes.empty()) {
AddErrorInfo("found icon with no valid size.");
}
diff --git a/chromium/content/renderer/manifest/manifest_parser.h b/chromium/content/renderer/manifest/manifest_parser.h
index 0f12c5a4745..2c8d2076e33 100644
--- a/chromium/content/renderer/manifest/manifest_parser.h
+++ b/chromium/content/renderer/manifest/manifest_parser.h
@@ -90,6 +90,12 @@ class CONTENT_EXPORT ManifestParser {
base::NullableString16 ParseShortName(
const base::DictionaryValue& dictionary);
+ // Parses the 'scope' field of the manifest, as defined in:
+ // http://w3c.github.io/manifest/#dfn-steps-for-processing-the-scope-member
+ // Returns the parsed GURL if any, an empty GURL if the parsing failed.
+ GURL ParseScope(const base::DictionaryValue& dictionary,
+ const GURL& start_url);
+
// Parses the 'start_url' field of the manifest, as defined in:
// http://w3c.github.io/manifest/#dfn-steps-for-processing-the-start_url-member
// Returns the parsed GURL if any, an empty GURL if the parsing failed.
diff --git a/chromium/content/renderer/manifest/manifest_parser_unittest.cc b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
index b86a0e7e6ca..4311531436d 100644
--- a/chromium/content/renderer/manifest/manifest_parser_unittest.cc
+++ b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
@@ -29,9 +29,9 @@ class ManifestParserTest : public testing::Test {
~ManifestParserTest() override {}
Manifest ParseManifestWithURLs(const base::StringPiece& data,
- const GURL& document_url,
- const GURL& manifest_url) {
- ManifestParser parser(data, document_url, manifest_url);
+ const GURL& manifest_url,
+ const GURL& document_url) {
+ ManifestParser parser(data, manifest_url, document_url);
parser.Parse();
std::vector<ManifestDebugInfo::Error> errors;
parser.TakeErrors(&errors);
@@ -44,7 +44,7 @@ class ManifestParserTest : public testing::Test {
Manifest ParseManifest(const base::StringPiece& data) {
return ParseManifestWithURLs(
- data, default_document_url, default_manifest_url);
+ data, default_manifest_url, default_document_url);
}
const std::vector<std::string>& errors() const {
@@ -101,6 +101,7 @@ TEST_F(ManifestParserTest, EmptyStringNull) {
ASSERT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
ASSERT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
ASSERT_TRUE(manifest.gcm_sender_id.is_null());
+ ASSERT_TRUE(manifest.scope.is_empty());
}
TEST_F(ManifestParserTest, ValidNoContentParses) {
@@ -119,6 +120,7 @@ TEST_F(ManifestParserTest, ValidNoContentParses) {
ASSERT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
ASSERT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
ASSERT_TRUE(manifest.gcm_sender_id.is_null());
+ ASSERT_TRUE(manifest.scope.is_empty());
}
TEST_F(ManifestParserTest, MultipleErrorsReporting) {
@@ -253,6 +255,14 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
errors()[0]);
}
+ // Don't parse if property isn't a valid URL.
+ {
+ Manifest manifest = ParseManifest("{ \"start_url\": \"http://www.google.ca:a\" }");
+ ASSERT_TRUE(manifest.start_url.is_empty());
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("property 'start_url' ignored, URL is invalid.", errors()[0]);
+ }
+
// Absolute start_url, same origin with document.
{
Manifest manifest =
@@ -287,6 +297,151 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
}
}
+TEST_F(ManifestParserTest, ScopeParseRules) {
+ // Smoke test.
+ {
+ Manifest manifest = ParseManifest(
+ "{ \"scope\": \"land\", \"start_url\": \"land/landing.html\" }");
+ ASSERT_EQ(manifest.scope.spec(),
+ default_document_url.Resolve("land").spec());
+ ASSERT_FALSE(manifest.IsEmpty());
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Whitespaces.
+ {
+ Manifest manifest = ParseManifest(
+ "{ \"scope\": \" land \", \"start_url\": \"land/landing.html\" }");
+ ASSERT_EQ(manifest.scope.spec(),
+ default_document_url.Resolve("land").spec());
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Don't parse if property isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"scope\": {} }");
+ ASSERT_TRUE(manifest.scope.is_empty());
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("property 'scope' ignored, type string expected.", errors()[0]);
+ }
+
+ // Don't parse if property isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"scope\": 42 }");
+ ASSERT_TRUE(manifest.scope.is_empty());
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("property 'scope' ignored, type string expected.", errors()[0]);
+ }
+
+ // Absolute scope, start URL is in scope.
+ {
+ Manifest manifest = ParseManifestWithURLs(
+ "{ \"scope\": \"http://foo.com/land\", "
+ "\"start_url\": \"http://foo.com/land/landing.html\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/index.html"));
+ ASSERT_EQ(manifest.scope.spec(), "http://foo.com/land");
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Absolute scope, start URL is not in scope.
+ {
+ Manifest manifest =
+ ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\", "
+ "\"start_url\": \"http://foo.com/index.html\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/index.html"));
+ ASSERT_TRUE(manifest.scope.is_empty());
+ EXPECT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("property 'scope' ignored. Start url should be within scope "
+ "of scope URL.",
+ errors()[0]);
+ }
+
+ // Absolute scope, start URL has different origin than scope URL.
+ {
+ Manifest manifest =
+ ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\", "
+ "\"start_url\": \"http://bar.com/land/landing.html\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/index.html"));
+ ASSERT_TRUE(manifest.scope.is_empty());
+ ASSERT_EQ(2u, GetErrorCount());
+ EXPECT_EQ(
+ "property 'start_url' ignored, should be same origin as document.",
+ errors()[0]);
+ EXPECT_EQ("property 'scope' ignored. Start url should be within scope "
+ "of scope URL.",
+ errors()[1]);
+ }
+
+ // scope and start URL have diferent origin than document URL.
+ {
+ Manifest manifest =
+ ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\", "
+ "\"start_url\": \"http://foo.com/land/landing.html\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://bar.com/index.html"));
+ ASSERT_TRUE(manifest.scope.is_empty());
+ ASSERT_EQ(2u, GetErrorCount());
+ EXPECT_EQ(
+ "property 'start_url' ignored, should be same origin as document.",
+ errors()[0]);
+ EXPECT_EQ("property 'scope' ignored, should be same origin as document.",
+ errors()[1]);
+ }
+
+ // No start URL. Document URL is in scope.
+ {
+ Manifest manifest = ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/land/index.html"));
+ ASSERT_EQ(manifest.scope.spec(), "http://foo.com/land");
+ ASSERT_EQ(0u, GetErrorCount());
+ }
+
+ // No start URL. Document is out of scope.
+ {
+ Manifest manifest = ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/index.html"));
+ ASSERT_EQ(1u, GetErrorCount());
+ EXPECT_EQ("property 'scope' ignored. Start url should be within scope "
+ "of scope URL.",
+ errors()[0]);
+ }
+
+ // Resolving has to happen based on the manifest_url.
+ {
+ Manifest manifest = ParseManifestWithURLs(
+ "{ \"scope\": \"treasure\" }",
+ GURL("http://foo.com/map/manifest.json"),
+ GURL("http://foo.com/map/treasure/island/index.html"));
+ ASSERT_EQ(manifest.scope.spec(), "http://foo.com/map/treasure");
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Scope is parent directory.
+ {
+ Manifest manifest =
+ ParseManifestWithURLs("{ \"scope\": \"..\" }",
+ GURL("http://foo.com/map/manifest.json"),
+ GURL("http://foo.com/index.html"));
+ ASSERT_EQ(manifest.scope.spec(), "http://foo.com/");
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+
+ // Scope tries to go up past domain.
+ {
+ Manifest manifest =
+ ParseManifestWithURLs("{ \"scope\": \"../..\" }",
+ GURL("http://foo.com/map/manifest.json"),
+ GURL("http://foo.com/index.html"));
+ ASSERT_EQ(manifest.scope.spec(), "http://foo.com/");
+ EXPECT_EQ(0u, GetErrorCount());
+ }
+}
+
TEST_F(ManifestParserTest, DisplayParserRules) {
// Smoke test.
{
@@ -512,7 +667,7 @@ TEST_F(ManifestParserTest, IconsParseRules) {
{
Manifest manifest = ParseManifest("{ \"icons\": [ { \"src\": \"\" } ] }");
EXPECT_EQ(manifest.icons.size(), 1u);
- EXPECT_EQ(manifest.icons[0].src.spec(), "http://foo.com/index.html");
+ EXPECT_EQ(manifest.icons[0].src.spec(), "http://foo.com/manifest.json");
EXPECT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
@@ -716,7 +871,6 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
{
Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \"x 40xx 1x2x3 x42 42xx42\" } ] }");
- gfx::Size any = gfx::Size(0, 0);
EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("found icon with no valid size.",
diff --git a/chromium/content/renderer/media/DEPS b/chromium/content/renderer/media/DEPS
index 29c1d241f42..37029086b55 100644
--- a/chromium/content/renderer/media/DEPS
+++ b/chromium/content/renderer/media/DEPS
@@ -1,7 +1,5 @@
include_rules = [
"+third_party/libvpx",
- # For video copying, cropping and scaling.
- # TODO(wuchengli): remove this when RTCVideoEncoder supports zero copy.
"+third_party/libyuv",
'+third_party/openh264/src/codec/api/svc',
'+third_party/opus',
diff --git a/chromium/content/renderer/media/android/media_info_loader_unittest.cc b/chromium/content/renderer/media/android/media_info_loader_unittest.cc
index 306ccdb50b8..3e0e1460410 100644
--- a/chromium/content/renderer/media/android/media_info_loader_unittest.cc
+++ b/chromium/content/renderer/media/android/media_info_loader_unittest.cc
@@ -5,6 +5,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "content/renderer/media/android/media_info_loader.h"
#include "content/test/mock_webframeclient.h"
#include "content/test/mock_weburlloader.h"
@@ -39,7 +40,7 @@ static const int kHttpNotFound = 404;
class MediaInfoLoaderTest : public testing::Test {
public:
MediaInfoLoaderTest()
- : view_(WebView::create(NULL)),
+ : view_(WebView::create(nullptr, blink::WebPageVisibilityStateVisible)),
frame_(WebLocalFrame::create(blink::WebTreeScopeType::Document,
&client_)) {
view_->setMainFrame(frame_);
@@ -84,7 +85,7 @@ class MediaInfoLoaderTest : public testing::Test {
loader_->willFollowRedirect(url_loader_, new_request, redirect_response);
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
void SendResponse(
diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.cc b/chromium/content/renderer/media/android/renderer_media_player_manager.cc
index a115772c0bc..b49a98e6563 100644
--- a/chromium/content/renderer/media/android/renderer_media_player_manager.cc
+++ b/chromium/content/renderer/media/android/renderer_media_player_manager.cc
@@ -281,6 +281,10 @@ media::RendererMediaPlayerInterface* RendererMediaPlayerManager::GetMediaPlayer(
return NULL;
}
+void RendererMediaPlayerManager::OnDestruct() {
+ delete this;
+}
+
#if defined(VIDEO_HOLE)
void RendererMediaPlayerManager::RequestExternalSurface(
int player_id,
diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.h b/chromium/content/renderer/media/android/renderer_media_player_manager.h
index 2baa846a0ad..9976488814d 100644
--- a/chromium/content/renderer/media/android/renderer_media_player_manager.h
+++ b/chromium/content/renderer/media/android/renderer_media_player_manager.h
@@ -116,6 +116,9 @@ class RendererMediaPlayerManager :
#endif // defined(VIDEO_HOLE)
private:
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
// Message handlers.
void OnMediaMetadataChanged(int player_id,
base::TimeDelta duration,
diff --git a/chromium/content/renderer/media/android/renderer_media_session_manager.cc b/chromium/content/renderer/media/android/renderer_media_session_manager.cc
index 93d19281f94..b5331c7472a 100644
--- a/chromium/content/renderer/media/android/renderer_media_session_manager.cc
+++ b/chromium/content/renderer/media/android/renderer_media_session_manager.cc
@@ -33,6 +33,10 @@ bool RendererMediaSessionManager::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
+void RendererMediaSessionManager::OnDestruct() {
+ delete this;
+}
+
int RendererMediaSessionManager::RegisterMediaSession(
WebMediaSessionAndroid* session) {
sessions_[next_session_id_] = session;
diff --git a/chromium/content/renderer/media/android/renderer_media_session_manager.h b/chromium/content/renderer/media/android/renderer_media_session_manager.h
index bc1808c3feb..fbfd5c848b0 100644
--- a/chromium/content/renderer/media/android/renderer_media_session_manager.h
+++ b/chromium/content/renderer/media/android/renderer_media_session_manager.h
@@ -44,6 +44,9 @@ class CONTENT_EXPORT RendererMediaSessionManager : public RenderFrameObserver {
private:
friend class WebMediaSessionTest;
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
std::map<int, WebMediaSessionAndroid*> sessions_;
int next_session_id_;
diff --git a/chromium/content/renderer/media/android/renderer_surface_view_manager.cc b/chromium/content/renderer/media/android/renderer_surface_view_manager.cc
index 6f54b1e30a1..48fd548c5ac 100644
--- a/chromium/content/renderer/media/android/renderer_surface_view_manager.cc
+++ b/chromium/content/renderer/media/android/renderer_surface_view_manager.cc
@@ -42,9 +42,14 @@ void RendererSurfaceViewManager::NaturalSizeChanged(const gfx::Size& size) {
void RendererSurfaceViewManager::OnFullscreenSurfaceCreated(int surface_id) {
DVLOG(3) << __FUNCTION__ << ": surface_id: " << surface_id;
- DCHECK(!pending_surface_created_cb_.is_null());
- pending_surface_created_cb_.Run(surface_id);
- pending_surface_created_cb_.Reset();
+ if (!pending_surface_created_cb_.is_null()) {
+ pending_surface_created_cb_.Run(surface_id);
+ pending_surface_created_cb_.Reset();
+ }
+}
+
+void RendererSurfaceViewManager::OnDestruct() {
+ delete this;
}
} // namespace content
diff --git a/chromium/content/renderer/media/android/renderer_surface_view_manager.h b/chromium/content/renderer/media/android/renderer_surface_view_manager.h
index 7022744bae1..f2918f37877 100644
--- a/chromium/content/renderer/media/android/renderer_surface_view_manager.h
+++ b/chromium/content/renderer/media/android/renderer_surface_view_manager.h
@@ -33,6 +33,9 @@ class CONTENT_EXPORT RendererSurfaceViewManager : public media::SurfaceManager,
void NaturalSizeChanged(const gfx::Size& size) override;
private:
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
void OnFullscreenSurfaceCreated(int surface_id);
// Set when a surface request is in progress.
diff --git a/chromium/content/renderer/media/android/webmediaplayer_android.cc b/chromium/content/renderer/media/android/webmediaplayer_android.cc
index eab113b48d6..7adb15e764c 100644
--- a/chromium/content/renderer/media/android/webmediaplayer_android.cc
+++ b/chromium/content/renderer/media/android/webmediaplayer_android.cc
@@ -287,7 +287,8 @@ WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
// Part of |media_source_delegate_| needs to be stopped on the media thread.
// Wait until |media_source_delegate_| is fully stopped before tearing
// down other objects.
- base::WaitableEvent waiter(false, false);
+ base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
media_source_delegate_->Stop(
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
waiter.Wait();
@@ -865,7 +866,7 @@ void WebMediaPlayerAndroid::OnPlaybackComplete() {
// If the loop attribute is set, timeChanged() will update the current time
// to 0. It will perform a seek to 0. Issue a command to the player to start
// playing after seek completes.
- if (seeking_ && seek_time_.is_zero())
+ if (is_playing_ && seeking_ && seek_time_.is_zero())
player_manager_->Start(player_id_);
else
playback_completed_ = true;
@@ -1513,11 +1514,6 @@ void WebMediaPlayerAndroid::OnWaitingForDecryptionKey() {
}
void WebMediaPlayerAndroid::OnHidden() {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableMediaSuspend)) {
- return;
- }
-
OnSuspendRequested(false);
}
@@ -1527,6 +1523,12 @@ void WebMediaPlayerAndroid::OnShown() {
}
void WebMediaPlayerAndroid::OnSuspendRequested(bool must_suspend) {
+ if (!must_suspend &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableMediaSuspend)) {
+ return;
+ }
+
// If we're idle or playing video, pause and release resources; audio only
// players are allowed to continue unless indicated otherwise by the call.
if (must_suspend || (paused() && playback_completed_) || hasVideo())
diff --git a/chromium/content/renderer/media/audio_device_factory.cc b/chromium/content/renderer/media/audio_device_factory.cc
index a4b1d77c034..9f9b8c15962 100644
--- a/chromium/content/renderer/media/audio_device_factory.cc
+++ b/chromium/content/renderer/media/audio_device_factory.cc
@@ -15,7 +15,9 @@
#include "content/renderer/render_thread_impl.h"
#include "media/audio/audio_input_device.h"
#include "media/audio/audio_output_device.h"
+#include "media/base/audio_latency.h"
#include "media/base/audio_renderer_mixer_input.h"
+#include "media/base/media_switches.h"
#include "url/origin.h"
namespace content {
@@ -29,11 +31,31 @@ namespace {
// chance device authorization response is never received from the browser side.
// In this case we will time out, to avoid renderer hang forever waiting for
// device authorization (http://crbug/615589). This will result in "no audio".
-const int64_t kMaxAuthorizationTimeoutMs = 900;
+const int64_t kMaxAuthorizationTimeoutMs = 1000;
#else
const int64_t kMaxAuthorizationTimeoutMs = 0; // No timeout.
#endif // defined(OS_WIN)
+media::AudioLatency::LatencyType GetSourceLatencyType(
+ AudioDeviceFactory::SourceType source) {
+ switch (source) {
+ case AudioDeviceFactory::kSourceWebAudioInteractive:
+ return media::AudioLatency::LATENCY_INTERACTIVE;
+ case AudioDeviceFactory::kSourceNone:
+ case AudioDeviceFactory::kSourceWebRtc:
+ case AudioDeviceFactory::kSourceNonRtcAudioTrack:
+ case AudioDeviceFactory::kSourceWebAudioBalanced:
+ return media::AudioLatency::LATENCY_RTC;
+ case AudioDeviceFactory::kSourceMediaElement:
+ case AudioDeviceFactory::kSourceWebAudioPlayback:
+ return media::AudioLatency::LATENCY_PLAYBACK;
+ case AudioDeviceFactory::kSourceWebAudioExact:
+ return media::AudioLatency::LATENCY_EXACT_MS;
+ }
+ NOTREACHED();
+ return media::AudioLatency::LATENCY_INTERACTIVE;
+}
+
scoped_refptr<media::AudioOutputDevice> NewOutputDevice(
int render_frame_id,
int session_id,
@@ -57,12 +79,12 @@ bool IsMixable(AudioDeviceFactory::SourceType source_type) {
if (source_type == AudioDeviceFactory::kSourceMediaElement)
return true; // Must ALWAYS go through mixer.
- // TODO(olka): make a decision for the rest of the sources basing on OS
- // type and configuration parameters.
- return false;
+ // Mix everything if experiment is enabled; otherwise mix nothing else.
+ return base::FeatureList::IsEnabled(media::kNewAudioRenderingMixingStrategy);
}
scoped_refptr<media::SwitchableAudioRendererSink> NewMixableSink(
+ AudioDeviceFactory::SourceType source_type,
int render_frame_id,
int session_id,
const std::string& device_id,
@@ -70,7 +92,8 @@ scoped_refptr<media::SwitchableAudioRendererSink> NewMixableSink(
RenderThreadImpl* render_thread = RenderThreadImpl::current();
return scoped_refptr<media::AudioRendererMixerInput>(
render_thread->GetAudioRendererMixerManager()->CreateInput(
- render_frame_id, session_id, device_id, security_origin));
+ render_frame_id, session_id, device_id, security_origin,
+ GetSourceLatencyType(source_type)));
}
} // namespace
@@ -102,7 +125,7 @@ AudioDeviceFactory::NewAudioRendererSink(SourceType source_type,
}
if (IsMixable(source_type))
- return NewMixableSink(render_frame_id, session_id, device_id,
+ return NewMixableSink(source_type, render_frame_id, session_id, device_id,
security_origin);
return NewFinalAudioRendererSink(render_frame_id, session_id, device_id,
@@ -127,7 +150,7 @@ AudioDeviceFactory::NewSwitchableAudioRendererSink(
}
if (IsMixable(source_type))
- return NewMixableSink(render_frame_id, session_id, device_id,
+ return NewMixableSink(source_type, render_frame_id, session_id, device_id,
security_origin);
// AudioOutputDevice is not RestartableAudioRendererSink, so we can't return
@@ -152,22 +175,16 @@ AudioDeviceFactory::NewAudioCapturerSource(int render_frame_id) {
}
// static
-// TODO(http://crbug.com/587461): Find a better way to check if device exists
-// and is authorized.
media::OutputDeviceInfo AudioDeviceFactory::GetOutputDeviceInfo(
int render_frame_id,
int session_id,
const std::string& device_id,
const url::Origin& security_origin) {
- scoped_refptr<media::AudioRendererSink> sink = NewFinalAudioRendererSink(
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ DCHECK(render_thread) << "RenderThreadImpl is not instantiated, or "
+ << "GetOutputDeviceInfo() is called on a wrong thread ";
+ return render_thread->GetAudioRendererMixerManager()->GetOutputDeviceInfo(
render_frame_id, session_id, device_id, security_origin);
-
- const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo();
-
- // TODO(olka): Cache it and reuse, http://crbug.com/586161
- sink->Stop(); // Must be stopped.
-
- return device_info;
}
AudioDeviceFactory::AudioDeviceFactory() {
diff --git a/chromium/content/renderer/media/audio_device_factory.h b/chromium/content/renderer/media/audio_device_factory.h
index a8b8cb8b335..66936892b0b 100644
--- a/chromium/content/renderer/media/audio_device_factory.h
+++ b/chromium/content/renderer/media/audio_device_factory.h
@@ -32,14 +32,20 @@ namespace content {
// AudioCapturerSourceFactory.
class CONTENT_EXPORT AudioDeviceFactory {
public:
- // Types of audio sources.
+ // Types of audio sources. Each source can have individual mixing and/or
+ // latency requirements for output. The source is specified by the client when
+ // requesting output sink from the factory, and the factory creates the output
+ // sink basing on those requirements.
enum SourceType {
kSourceNone = 0,
kSourceMediaElement,
kSourceWebRtc,
kSourceNonRtcAudioTrack,
- kSourceWebAudio,
- kSourceLast = kSourceWebAudio // Only used for validation of format.
+ kSourceWebAudioInteractive,
+ kSourceWebAudioBalanced,
+ kSourceWebAudioPlayback,
+ kSourceWebAudioExact,
+ kSourceLast = kSourceWebAudioExact // Only used for validation of format.
};
// Creates a sink for AudioRendererMixer.
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc b/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
index 75b7ed60f30..30f66fb3771 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
@@ -4,20 +4,116 @@
#include "content/renderer/media/audio_renderer_mixer_manager.h"
+#include <algorithm>
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/sparse_histogram.h"
#include "build/build_config.h"
-#include "content/renderer/media/audio_device_factory.h"
+#include "content/renderer/media/audio_renderer_sink_cache.h"
#include "media/audio/audio_device_description.h"
#include "media/base/audio_hardware_config.h"
#include "media/base/audio_renderer_mixer.h"
#include "media/base/audio_renderer_mixer_input.h"
+namespace {
+// Calculate mixer output parameters based on mixer input parameters and
+// hardware parameters for audio output.
+media::AudioParameters GetMixerOutputParams(
+ const media::AudioParameters& input_params,
+ const media::AudioParameters& hardware_params,
+ media::AudioLatency::LatencyType latency) {
+ int output_sample_rate = input_params.sample_rate();
+ bool valid_not_fake_hardware_params =
+ hardware_params.format() != media::AudioParameters::AUDIO_FAKE &&
+ hardware_params.IsValid();
+ int preferred_high_latency_output_buffer_size = 0;
+
+#if !defined(OS_CHROMEOS)
+ // On ChromeOS as well as when a fake device is used, we can rely on the
+ // playback device to handle resampling, so don't waste cycles on it here.
+ // On other systems if hardware parameters are valid and the device is not
+ // fake, resample to hardware sample rate. Otherwise, pass the input one and
+ // let the browser side handle automatic fallback.
+ if (valid_not_fake_hardware_params) {
+ output_sample_rate = hardware_params.sample_rate();
+ preferred_high_latency_output_buffer_size =
+ hardware_params.frames_per_buffer();
+ }
+#endif
+
+ int output_buffer_size = 0;
+
+ // Adjust output buffer size according to the latency requirement.
+ switch (latency) {
+ case media::AudioLatency::LATENCY_INTERACTIVE:
+ output_buffer_size = media::AudioLatency::GetInteractiveBufferSize(
+ hardware_params.frames_per_buffer());
+ break;
+ case media::AudioLatency::LATENCY_RTC:
+ output_buffer_size = media::AudioLatency::GetRtcBufferSize(
+ output_sample_rate, valid_not_fake_hardware_params
+ ? hardware_params.frames_per_buffer()
+ : 0);
+ break;
+ case media::AudioLatency::LATENCY_PLAYBACK:
+ output_buffer_size = media::AudioLatency::GetHighLatencyBufferSize(
+ output_sample_rate, preferred_high_latency_output_buffer_size);
+ break;
+ case media::AudioLatency::LATENCY_EXACT_MS:
+ // TODO(olka): add support when WebAudio requires it.
+ default:
+ NOTREACHED();
+ }
+
+ DCHECK_NE(output_buffer_size, 0);
+
+ // Force to 16-bit output for now since we know that works everywhere;
+ // ChromeOS does not support other bit depths.
+ return media::AudioParameters(input_params.format(),
+ input_params.channel_layout(),
+ output_sample_rate, 16, output_buffer_size);
+}
+
+void LogMixerUmaHistogram(media::AudioLatency::LatencyType latency, int value) {
+ switch (latency) {
+ case media::AudioLatency::LATENCY_EXACT_MS:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Media.Audio.Render.AudioInputsPerMixer.LatencyExact", value, 1, 20,
+ 21);
+ return;
+ case media::AudioLatency::LATENCY_INTERACTIVE:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Media.Audio.Render.AudioInputsPerMixer.LatencyInteractive", value, 1,
+ 20, 21);
+ return;
+ case media::AudioLatency::LATENCY_RTC:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Media.Audio.Render.AudioInputsPerMixer.LatencyRtc", value, 1, 20,
+ 21);
+ return;
+ case media::AudioLatency::LATENCY_PLAYBACK:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Media.Audio.Render.AudioInputsPerMixer.LatencyPlayback", value, 1,
+ 20, 21);
+ return;
+ default:
+ NOTREACHED();
+ }
+}
+
+} // namespace
+
namespace content {
-AudioRendererMixerManager::AudioRendererMixerManager() {}
+AudioRendererMixerManager::AudioRendererMixerManager(
+ std::unique_ptr<AudioRendererSinkCache> sink_cache)
+ : sink_cache_(std::move(sink_cache)) {
+ DCHECK(sink_cache_);
+}
AudioRendererMixerManager::~AudioRendererMixerManager() {
// References to AudioRendererMixers may be owned by garbage collected
@@ -25,122 +121,130 @@ AudioRendererMixerManager::~AudioRendererMixerManager() {
// |mixers_| may leak (i.e., may be non-empty at this time) as well.
}
+// static
+std::unique_ptr<AudioRendererMixerManager> AudioRendererMixerManager::Create() {
+ return base::WrapUnique(
+ new AudioRendererMixerManager(AudioRendererSinkCache::Create()));
+}
+
media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput(
int source_render_frame_id,
int session_id,
const std::string& device_id,
- const url::Origin& security_origin) {
- // base::Unretained() is safe since AudioRendererMixerManager lives on the
- // renderer thread and is destroyed on renderer thread destruction.
+ const url::Origin& security_origin,
+ media::AudioLatency::LatencyType latency) {
+ // AudioRendererMixerManager lives on the renderer thread and is destroyed on
+ // renderer thread destruction, so it's safe to pass its pointer to a mixer
+ // input.
return new media::AudioRendererMixerInput(
- base::Bind(&AudioRendererMixerManager::GetMixer, base::Unretained(this),
- source_render_frame_id),
- base::Bind(&AudioRendererMixerManager::RemoveMixer,
- base::Unretained(this), source_render_frame_id),
+ this, source_render_frame_id,
media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
device_id)
- ? AudioDeviceFactory::GetOutputDeviceInfo(
- source_render_frame_id, session_id, device_id, security_origin)
+ ? GetOutputDeviceInfo(source_render_frame_id, session_id, device_id,
+ security_origin)
.device_id()
: device_id,
- security_origin);
+ security_origin, latency);
}
media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
int source_render_frame_id,
- const media::AudioParameters& params,
+ const media::AudioParameters& input_params,
+ media::AudioLatency::LatencyType latency,
const std::string& device_id,
const url::Origin& security_origin,
media::OutputDeviceStatus* device_status) {
// Effects are not passed through to output creation, so ensure none are set.
- DCHECK_EQ(params.effects(), media::AudioParameters::NO_EFFECTS);
+ DCHECK_EQ(input_params.effects(), media::AudioParameters::NO_EFFECTS);
- const MixerKey key(source_render_frame_id, params, device_id,
+ const MixerKey key(source_render_frame_id, input_params, latency, device_id,
security_origin);
base::AutoLock auto_lock(mixers_lock_);
+ // Update latency map when the mixer is requested, i.e. there is an attempt to
+ // mix and output audio with a given latency. This is opposite to
+ // CreateInput() which creates a sink which is probably never used for output.
+ if (!latency_map_[latency]) {
+ latency_map_[latency] = 1;
+ // Log the updated latency map. This can't be done once in the end of the
+ // renderer lifetime, because the destructor is usually not called. So,
+ // we'll have a sort of exponential scale here, with a smaller subset
+ // logged both on its own and as a part of any larger subset.
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Media.Audio.Render.AudioMixing.LatencyMap",
+ latency_map_.to_ulong());
+ }
+
AudioRendererMixerMap::iterator it = mixers_.find(key);
if (it != mixers_.end()) {
if (device_status)
*device_status = media::OUTPUT_DEVICE_STATUS_OK;
it->second.ref_count++;
+ DVLOG(1) << "Reusing mixer: " << it->second.mixer;
return it->second.mixer;
}
scoped_refptr<media::AudioRendererSink> sink =
- AudioDeviceFactory::NewAudioRendererMixerSink(source_render_frame_id, 0,
- device_id, security_origin);
+ sink_cache_->GetSink(source_render_frame_id, device_id, security_origin);
const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo();
if (device_status)
*device_status = device_info.device_status();
if (device_info.device_status() != media::OUTPUT_DEVICE_STATUS_OK) {
+ sink_cache_->ReleaseSink(sink.get());
sink->Stop();
return nullptr;
}
- // On ChromeOS as well as when a fake device is used, we can rely on the
- // playback device to handle resampling, so don't waste cycles on it here.
- int sample_rate = params.sample_rate();
- int buffer_size =
- media::AudioHardwareConfig::GetHighLatencyBufferSize(sample_rate, 0);
-
-#if !defined(OS_CHROMEOS)
- const media::AudioParameters& hardware_params = device_info.output_params();
-
- // If we have valid, non-fake hardware parameters, use them. Otherwise, pass
- // on the input params and let the browser side handle automatic fallback.
- if (hardware_params.format() != media::AudioParameters::AUDIO_FAKE &&
- hardware_params.IsValid()) {
- sample_rate = hardware_params.sample_rate();
- buffer_size = media::AudioHardwareConfig::GetHighLatencyBufferSize(
- sample_rate, hardware_params.frames_per_buffer());
- }
-#endif
-
- // Create output parameters based on the audio hardware configuration for
- // passing on to the output sink. Force to 16-bit output for now since we
- // know that works everywhere; ChromeOS does not support other bit depths.
- media::AudioParameters output_params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY, params.channel_layout(),
- sample_rate, 16, buffer_size);
- DCHECK(output_params.IsValid());
-
- media::AudioRendererMixer* mixer =
- new media::AudioRendererMixer(output_params, sink);
- AudioRendererMixerReference mixer_reference = { mixer, 1 };
+ const media::AudioParameters& mixer_output_params =
+ GetMixerOutputParams(input_params, device_info.output_params(), latency);
+ media::AudioRendererMixer* mixer = new media::AudioRendererMixer(
+ mixer_output_params, sink, base::Bind(LogMixerUmaHistogram, latency));
+ AudioRendererMixerReference mixer_reference = {mixer, 1, sink.get()};
mixers_[key] = mixer_reference;
+ DVLOG(1) << __FUNCTION__ << " mixer: " << mixer << " latency: " << latency
+ << "\n input: " << input_params.AsHumanReadableString()
+ << "\noutput: " << mixer_output_params.AsHumanReadableString();
return mixer;
}
-void AudioRendererMixerManager::RemoveMixer(
- int source_render_frame_id,
- const media::AudioParameters& params,
- const std::string& device_id,
- const url::Origin& security_origin) {
- const MixerKey key(source_render_frame_id, params, device_id,
- security_origin);
+void AudioRendererMixerManager::ReturnMixer(media::AudioRendererMixer* mixer) {
base::AutoLock auto_lock(mixers_lock_);
-
- AudioRendererMixerMap::iterator it = mixers_.find(key);
+ AudioRendererMixerMap::iterator it = std::find_if(
+ mixers_.begin(), mixers_.end(),
+ [mixer](const std::pair<MixerKey, AudioRendererMixerReference>& val) {
+ return val.second.mixer == mixer;
+ });
DCHECK(it != mixers_.end());
// Only remove the mixer if AudioRendererMixerManager is the last owner.
it->second.ref_count--;
if (it->second.ref_count == 0) {
+ // The mixer will be deleted now, so release the sink.
+ sink_cache_->ReleaseSink(it->second.sink_ptr);
delete it->second.mixer;
mixers_.erase(it);
}
}
+media::OutputDeviceInfo AudioRendererMixerManager::GetOutputDeviceInfo(
+ int source_render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ return sink_cache_->GetSinkInfo(source_render_frame_id, session_id, device_id,
+ security_origin);
+}
+
AudioRendererMixerManager::MixerKey::MixerKey(
int source_render_frame_id,
const media::AudioParameters& params,
+ media::AudioLatency::LatencyType latency,
const std::string& device_id,
const url::Origin& security_origin)
: source_render_frame_id(source_render_frame_id),
params(params),
+ latency(latency),
device_id(device_id),
security_origin(security_origin) {}
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.h b/chromium/content/renderer/media/audio_renderer_mixer_manager.h
index 20a1aa59eaf..7d77212bbe6 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager.h
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager.h
@@ -5,31 +5,36 @@
#ifndef CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_
#define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_
+#include <bitset>
#include <map>
+#include <memory>
#include <string>
-#include <utility>
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "media/audio/audio_device_description.h"
+#include "media/base/audio_latency.h"
#include "media/base/audio_parameters.h"
+#include "media/base/audio_renderer_mixer_pool.h"
#include "media/base/output_device_info.h"
#include "url/origin.h"
namespace media {
-class AudioHardwareConfig;
class AudioRendererMixer;
class AudioRendererMixerInput;
class AudioRendererSink;
}
namespace content {
+class AudioRendererSinkCache;
// Manages sharing of an AudioRendererMixer among AudioRendererMixerInputs based
// on their AudioParameters configuration. Inputs with the same AudioParameters
// configuration will share a mixer while a new AudioRendererMixer will be
-// lazily created if one with the exact AudioParameters does not exist.
+// lazily created if one with the exact AudioParameters does not exist. When an
+// AudioRendererMixer is returned by AudioRendererMixerInput, it will be deleted
+// if its only other reference is held by AudioRendererMixerManager.
//
// There should only be one instance of AudioRendererMixerManager per render
// thread.
@@ -39,10 +44,12 @@ namespace content {
// with floats. However, bits per channel is currently used to interleave the
// audio data by AudioOutputDevice::AudioThreadCallback::Process for consumption
// via the shared memory. See http://crbug.com/114700.
-class CONTENT_EXPORT AudioRendererMixerManager {
+class CONTENT_EXPORT AudioRendererMixerManager
+ : public media::AudioRendererMixerPool {
public:
- AudioRendererMixerManager();
- ~AudioRendererMixerManager();
+ ~AudioRendererMixerManager() final;
+
+ static std::unique_ptr<AudioRendererMixerManager> Create();
// Creates an AudioRendererMixerInput with the proper callbacks necessary to
// retrieve an AudioRendererMixer instance from AudioRendererMixerManager.
@@ -56,23 +63,30 @@ class CONTENT_EXPORT AudioRendererMixerManager {
int source_render_frame_id,
int session_id,
const std::string& device_id,
- const url::Origin& security_origin);
-
- // Returns a mixer instance based on AudioParameters; an existing one if one
- // with the provided AudioParameters exists or a new one if not.
- media::AudioRendererMixer* GetMixer(int source_render_frame_id,
- const media::AudioParameters& params,
- const std::string& device_id,
- const url::Origin& security_origin,
- media::OutputDeviceStatus* device_status);
-
- // Remove a mixer instance given a mixer if the only other reference is held
- // by AudioRendererMixerManager. Every AudioRendererMixer owner must call
- // this method when it's done with a mixer.
- void RemoveMixer(int source_render_frame_id,
- const media::AudioParameters& params,
- const std::string& device_id,
- const url::Origin& security_origin);
+ const url::Origin& security_origin,
+ media::AudioLatency::LatencyType latency);
+
+ // AudioRendererMixerPool implementation.
+
+ media::AudioRendererMixer* GetMixer(
+ int source_render_frame_id,
+ const media::AudioParameters& input_params,
+ media::AudioLatency::LatencyType latency,
+ const std::string& device_id,
+ const url::Origin& security_origin,
+ media::OutputDeviceStatus* device_status) final;
+
+ void ReturnMixer(media::AudioRendererMixer* mixer) final;
+
+ media::OutputDeviceInfo GetOutputDeviceInfo(
+ int source_render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) final;
+
+ protected:
+ explicit AudioRendererMixerManager(
+ std::unique_ptr<AudioRendererSinkCache> sink_cache);
private:
friend class AudioRendererMixerManagerTest;
@@ -82,11 +96,13 @@ class CONTENT_EXPORT AudioRendererMixerManager {
struct MixerKey {
MixerKey(int source_render_frame_id,
const media::AudioParameters& params,
+ media::AudioLatency::LatencyType latency,
const std::string& device_id,
const url::Origin& security_origin);
MixerKey(const MixerKey& other);
int source_render_frame_id;
media::AudioParameters params;
+ media::AudioLatency::LatencyType latency;
std::string device_id;
url::Origin security_origin;
};
@@ -100,6 +116,13 @@ class CONTENT_EXPORT AudioRendererMixerManager {
if (a.params.channels() != b.params.channels())
return a.params.channels() < b.params.channels();
+ if (a.latency != b.latency)
+ return a.latency < b.latency;
+
+ // TODO(olka) add buffer duration comparison for LATENCY_EXACT_MS when
+ // adding support for it.
+ DCHECK_NE(media::AudioLatency::LATENCY_EXACT_MS, a.latency);
+
// Ignore effects(), bits_per_sample(), format(), and frames_per_buffer(),
// these parameters do not affect mixer reuse. All AudioRendererMixer
// units disable FIFO, so frames_per_buffer() can be safely ignored.
@@ -127,14 +150,24 @@ class CONTENT_EXPORT AudioRendererMixerManager {
struct AudioRendererMixerReference {
media::AudioRendererMixer* mixer;
int ref_count;
+ // Mixer sink pointer, to remove a sink from cache upon mixer destruction.
+ const media::AudioRendererSink* sink_ptr;
};
- typedef std::map<MixerKey, AudioRendererMixerReference, MixerKeyCompare>
- AudioRendererMixerMap;
+
+ using AudioRendererMixerMap =
+ std::map<MixerKey, AudioRendererMixerReference, MixerKeyCompare>;
// Active mixers.
AudioRendererMixerMap mixers_;
base::Lock mixers_lock_;
+ // Mixer sink cache.
+ const std::unique_ptr<AudioRendererSinkCache> sink_cache_;
+
+ // Map of the output latencies encountered throughout mixer manager lifetime.
+ // Used for UMA histogram logging.
+ std::bitset<media::AudioLatency::LATENCY_COUNT> latency_map_;
+
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManager);
};
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
index e3eb3b3718f..fbdb0c55076 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
@@ -6,12 +6,13 @@
#include <memory>
+#include "base/bind.h"
+#include "build/build_config.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "content/renderer/media/audio_device_factory.h"
+#include "content/renderer/media/audio_renderer_sink_cache.h"
#include "media/audio/audio_device_description.h"
-#include "media/base/audio_capturer_source.h"
#include "media/base/audio_parameters.h"
#include "media/base/audio_renderer_mixer.h"
#include "media/base/audio_renderer_mixer_input.h"
@@ -23,56 +24,109 @@
namespace content {
-static const int kBitsPerChannel = 16;
-static const int kSampleRate = 48000;
-static const int kBufferSize = 8192;
-static const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO;
-static const media::ChannelLayout kAnotherChannelLayout =
- media::CHANNEL_LAYOUT_2_1;
-static const char* const kDefaultDeviceId =
+namespace {
+const int kBitsPerChannel = 16;
+const int kSampleRate = 48000;
+const int kBufferSize = 8192;
+const int kHardwareSampleRate = 44100;
+const int kHardwareBufferSize = 128;
+const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO;
+const media::ChannelLayout kAnotherChannelLayout = media::CHANNEL_LAYOUT_2_1;
+const char* const kDefaultDeviceId =
media::AudioDeviceDescription::kDefaultDeviceId;
-static const char kAnotherDeviceId[] = "another-device-id";
-static const char kMatchedDeviceId[] = "matched-device-id";
-static const char kNonexistentDeviceId[] = "nonexistent-device-id";
+const char kAnotherDeviceId[] = "another-device-id";
+const char kMatchedDeviceId[] = "matched-device-id";
+const char kNonexistentDeviceId[] = "nonexistent-device-id";
-static const int kRenderFrameId = 124;
-static const int kAnotherRenderFrameId = 678;
+const int kRenderFrameId = 124;
+const int kAnotherRenderFrameId = 678;
+} // namespace;
using media::AudioParameters;
+using media::AudioLatency;
-class AudioRendererMixerManagerTest : public testing::Test,
- public AudioDeviceFactory {
+class FakeAudioRendererSinkCache : public AudioRendererSinkCache {
+ public:
+ using GetSinkCallback =
+ base::Callback<scoped_refptr<media::AudioRendererSink>(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin)>;
+
+ using ReleaseSinkCallback =
+ base::Callback<void(const media::AudioRendererSink*)>;
+
+ FakeAudioRendererSinkCache(const GetSinkCallback& get_sink_cb,
+ const ReleaseSinkCallback& release_sink_cb)
+ : get_sink_cb_(get_sink_cb), release_sink_cb_(release_sink_cb) {}
+
+ media::OutputDeviceInfo GetSinkInfo(
+ int source_render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) final {
+ return get_sink_cb_
+ .Run(source_render_frame_id, session_id, device_id, security_origin)
+ ->GetOutputDeviceInfo();
+ }
+
+ scoped_refptr<media::AudioRendererSink> GetSink(
+ int source_render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) final {
+ return get_sink_cb_.Run(source_render_frame_id, 0, device_id,
+ security_origin);
+ }
+
+ void ReleaseSink(const media::AudioRendererSink* sink) final {
+ release_sink_cb_.Run(sink);
+ }
+
+ private:
+ GetSinkCallback get_sink_cb_;
+ ReleaseSinkCallback release_sink_cb_;
+};
+
+class AudioRendererMixerManagerTest : public testing::Test {
public:
AudioRendererMixerManagerTest()
- : manager_(new AudioRendererMixerManager()),
- mock_sink_(new media::MockAudioRendererSink()),
+ : manager_(new AudioRendererMixerManager(
+ std::unique_ptr<AudioRendererSinkCache>(
+ new FakeAudioRendererSinkCache(
+ base::Bind(&AudioRendererMixerManagerTest::GetSinkPtr,
+ base::Unretained(this)),
+ base::Bind(&AudioRendererMixerManagerTest::ReleaseSinkPtr,
+ base::Unretained(this)))))),
+ mock_sink_(new media::MockAudioRendererSink(
+ kDefaultDeviceId,
+ media::OUTPUT_DEVICE_STATUS_OK,
+ AudioParameters(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout,
+ kHardwareSampleRate,
+ kBitsPerChannel,
+ kHardwareBufferSize))),
mock_sink_no_device_(new media::MockAudioRendererSink(
kNonexistentDeviceId,
media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND)),
mock_sink_matched_device_(
new media::MockAudioRendererSink(kMatchedDeviceId,
media::OUTPUT_DEVICE_STATUS_OK)),
- mock_sink_for_session_id_(
- new media::MockAudioRendererSink(kMatchedDeviceId,
- media::OUTPUT_DEVICE_STATUS_OK)),
kSecurityOrigin2(GURL("http://localhost")) {}
media::AudioRendererMixer* GetMixer(
int source_render_frame_id,
const media::AudioParameters& params,
+ AudioLatency::LatencyType latency,
const std::string& device_id,
const url::Origin& security_origin,
media::OutputDeviceStatus* device_status) {
- return manager_->GetMixer(source_render_frame_id, params, device_id,
- security_origin, device_status);
+ return manager_->GetMixer(source_render_frame_id, params, latency,
+ device_id, security_origin, device_status);
}
- void RemoveMixer(int source_render_frame_id,
- const media::AudioParameters& params,
- const std::string& device_id,
- const url::Origin& security_origin) {
- return manager_->RemoveMixer(source_render_frame_id, params, device_id,
- security_origin);
+ void ReturnMixer(media::AudioRendererMixer* mixer) {
+ return manager_->ReturnMixer(mixer);
}
// Number of instantiated mixers.
@@ -81,24 +135,8 @@ class AudioRendererMixerManagerTest : public testing::Test,
}
protected:
- MOCK_METHOD1(CreateAudioCapturerSource,
- scoped_refptr<media::AudioCapturerSource>(int));
- MOCK_METHOD5(
- CreateSwitchableAudioRendererSink,
- scoped_refptr<media::SwitchableAudioRendererSink>(SourceType,
- int,
- int,
- const std::string&,
- const url::Origin&));
- MOCK_METHOD5(CreateAudioRendererSink,
- scoped_refptr<media::AudioRendererSink>(SourceType,
- int,
- int,
- const std::string&,
- const url::Origin&));
-
- scoped_refptr<media::AudioRendererSink> CreateFinalAudioRendererSink(
- int render_frame_id,
+ scoped_refptr<media::AudioRendererSink> GetSinkPtr(
+ int source_render_frame_id,
int session_id,
const std::string& device_id,
const url::Origin& security_origin) {
@@ -110,7 +148,7 @@ class AudioRendererMixerManagerTest : public testing::Test,
return mock_sink_no_device_;
if (device_id.empty()) {
// The sink used to get device ID from session ID if it's not empty
- return session_id ? mock_sink_for_session_id_ : mock_sink_;
+ return session_id ? mock_sink_matched_device_ : mock_sink_;
}
if (device_id == kMatchedDeviceId)
return mock_sink_matched_device_;
@@ -119,11 +157,13 @@ class AudioRendererMixerManagerTest : public testing::Test,
return nullptr;
}
+ MOCK_METHOD1(ReleaseSinkPtr, void(const media::AudioRendererSink*));
+
std::unique_ptr<AudioRendererMixerManager> manager_;
+
scoped_refptr<media::MockAudioRendererSink> mock_sink_;
scoped_refptr<media::MockAudioRendererSink> mock_sink_no_device_;
scoped_refptr<media::MockAudioRendererSink> mock_sink_matched_device_;
- scoped_refptr<media::MockAudioRendererSink> mock_sink_for_session_id_;
// To avoid global/static non-POD constants.
const url::Origin kSecurityOrigin;
@@ -133,50 +173,56 @@ class AudioRendererMixerManagerTest : public testing::Test,
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest);
};
-// Verify GetMixer() and RemoveMixer() both work as expected; particularly with
+// Verify GetMixer() and ReturnMixer() both work as expected; particularly with
// respect to the explicit ref counting done.
-TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) {
+TEST_F(AudioRendererMixerManagerTest, GetReturnMixer) {
// Since we're testing two different sets of parameters, we expect
// AudioRendererMixerManager to call Start and Stop on our mock twice.
EXPECT_CALL(*mock_sink_.get(), Start()).Times(2);
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2);
+ // We expect 2 mixers to be created; each of them should release the sink.
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2);
+
// There should be no mixers outstanding to start with.
EXPECT_EQ(0, mixer_count());
- media::AudioParameters params1(
- AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
- kBitsPerChannel, kBufferSize);
+ media::AudioParameters params1(media::AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout, kSampleRate, kBitsPerChannel,
+ kBufferSize);
- media::AudioRendererMixer* mixer1 = GetMixer(
- kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer1 =
+ GetMixer(kRenderFrameId, params1, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer1);
EXPECT_EQ(1, mixer_count());
// The same parameters should return the same mixer1.
- EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params1, kDefaultDeviceId,
- kSecurityOrigin, nullptr));
+ EXPECT_EQ(mixer1,
+ GetMixer(kRenderFrameId, params1, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr));
EXPECT_EQ(1, mixer_count());
- // Remove the extra mixer we just acquired.
- RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin);
+ // Return the extra mixer we just acquired.
+ ReturnMixer(mixer1);
EXPECT_EQ(1, mixer_count());
media::AudioParameters params2(
AudioParameters::AUDIO_PCM_LINEAR, kAnotherChannelLayout, kSampleRate * 2,
kBitsPerChannel, kBufferSize * 2);
- media::AudioRendererMixer* mixer2 = GetMixer(
- kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer2 =
+ GetMixer(kRenderFrameId, params2, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer2);
EXPECT_EQ(2, mixer_count());
// Different parameters should result in a different mixer1.
EXPECT_NE(mixer1, mixer2);
- // Remove both outstanding mixers.
- RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin);
+ // Return both outstanding mixers.
+ ReturnMixer(mixer1);
EXPECT_EQ(1, mixer_count());
- RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin);
+ ReturnMixer(mixer2);
EXPECT_EQ(0, mixer_count());
}
@@ -187,13 +233,17 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2);
EXPECT_EQ(mixer_count(), 0);
+ // We expect 2 mixers to be created; each of them should release the sink.
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2);
+
media::AudioParameters params1(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout,
kSampleRate,
kBitsPerChannel,
kBufferSize);
- media::AudioRendererMixer* mixer1 = GetMixer(
- kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer1 =
+ GetMixer(kRenderFrameId, params1, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer1);
EXPECT_EQ(1, mixer_count());
@@ -204,10 +254,12 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
kSampleRate * 2,
kBitsPerChannel * 2,
kBufferSize * 2);
- EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params2, kDefaultDeviceId,
- kSecurityOrigin, nullptr));
+ media::AudioRendererMixer* mixer2 =
+ GetMixer(kRenderFrameId, params2, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+ EXPECT_EQ(mixer1, mixer2);
EXPECT_EQ(1, mixer_count());
- RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin);
+ ReturnMixer(mixer2);
EXPECT_EQ(1, mixer_count());
// Modify some parameters that do matter: channel layout
@@ -217,28 +269,32 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
kBitsPerChannel,
kBufferSize);
ASSERT_NE(params3.channel_layout(), params1.channel_layout());
-
- EXPECT_NE(mixer1, GetMixer(kRenderFrameId, params3, kDefaultDeviceId,
- kSecurityOrigin, nullptr));
+ media::AudioRendererMixer* mixer3 =
+ GetMixer(kRenderFrameId, params3, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+ EXPECT_NE(mixer1, mixer3);
EXPECT_EQ(2, mixer_count());
- RemoveMixer(kRenderFrameId, params3, kDefaultDeviceId, kSecurityOrigin);
+ ReturnMixer(mixer3);
EXPECT_EQ(1, mixer_count());
- // Remove final mixer.
- RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin);
+ // Return final mixer.
+ ReturnMixer(mixer1);
EXPECT_EQ(0, mixer_count());
}
// Verify CreateInput() provides AudioRendererMixerInput with the appropriate
// callbacks and they are working as expected. Also, verify that separate
-// mixers are created for separate render views, even though the AudioParameters
-// are the same.
+// mixers are created for separate RenderFrames, even though the
+// AudioParameters are the same.
TEST_F(AudioRendererMixerManagerTest, CreateInput) {
// Expect AudioRendererMixerManager to call Start and Stop on our mock twice
// each. Note: Under normal conditions, each mixer would get its own sink!
EXPECT_CALL(*mock_sink_.get(), Start()).Times(2);
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2);
+ // We expect 2 mixers to be created; each of them should release the sink.
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2);
+
media::AudioParameters params(
AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
kBitsPerChannel, kBufferSize);
@@ -246,19 +302,20 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) {
// Create two mixer inputs and ensure this doesn't instantiate any mixers yet.
EXPECT_EQ(0, mixer_count());
media::FakeAudioRenderCallback callback(0);
- scoped_refptr<media::AudioRendererMixerInput> input(manager_->CreateInput(
- kRenderFrameId, 0, kDefaultDeviceId, kSecurityOrigin));
+ scoped_refptr<media::AudioRendererMixerInput> input(
+ manager_->CreateInput(kRenderFrameId, 0, kDefaultDeviceId,
+ kSecurityOrigin, AudioLatency::LATENCY_PLAYBACK));
input->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
media::FakeAudioRenderCallback another_callback(1);
scoped_refptr<media::AudioRendererMixerInput> another_input(
manager_->CreateInput(kAnotherRenderFrameId, 0, kDefaultDeviceId,
- kSecurityOrigin));
+ kSecurityOrigin, AudioLatency::LATENCY_PLAYBACK));
another_input->Initialize(params, &another_callback);
EXPECT_EQ(0, mixer_count());
// Implicitly test that AudioRendererMixerInput was provided with the expected
- // callbacks needed to acquire an AudioRendererMixer and remove it.
+ // callbacks needed to acquire an AudioRendererMixer and return it.
input->Start();
EXPECT_EQ(1, mixer_count());
another_input->Start();
@@ -287,6 +344,10 @@ TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) {
EXPECT_CALL(*mock_sink_matched_device_.get(), Start()).Times(1);
EXPECT_CALL(*mock_sink_matched_device_.get(), Stop()).Times(1);
+ // We expect 3 mixers to be created; each of them should release a sink.
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2);
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_matched_device_.get())).Times(1);
+
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBitsPerChannel,
kBufferSize);
@@ -296,34 +357,37 @@ TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) {
// Empty device id, zero session id;
scoped_refptr<media::AudioRendererMixerInput> input_to_default_device(
manager_->CreateInput(kRenderFrameId, 0, // session_id
- std::string(), kSecurityOrigin));
+ std::string(), kSecurityOrigin,
+ AudioLatency::LATENCY_PLAYBACK));
input_to_default_device->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
// Specific device id, zero session id;
scoped_refptr<media::AudioRendererMixerInput> input_to_matched_device(
manager_->CreateInput(kRenderFrameId, 0, // session_id
- kMatchedDeviceId, kSecurityOrigin));
+ kMatchedDeviceId, kSecurityOrigin,
+ AudioLatency::LATENCY_PLAYBACK));
input_to_matched_device->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
// Specific device id, non-zero session id (to be ignored);
scoped_refptr<media::AudioRendererMixerInput> input_to_another_device(
manager_->CreateInput(kRenderFrameId, 1, // session id
- kAnotherDeviceId, kSecurityOrigin));
+ kAnotherDeviceId, kSecurityOrigin,
+ AudioLatency::LATENCY_PLAYBACK));
input_to_another_device->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
// Empty device id, non-zero session id;
scoped_refptr<media::AudioRendererMixerInput>
- input_to_matched_device_with_session_id(
- manager_->CreateInput(kRenderFrameId, 2, // session id
- std::string(), kSecurityOrigin));
+ input_to_matched_device_with_session_id(manager_->CreateInput(
+ kRenderFrameId, 2, // session id
+ std::string(), kSecurityOrigin, AudioLatency::LATENCY_PLAYBACK));
input_to_matched_device_with_session_id->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
// Implicitly test that AudioRendererMixerInput was provided with the expected
- // callbacks needed to acquire an AudioRendererMixer and remove it.
+ // callbacks needed to acquire an AudioRendererMixer and return it.
input_to_default_device->Start();
EXPECT_EQ(1, mixer_count());
@@ -359,32 +423,38 @@ TEST_F(AudioRendererMixerManagerTest, MixerDevices) {
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(3);
EXPECT_EQ(0, mixer_count());
+ // We expect 3 mixers to be created; each of them should release a sink.
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(3);
+
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBitsPerChannel,
kBufferSize);
- media::AudioRendererMixer* mixer1 = GetMixer(
- kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer1 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer1);
EXPECT_EQ(1, mixer_count());
- media::AudioRendererMixer* mixer2 = GetMixer(
- kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer2 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kAnotherDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer2);
EXPECT_EQ(2, mixer_count());
EXPECT_NE(mixer1, mixer2);
- media::AudioRendererMixer* mixer3 = GetMixer(
- kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2, nullptr);
+ media::AudioRendererMixer* mixer3 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kAnotherDeviceId, kSecurityOrigin2, nullptr);
ASSERT_TRUE(mixer3);
EXPECT_EQ(3, mixer_count());
EXPECT_NE(mixer1, mixer3);
EXPECT_NE(mixer2, mixer3);
- RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin);
+ ReturnMixer(mixer1);
EXPECT_EQ(2, mixer_count());
- RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin);
+ ReturnMixer(mixer2);
EXPECT_EQ(1, mixer_count());
- RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2);
+ ReturnMixer(mixer3);
EXPECT_EQ(0, mixer_count());
}
@@ -395,39 +465,46 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) {
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
EXPECT_EQ(0, mixer_count());
+ // We expect 1 mixer to be created; it should release its sink.
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
+
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBitsPerChannel,
kBufferSize);
- media::AudioRendererMixer* mixer1 = GetMixer(
- kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer1 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer1);
EXPECT_EQ(1, mixer_count());
media::AudioRendererMixer* mixer2 =
- GetMixer(kRenderFrameId, params, std::string(), kSecurityOrigin, nullptr);
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ std::string(), kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer2);
EXPECT_EQ(1, mixer_count());
EXPECT_EQ(mixer1, mixer2);
- media::AudioRendererMixer* mixer3 = GetMixer(
- kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2, nullptr);
+ media::AudioRendererMixer* mixer3 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin2, nullptr);
ASSERT_TRUE(mixer3);
EXPECT_EQ(1, mixer_count());
EXPECT_EQ(mixer1, mixer3);
- media::AudioRendererMixer* mixer4 = GetMixer(
- kRenderFrameId, params, std::string(), kSecurityOrigin2, nullptr);
+ media::AudioRendererMixer* mixer4 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ std::string(), kSecurityOrigin2, nullptr);
ASSERT_TRUE(mixer4);
EXPECT_EQ(1, mixer_count());
EXPECT_EQ(mixer1, mixer4);
- RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin);
+ ReturnMixer(mixer1);
EXPECT_EQ(1, mixer_count());
- RemoveMixer(kRenderFrameId, params, std::string(), kSecurityOrigin);
+ ReturnMixer(mixer2);
EXPECT_EQ(1, mixer_count());
- RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin2);
+ ReturnMixer(mixer3);
EXPECT_EQ(1, mixer_count());
- RemoveMixer(kRenderFrameId, params, std::string(), kSecurityOrigin2);
+ ReturnMixer(mixer4);
EXPECT_EQ(0, mixer_count());
}
@@ -435,17 +512,320 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) {
// status code when a nonexistent device is requested.
TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) {
EXPECT_EQ(0, mixer_count());
+
+ // Mixer manager should release a not-ok sink when failing to create a mixer.
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_no_device_.get())).Times(1);
+
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBitsPerChannel,
kBufferSize);
media::OutputDeviceStatus device_status = media::OUTPUT_DEVICE_STATUS_OK;
- EXPECT_CALL(*mock_sink_no_device_.get(), Stop());
+
media::AudioRendererMixer* mixer =
- GetMixer(kRenderFrameId, params, kNonexistentDeviceId, kSecurityOrigin,
- &device_status);
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kNonexistentDeviceId, kSecurityOrigin, &device_status);
+
EXPECT_FALSE(mixer);
EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, device_status);
EXPECT_EQ(0, mixer_count());
}
+// Verify GetMixer() correctly deduplicate mixers basing on latency
+// requirements.
+TEST_F(AudioRendererMixerManagerTest, LatencyMixing) {
+ EXPECT_CALL(*mock_sink_.get(), Start()).Times(3);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(3);
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(3);
+
+ EXPECT_EQ(0, mixer_count());
+
+ media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout, kSampleRate, kBitsPerChannel,
+ kBufferSize);
+ media::AudioRendererMixer* mixer1 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+ ASSERT_TRUE(mixer1);
+ EXPECT_EQ(1, mixer_count());
+
+ media::AudioRendererMixer* mixer2 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+ ASSERT_TRUE(mixer2);
+ EXPECT_EQ(mixer1, mixer2); // Same latency => same mixer.
+ EXPECT_EQ(1, mixer_count());
+
+ media::AudioRendererMixer* mixer3 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+ ASSERT_TRUE(mixer3);
+ EXPECT_NE(mixer1, mixer3);
+ EXPECT_EQ(2, mixer_count()); // Another latency => another mixer.
+
+ media::AudioRendererMixer* mixer4 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+ EXPECT_EQ(mixer3, mixer4);
+ EXPECT_EQ(2, mixer_count()); // Same latency => same mixer.
+
+ media::AudioRendererMixer* mixer5 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_INTERACTIVE,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+ ASSERT_TRUE(mixer5);
+ EXPECT_EQ(3, mixer_count()); // Another latency => another mixer.
+
+ media::AudioRendererMixer* mixer6 =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_INTERACTIVE,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+ EXPECT_EQ(mixer5, mixer6);
+ EXPECT_EQ(3, mixer_count()); // Same latency => same mixer.
+
+ ReturnMixer(mixer1);
+ EXPECT_EQ(3, mixer_count());
+ ReturnMixer(mixer2);
+ EXPECT_EQ(2, mixer_count());
+ ReturnMixer(mixer3);
+ EXPECT_EQ(2, mixer_count());
+ ReturnMixer(mixer4);
+ EXPECT_EQ(1, mixer_count());
+ ReturnMixer(mixer5);
+ EXPECT_EQ(1, mixer_count());
+ ReturnMixer(mixer6);
+ EXPECT_EQ(0, mixer_count());
+}
+
+// Verify output bufer size of the mixer is correctly adjusted for Playback
+// latency.
+TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyPlayback) {
+ // Expecting hardware buffer size of 128 frames
+ EXPECT_EQ(44100,
+ mock_sink_->GetOutputDeviceInfo().output_params().sample_rate());
+ // Expecting hardware buffer size of 128 frames
+ EXPECT_EQ(
+ 128,
+ mock_sink_->GetOutputDeviceInfo().output_params().frames_per_buffer());
+
+ EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
+
+ media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout, 32000, kBitsPerChannel, 512);
+
+ media::AudioRendererMixer* mixer =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+
+#if defined(OS_CHROMEOS)
+ // Expecting input sample rate
+ EXPECT_EQ(32000, mixer->GetOutputParamsForTesting().sample_rate());
+ // Round up 20 ms (640) to the power of 2.
+ EXPECT_EQ(1024, mixer->GetOutputParamsForTesting().frames_per_buffer());
+
+#else
+ // Expecting hardware sample rate
+ EXPECT_EQ(44100, mixer->GetOutputParamsForTesting().sample_rate());
+
+// 20 ms at 44100 is 882 frames per buffer.
+#if defined(OS_WIN)
+ // Round up 882 to the nearest multiple of the output buffer size (128). which
+ // is 7 * 128 = 896
+ EXPECT_EQ(896, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#else
+ // Round up 882 to the power of 2.
+ EXPECT_EQ(1024, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#endif // defined(OS_WIN)
+
+#endif // defined(OS_CHROMEOS)
+
+ ReturnMixer(mixer);
+}
+
+// Verify output bufer size of the mixer is correctly adjusted for Playback
+// latency when the device buffer size exceeds 20 ms.
+TEST_F(AudioRendererMixerManagerTest,
+ MixerParamsLatencyPlaybackLargeDeviceBufferSize) {
+ mock_sink_ = new media::MockAudioRendererSink(
+ std::string(), media::OUTPUT_DEVICE_STATUS_OK,
+ AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 44100,
+ kBitsPerChannel, 2048));
+
+ EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
+
+ media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout, 32000, kBitsPerChannel, 512);
+
+ media::AudioRendererMixer* mixer =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+
+// 20 ms at 44100 is 882 frames per buffer.
+#if defined(OS_CHROMEOS)
+ // Expecting input sample rate
+ EXPECT_EQ(32000, mixer->GetOutputParamsForTesting().sample_rate());
+ // Ignore device buffer size, round up 20 ms (640) to the power of 2.
+ EXPECT_EQ(1024, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#else
+ // Expecting hardware sample rate
+ EXPECT_EQ(44100, mixer->GetOutputParamsForTesting().sample_rate());
+ // Prefer device buffer size (2048) if is larger than 20 ms buffer size (882).
+ EXPECT_EQ(2048, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#endif
+
+ ReturnMixer(mixer);
+}
+
+// Verify output bufer size of the mixer is correctly adjusted for Playback
+// latency when output audio is fake.
+TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyPlaybackFakeAudio) {
+ mock_sink_ = new media::MockAudioRendererSink(
+ std::string(), media::OUTPUT_DEVICE_STATUS_OK,
+ AudioParameters(AudioParameters::AUDIO_FAKE, kChannelLayout, 44100,
+ kBitsPerChannel, 2048));
+
+ EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
+
+ media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout, 32000, kBitsPerChannel, 512);
+
+ media::AudioRendererMixer* mixer =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+
+ // Expecting input sample rate
+ EXPECT_EQ(32000, mixer->GetOutputParamsForTesting().sample_rate());
+
+// 20 ms at 32000 is 640 frames per buffer.
+#if defined(OS_WIN)
+ // Use 20 ms buffer.
+ EXPECT_EQ(640, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#else
+ // Ignore device buffer size, round up 640 to the power of 2.
+ EXPECT_EQ(1024, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#endif // defined(OS_WIN)
+
+ ReturnMixer(mixer);
+}
+
+// Verify output bufer size of the mixer is correctly adjusted for RTC latency.
+TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyRtc) {
+ // Expecting hardware buffer size of 128 frames
+ EXPECT_EQ(44100,
+ mock_sink_->GetOutputDeviceInfo().output_params().sample_rate());
+ // Expecting hardware buffer size of 128 frames
+ EXPECT_EQ(
+ 128,
+ mock_sink_->GetOutputDeviceInfo().output_params().frames_per_buffer());
+
+ EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
+
+ media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout, 32000, kBitsPerChannel, 512);
+
+ media::AudioRendererMixer* mixer =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+
+#if defined(OS_CHROMEOS)
+ int output_sample_rate = 32000;
+#else
+ // Expecting hardware sample rate.
+ int output_sample_rate = 44100;
+#endif // defined(OS_CHROMEOS)
+
+ EXPECT_EQ(output_sample_rate,
+ mixer->GetOutputParamsForTesting().sample_rate());
+
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+ // Use 10 ms buffer (441 frames per buffer).
+ EXPECT_EQ(output_sample_rate / 100,
+ mixer->GetOutputParamsForTesting().frames_per_buffer());
+#elif defined(OS_ANDROID)
+ // If hardware buffer size (128) is less than 20 ms (882), use 20 ms buffer
+ // (otherwise, use hardware buffer).
+ EXPECT_EQ(882, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#else
+ // Use hardware buffer size (128).
+ EXPECT_EQ(128, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#endif // defined(OS_LINUX) || defined(OS_MACOSX)
+
+ ReturnMixer(mixer);
+}
+
+// Verify output bufer size of the mixer is correctly adjusted for RTC latency
+// when output audio is fake.
+TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyRtcFakeAudio) {
+ mock_sink_ = new media::MockAudioRendererSink(
+ std::string(), media::OUTPUT_DEVICE_STATUS_OK,
+ AudioParameters(AudioParameters::AUDIO_FAKE, kChannelLayout, 44100,
+ kBitsPerChannel, 128));
+
+ EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
+
+ media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout, 32000, kBitsPerChannel, 512);
+
+ media::AudioRendererMixer* mixer =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+
+ // Expecting input sample rate.
+ EXPECT_EQ(32000, mixer->GetOutputParamsForTesting().sample_rate());
+
+ // 10 ms at 32000 is 320 frames per buffer. Expect it on all the platforms for
+ // fake audio output.
+ EXPECT_EQ(320, mixer->GetOutputParamsForTesting().frames_per_buffer());
+
+ ReturnMixer(mixer);
+}
+
+// Verify output bufer size of the mixer is correctly adjusted for Interactive
+// latency.
+TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyInteractive) {
+ // Expecting hardware buffer size of 128 frames
+ EXPECT_EQ(44100,
+ mock_sink_->GetOutputDeviceInfo().output_params().sample_rate());
+ // Expecting hardware buffer size of 128 frames
+ EXPECT_EQ(
+ 128,
+ mock_sink_->GetOutputDeviceInfo().output_params().frames_per_buffer());
+
+ EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
+
+ media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout, 32000, kBitsPerChannel, 512);
+
+ media::AudioRendererMixer* mixer =
+ GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_INTERACTIVE,
+ kDefaultDeviceId, kSecurityOrigin, nullptr);
+
+#if defined(OS_CHROMEOS)
+ // Expecting input sample rate.
+ EXPECT_EQ(32000, mixer->GetOutputParamsForTesting().sample_rate());
+#else
+ // Expecting hardware sample rate.
+ EXPECT_EQ(44100, mixer->GetOutputParamsForTesting().sample_rate());
+#endif // defined(OS_CHROMEOS)
+
+#if defined(OS_ANDROID)
+ // If hardware buffer size (128) is less than 1024, use 2048.
+ EXPECT_EQ(2048, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#else
+ // Expect hardware buffer size.
+ EXPECT_EQ(128, mixer->GetOutputParamsForTesting().frames_per_buffer());
+#endif
+
+ ReturnMixer(mixer);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache.h b/chromium/content/renderer/media/audio_renderer_sink_cache.h
new file mode 100644
index 00000000000..25ab762e8b2
--- /dev/null
+++ b/chromium/content/renderer/media/audio_renderer_sink_cache.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_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_H_
+#define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+#include "media/base/output_device_info.h"
+
+namespace url {
+class Origin;
+}
+
+namespace media {
+class AudioRendererSink;
+}
+
+namespace content {
+
+// Caches AudioRendererSink instances, provides them to the clients for usage,
+// tracks their used/unused state, reuses them to obtain output device
+// information, garbage-collects unused sinks.
+// Thread safe.
+class CONTENT_EXPORT AudioRendererSinkCache {
+ public:
+ virtual ~AudioRendererSinkCache() {}
+
+ // Creates default cache, to be used by AudioRendererMixerManager.
+ static std::unique_ptr<AudioRendererSinkCache> Create();
+
+ // Returns output device information for a specified sink.
+ virtual media::OutputDeviceInfo GetSinkInfo(
+ int source_render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) = 0;
+
+ // Provides a sink for usage. The sink must be returned to the cache by
+ // calling ReleaseSink(). The sink must be stopped by the user before
+ // deletion, but after releasing it from the cache.
+ virtual scoped_refptr<media::AudioRendererSink> GetSink(
+ int source_render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) = 0;
+
+ // Notifies the cache that the sink is not in use any more. Must be
+ // called by the client, so that the cache can garbage-collect the sink
+ // reference.
+ virtual void ReleaseSink(const media::AudioRendererSink* sink_ptr) = 0;
+
+ protected:
+ AudioRendererSinkCache() {}
+
+ DISALLOW_COPY_AND_ASSIGN(AudioRendererSinkCache);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_H_
diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc b/chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc
new file mode 100644
index 00000000000..9fef7d0937b
--- /dev/null
+++ b/chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc
@@ -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.
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/memory/ptr_util.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "content/renderer/media/audio_device_factory.h"
+#include "content/renderer/media/audio_renderer_sink_cache_impl.h"
+#include "media/audio/audio_device_description.h"
+#include "media/base/audio_renderer_sink.h"
+#include "url/origin.h"
+
+namespace content {
+
+constexpr int kDeleteTimeoutMs = 5000;
+
+// Cached sink data.
+struct AudioRendererSinkCacheImpl::CacheEntry {
+ int source_render_frame_id;
+ std::string device_id;
+ url::Origin security_origin;
+ scoped_refptr<media::AudioRendererSink> sink; // Sink instance
+ bool used; // True if in use by a client.
+};
+
+// static
+std::unique_ptr<AudioRendererSinkCache> AudioRendererSinkCache::Create() {
+ return base::WrapUnique(new AudioRendererSinkCacheImpl(
+ base::ThreadTaskRunnerHandle::Get(),
+ base::Bind(&AudioDeviceFactory::NewAudioRendererMixerSink),
+ base::TimeDelta::FromMilliseconds(kDeleteTimeoutMs)));
+}
+
+AudioRendererSinkCacheImpl::AudioRendererSinkCacheImpl(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const CreateSinkCallback& create_sink_cb,
+ base::TimeDelta delete_timeout)
+ : task_runner_(std::move(task_runner)),
+ create_sink_cb_(create_sink_cb),
+ delete_timeout_(delete_timeout),
+ weak_ptr_factory_(this) {
+ weak_this_ = weak_ptr_factory_.GetWeakPtr();
+}
+
+AudioRendererSinkCacheImpl::~AudioRendererSinkCacheImpl() {
+ // We just release all the cached sinks here.
+}
+
+media::OutputDeviceInfo AudioRendererSinkCacheImpl::GetSinkInfo(
+ int source_render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ CacheEntry cache_entry = {source_render_frame_id,
+ std::string() /* device_id */, security_origin,
+ nullptr /* sink */, false /* not used */};
+
+ if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
+ device_id)) {
+ // We are provided with session id instead of device id. Session id is
+ // unique, so we can't find any matching sink. Creating a new one.
+ cache_entry.sink = create_sink_cb_.Run(source_render_frame_id, session_id,
+ device_id, security_origin);
+ cache_entry.device_id = cache_entry.sink->GetOutputDeviceInfo().device_id();
+
+ DVLOG(1) << "GetSinkInfo: address: " << cache_entry.sink.get()
+ << " - used session to create new sink.";
+
+ // Cache a newly-created sink.
+ base::AutoLock auto_lock(cache_lock_);
+ cache_.push_back(cache_entry);
+
+ } else {
+ // Ignore session id.
+ base::AutoLock auto_lock(cache_lock_);
+
+ auto cache_iter =
+ FindCacheEntry_Locked(source_render_frame_id, device_id,
+ security_origin, false /* unused_only */);
+
+ if (cache_iter != cache_.end()) {
+ // A matching cached sink is found.
+ DVLOG(1) << "GetSinkInfo: address: " << cache_iter->sink.get()
+ << " - reused a cached sink.";
+
+ return cache_iter->sink->GetOutputDeviceInfo();
+ }
+
+ // No matching sink found, create a new one.
+ cache_entry.device_id = device_id;
+ cache_entry.sink = create_sink_cb_.Run(
+ source_render_frame_id, 0 /* session_id */, device_id, security_origin);
+
+ DVLOG(1) << "GetSinkInfo: address: " << cache_entry.sink.get()
+ << " - no matching cached sink found, created a new one.";
+
+ // Cache a newly-created sink.
+ cache_.push_back(cache_entry);
+ }
+
+ // Schedule it for deletion.
+ DeleteLaterIfUnused(cache_entry.sink.get());
+
+ DVLOG(1) << "GetSinkInfo: address: " << cache_entry.sink.get()
+ << " created. source_render_frame_id: " << source_render_frame_id
+ << " session_id: " << session_id << " device_id: " << device_id
+ << " security_origin: " << security_origin;
+
+ return cache_entry.sink->GetOutputDeviceInfo();
+}
+
+scoped_refptr<media::AudioRendererSink> AudioRendererSinkCacheImpl::GetSink(
+ int source_render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ base::AutoLock auto_lock(cache_lock_);
+
+ auto cache_iter =
+ FindCacheEntry_Locked(source_render_frame_id, device_id, security_origin,
+ true /* unused_only */);
+
+ if (cache_iter != cache_.end()) {
+ // Found unused sink; mark it as used and return.
+ DVLOG(1) << "GetSink: address: " << cache_iter->sink.get()
+ << " - found unused cached sink, reusing it.";
+
+ cache_iter->used = true;
+ return cache_iter->sink;
+ }
+
+ // No unused sink is found, create one, mark it used, cache it and return.
+ CacheEntry cache_entry = {
+ source_render_frame_id, device_id, security_origin,
+ create_sink_cb_.Run(source_render_frame_id, 0 /* session_id */, device_id,
+ security_origin),
+ true /* used */};
+
+ cache_.push_back(cache_entry);
+
+ DVLOG(1) << "GetSink: address: " << cache_entry.sink.get()
+ << " - no unused cached sink found, created a new one."
+ << " source_render_frame_id: " << source_render_frame_id
+ << " device_id: " << device_id
+ << " security_origin: " << security_origin;
+ return cache_entry.sink;
+}
+
+void AudioRendererSinkCacheImpl::ReleaseSink(
+ const media::AudioRendererSink* sink_ptr) {
+ // We don't know the sink state, so won't reuse it. Delete it immediately.
+ DeleteSink(sink_ptr, true);
+}
+
+void AudioRendererSinkCacheImpl::DeleteLaterIfUnused(
+ const media::AudioRendererSink* sink_ptr) {
+ task_runner_->PostDelayedTask(
+ FROM_HERE, base::Bind(&AudioRendererSinkCacheImpl::DeleteSink, weak_this_,
+ sink_ptr, false /*do not delete if used*/),
+ delete_timeout_);
+}
+
+void AudioRendererSinkCacheImpl::DeleteSink(
+ const media::AudioRendererSink* sink_ptr,
+ bool force_delete_used) {
+ DCHECK(sink_ptr);
+
+ scoped_refptr<media::AudioRendererSink> sink_to_stop;
+
+ {
+ base::AutoLock auto_lock(cache_lock_);
+
+ // Looking up the sink by its pointer.
+ auto cache_iter = std::find_if(cache_.begin(), cache_.end(),
+ [sink_ptr](const CacheEntry& val) {
+ return val.sink.get() == sink_ptr;
+ });
+
+ if (cache_iter == cache_.end()) {
+ // If |force_delete_used| is not set it means the sink scheduled for
+ // deletion got aquired and released before scheduled deletion - it's ok.
+ DCHECK(!force_delete_used)
+ << "DeleteSink: address: " << sink_ptr
+ << " could not find a sink which is supposed to be in use";
+
+ DVLOG(1) << "DeleteSink: address: " << sink_ptr
+ << " force_delete_used = false - already deleted.";
+ return;
+ }
+
+ // When |force_delete_used| is set, it's expected that we are deleting a
+ // used sink.
+ DCHECK((!force_delete_used) || (force_delete_used && cache_iter->used))
+ << "Attempt to delete a non-aquired sink.";
+
+ if (!force_delete_used && cache_iter->used) {
+ DVLOG(1) << "DeleteSink: address: " << sink_ptr
+ << " sink in use, skipping deletion.";
+ return;
+ }
+
+ // To stop the sink before deletion if it's not used, we need to hold
+ // a ref to it.
+ if (!cache_iter->used)
+ sink_to_stop = cache_iter->sink;
+
+ cache_.erase(cache_iter);
+ DVLOG(1) << "DeleteSink: address: " << sink_ptr;
+ } // Lock scope;
+
+ // Stop the sink out of the lock scope.
+ if (sink_to_stop.get()) {
+ DCHECK_EQ(sink_ptr, sink_to_stop.get());
+ sink_to_stop->Stop();
+ DVLOG(1) << "DeleteSink: address: " << sink_ptr << " stopped.";
+ }
+}
+
+AudioRendererSinkCacheImpl::CacheContainer::iterator
+AudioRendererSinkCacheImpl::FindCacheEntry_Locked(
+ int source_render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin,
+ bool unused_only) {
+ return std::find_if(
+ cache_.begin(), cache_.end(),
+ [source_render_frame_id, &device_id, &security_origin,
+ unused_only](const CacheEntry& val) {
+ if (val.used && unused_only)
+ return false;
+ if (val.source_render_frame_id != source_render_frame_id)
+ return false;
+ if (media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
+ media::AudioDeviceDescription::IsDefaultDevice(val.device_id)) {
+ // Both device IDs represent the same default device => do not compare
+ // them; the default device is always authorized => ignore security
+ // origin.
+ return true;
+ }
+ return val.device_id == device_id &&
+ val.security_origin == security_origin;
+ });
+};
+
+int AudioRendererSinkCacheImpl::GetCacheSizeForTesting() {
+ return cache_.size();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.h b/chromium/content/renderer/media/audio_renderer_sink_cache_impl.h
new file mode 100644
index 00000000000..7d163d9074c
--- /dev/null
+++ b/chromium/content/renderer/media/audio_renderer_sink_cache_impl.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_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_IMPL_H_
+
+#include "content/renderer/media/audio_renderer_sink_cache.h"
+
+#include <vector>
+
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// AudioRendererSinkCache implementation.
+class CONTENT_EXPORT AudioRendererSinkCacheImpl
+ : public AudioRendererSinkCache {
+ public:
+ // Callback to be used for AudioRendererSink creation
+ using CreateSinkCallback =
+ base::Callback<scoped_refptr<media::AudioRendererSink>(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin)>;
+
+ AudioRendererSinkCacheImpl(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const CreateSinkCallback& create_sink_callback,
+ base::TimeDelta delete_timeout);
+
+ ~AudioRendererSinkCacheImpl() final;
+
+ media::OutputDeviceInfo GetSinkInfo(int source_render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) final;
+
+ scoped_refptr<media::AudioRendererSink> GetSink(
+ int source_render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) final;
+
+ void ReleaseSink(const media::AudioRendererSink* sink_ptr) final;
+
+ private:
+ friend class AudioRendererSinkCacheTest;
+ friend class CacheEntryFinder;
+
+ struct CacheEntry;
+ using CacheContainer = std::vector<CacheEntry>;
+
+ // Schedules a sink for deletion. Deletion will be performed on the same
+ // thread the cache is created on.
+ void DeleteLaterIfUnused(const media::AudioRendererSink* sink_ptr);
+
+ // Deletes a sink from the cache. If |force_delete_used| is set, a sink being
+ // deleted can (and should) be in use at the moment of deletion; otherwise the
+ // sink is deleted only if unused.
+ void DeleteSink(const media::AudioRendererSink* sink_ptr,
+ bool force_delete_used);
+
+ CacheContainer::iterator FindCacheEntry_Locked(
+ int source_render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin,
+ bool unused_only);
+
+ // To avoid publishing CacheEntry structure in the header.
+ int GetCacheSizeForTesting();
+
+ // Task runner for scheduled sink garbage collection.
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ // Callback used for sink creation.
+ const CreateSinkCallback create_sink_cb_;
+
+ // Cached sink deletion timeout.
+ // For example: (1) sink was created and cached in GetSinkInfo(), and then (2)
+ // the same sink is requested in GetSink(), if time interval between (1) and
+ // (2) is less than |kDeleteTimeoutMs|, then sink cached in (1) is reused in
+ // (2). On the other hand, if after (1) nobody is interested in the sink
+ // within |kDeleteTimeoutMs|, it is garbage-collected.
+ const base::TimeDelta delete_timeout_;
+
+ // Cached sinks, protected by lock.
+ base::Lock cache_lock_;
+ CacheContainer cache_;
+
+ // Weak pointer to be used for delayed sink deletion on |task_runner_|.
+ // Pre-created in constructor and is used to post all the delayed tasks.
+ // A delayed task can be concurrently posted from any thread the cache is used
+ // on, so on-the-flight weak pointer creation with
+ // weak_ptr_factory_.GetWeakPtr() can't be used, because it will result in the
+ // racy access to the factory.
+ base::WeakPtr<AudioRendererSinkCacheImpl> weak_this_;
+
+ // Used to produce |weak_this_| on AudioRendererSinkCacheImpl construction.
+ base::WeakPtrFactory<AudioRendererSinkCacheImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioRendererSinkCacheImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_IMPL_H_
diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc b/chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc
new file mode 100644
index 00000000000..81e349c24fa
--- /dev/null
+++ b/chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc
@@ -0,0 +1,374 @@
+// 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 <array>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/test/test_timeouts.h"
+#include "content/renderer/media/audio_renderer_sink_cache_impl.h"
+#include "media/audio/audio_device_description.h"
+#include "media/base/audio_parameters.h"
+#include "media/base/mock_audio_renderer_sink.h"
+#include "media/base/test_helpers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+const char* const kDefaultDeviceId =
+ media::AudioDeviceDescription::kDefaultDeviceId;
+const char kAnotherDeviceId[] = "another-device-id";
+const int kRenderFrameId = 124;
+const int kDeleteTimeoutMs = 500;
+} // namespace
+
+class AudioRendererSinkCacheTest : public testing::Test {
+ public:
+ AudioRendererSinkCacheTest()
+ : cache_(new AudioRendererSinkCacheImpl(
+ message_loop_.task_runner(),
+ base::Bind(&AudioRendererSinkCacheTest::CreateSink,
+ base::Unretained(this)),
+ base::TimeDelta::FromMilliseconds(kDeleteTimeoutMs))) {}
+
+ void GetSink(int render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin,
+ media::AudioRendererSink** sink) {
+ *sink = cache_->GetSink(render_frame_id, device_id, security_origin).get();
+ }
+
+ void GetRandomSinkInfo(int frame) {
+ // Get info and check if memory is not corrupted.
+ EXPECT_EQ(kDefaultDeviceId,
+ cache_->GetSinkInfo(frame, 0, kDefaultDeviceId, url::Origin())
+ .device_id());
+ }
+
+ void GetRandomSink(int frame, base::TimeDelta sleep_timeout) {
+ scoped_refptr<media::AudioRendererSink> sink =
+ cache_->GetSink(frame, kDefaultDeviceId, url::Origin()).get();
+ ExpectToStop(sink.get());
+ base::PlatformThread::Sleep(sleep_timeout);
+ cache_->ReleaseSink(sink.get());
+ sink->Stop(); // Call a method to make the object is not corrupted.
+ }
+
+ protected:
+ int sink_count() {
+ DCHECK(message_loop_.task_runner()->BelongsToCurrentThread());
+ return cache_->GetCacheSizeForTesting();
+ }
+
+ scoped_refptr<media::AudioRendererSink> CreateSink(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ return new media::MockAudioRendererSink(device_id,
+ media::OUTPUT_DEVICE_STATUS_OK);
+ }
+
+ void ExpectToStop(media::AudioRendererSink* sink) {
+ // Sink must be stoped before deletion.
+ EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink), Stop())
+ .Times(1);
+ }
+
+ void ExpectNotToStop(media::AudioRendererSink* sink) {
+ // The sink must be stoped before deletion.
+ EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink), Stop())
+ .Times(0);
+ }
+
+ // Posts the task to the specified thread and runs current message loop until
+ // the task is completed.
+ void PostAndRunUntilDone(const base::Thread& thread,
+ const base::Closure& task) {
+ media::WaitableMessageLoopEvent event;
+ thread.task_runner()->PostTaskAndReply(FROM_HERE, task, event.GetClosure());
+ // Runs the loop and waits for the thread to call event's closure.
+ event.RunAndWait();
+ }
+
+ void WaitOnAnotherThread(const base::Thread& thread, int timeout_ms) {
+ PostAndRunUntilDone(
+ thread, base::Bind(base::IgnoreResult(&base::PlatformThread::Sleep),
+ base::TimeDelta::FromMilliseconds(timeout_ms)));
+ }
+
+ base::MessageLoop message_loop_;
+ std::unique_ptr<AudioRendererSinkCacheImpl> cache_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioRendererSinkCacheTest);
+};
+
+// Verify that normal get/release sink sequence works.
+TEST_F(AudioRendererSinkCacheTest, GetReleaseSink) {
+ // Verify that a new sink is successfully created.
+ EXPECT_EQ(0, sink_count());
+ scoped_refptr<media::AudioRendererSink> sink =
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ ExpectNotToStop(sink.get()); // Cache should not stop sinks marked as used.
+ EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
+ EXPECT_EQ(1, sink_count());
+
+ // Verify that another sink with the same key is successfully created
+ scoped_refptr<media::AudioRendererSink> another_sink =
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ ExpectNotToStop(another_sink.get());
+ EXPECT_EQ(kDefaultDeviceId, another_sink->GetOutputDeviceInfo().device_id());
+ EXPECT_EQ(2, sink_count());
+ EXPECT_NE(sink, another_sink);
+
+ // Verify that another sink with a different kay is successfully created.
+ scoped_refptr<media::AudioRendererSink> yet_another_sink =
+ cache_->GetSink(kRenderFrameId, kAnotherDeviceId, url::Origin()).get();
+ ExpectNotToStop(yet_another_sink.get());
+ EXPECT_EQ(kAnotherDeviceId,
+ yet_another_sink->GetOutputDeviceInfo().device_id());
+ EXPECT_EQ(3, sink_count());
+ EXPECT_NE(sink, yet_another_sink);
+ EXPECT_NE(another_sink, yet_another_sink);
+
+ // Verify that the first sink is successfully deleted.
+ cache_->ReleaseSink(sink.get());
+ EXPECT_EQ(2, sink_count());
+ sink = nullptr;
+
+ // Make sure we deleted the right sink, and the memory for the rest is not
+ // corrupted.
+ EXPECT_EQ(kDefaultDeviceId, another_sink->GetOutputDeviceInfo().device_id());
+ EXPECT_EQ(kAnotherDeviceId,
+ yet_another_sink->GetOutputDeviceInfo().device_id());
+
+ // Verify that the second sink is successfully deleted.
+ cache_->ReleaseSink(another_sink.get());
+ EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(kAnotherDeviceId,
+ yet_another_sink->GetOutputDeviceInfo().device_id());
+
+ cache_->ReleaseSink(yet_another_sink.get());
+ EXPECT_EQ(0, sink_count());
+}
+
+// Verify that the sink created with GetSinkInfo() is reused when possible.
+TEST_F(AudioRendererSinkCacheTest, GetDeviceInfo) {
+ EXPECT_EQ(0, sink_count());
+ media::OutputDeviceInfo device_info =
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ EXPECT_EQ(1, sink_count());
+
+ // The info on the same device is requested, so no new sink is created.
+ media::OutputDeviceInfo one_more_device_info =
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(device_info.device_id(), one_more_device_info.device_id());
+
+ // Aquire the sink that was created on GetSinkInfo().
+ scoped_refptr<media::AudioRendererSink> sink =
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(device_info.device_id(), sink->GetOutputDeviceInfo().device_id());
+
+ // Now the sink is in used, but we can still get the device info out of it, no
+ // new sink is created.
+ one_more_device_info =
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ EXPECT_EQ(1, sink_count());
+ EXPECT_EQ(device_info.device_id(), one_more_device_info.device_id());
+
+ // Request sink for the same device. The first sink is in use, so a new one
+ // should be created.
+ scoped_refptr<media::AudioRendererSink> another_sink =
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ EXPECT_EQ(2, sink_count());
+ EXPECT_EQ(device_info.device_id(),
+ another_sink->GetOutputDeviceInfo().device_id());
+}
+
+// Verify that the sink created with GetSinkInfo() is deleted if unused.
+// The test produces 2 "Uninteresting mock" warnings for
+// MockAudioRendererSink::Stop().
+TEST_F(AudioRendererSinkCacheTest, GarbageCollection) {
+ EXPECT_EQ(0, sink_count());
+ media::OutputDeviceInfo device_info =
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ EXPECT_EQ(1, sink_count());
+
+ media::OutputDeviceInfo another_device_info =
+ cache_->GetSinkInfo(kRenderFrameId, 0, kAnotherDeviceId, url::Origin());
+ EXPECT_EQ(2, sink_count());
+
+ base::Thread thread("timeout_thread");
+ thread.Start();
+
+ // 100 ms more than garbage collection timeout.
+ WaitOnAnotherThread(thread, kDeleteTimeoutMs + 100);
+
+ // All the sinks should be garbage-collected by now.
+ EXPECT_EQ(0, sink_count());
+}
+
+// Verify that the sink created with GetSinkInfo() is not deleted if used within
+// the timeout.
+TEST_F(AudioRendererSinkCacheTest, NoGarbageCollectionForUsedSink) {
+ EXPECT_EQ(0, sink_count());
+ media::OutputDeviceInfo device_info =
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ EXPECT_EQ(1, sink_count());
+
+ base::Thread thread("timeout_thread");
+ thread.Start();
+
+ // Wait significantly less than grabage collection timeout.
+ int wait_a_bit = 100;
+ DCHECK_GT(kDeleteTimeoutMs, wait_a_bit * 2);
+ WaitOnAnotherThread(thread, wait_a_bit);
+
+ // Sink is not deleted yet.
+ EXPECT_EQ(1, sink_count());
+
+ // Request it:
+ scoped_refptr<media::AudioRendererSink> sink =
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
+ EXPECT_EQ(1, sink_count());
+
+ // Wait more to hit garbage collection timeout.
+ WaitOnAnotherThread(thread, kDeleteTimeoutMs);
+
+ // The sink is still in place.
+ EXPECT_EQ(1, sink_count());
+}
+
+// Verify that cache works fine if a sink scheduled for delettion is aquired and
+// released before deletion timeout elapses.
+// The test produces one "Uninteresting mock" warning for
+// MockAudioRendererSink::Stop().
+TEST_F(AudioRendererSinkCacheTest, ReleaseSinkBeforeScheduledDeletion) {
+ EXPECT_EQ(0, sink_count());
+
+ media::OutputDeviceInfo device_info =
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ EXPECT_EQ(1, sink_count()); // This sink is scheduled for deletion now.
+
+ // Request it:
+ scoped_refptr<media::AudioRendererSink> sink =
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ ExpectNotToStop(sink.get());
+ EXPECT_EQ(1, sink_count());
+
+ // Release it:
+ cache_->ReleaseSink(sink.get());
+ EXPECT_EQ(0, sink_count());
+
+ media::OutputDeviceInfo another_device_info =
+ cache_->GetSinkInfo(kRenderFrameId, 0, kAnotherDeviceId, url::Origin());
+ EXPECT_EQ(1, sink_count()); // This sink is scheduled for deletion now.
+
+ base::Thread thread("timeout_thread");
+ thread.Start();
+
+ // 100 ms more than garbage collection timeout.
+ WaitOnAnotherThread(thread, kDeleteTimeoutMs + 100);
+
+ // Nothing crashed and the second sink deleted on schedule.
+ EXPECT_EQ(0, sink_count());
+}
+
+// Check that a sink created on one thread in response to GetSinkInfo can be
+// used on another thread.
+TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) {
+ EXPECT_EQ(0, sink_count());
+
+ base::Thread thread1("thread1");
+ thread1.Start();
+
+ base::Thread thread2("thread2");
+ thread2.Start();
+
+ // Request device information on the first thread.
+ PostAndRunUntilDone(
+ thread1,
+ base::Bind(base::IgnoreResult(&AudioRendererSinkCacheImpl::GetSinkInfo),
+ base::Unretained(cache_.get()), kRenderFrameId, 0,
+ kDefaultDeviceId, url::Origin()));
+
+ EXPECT_EQ(1, sink_count());
+
+ // Request the sink on the second thread.
+ media::AudioRendererSink* sink;
+
+ PostAndRunUntilDone(
+ thread2,
+ base::Bind(&AudioRendererSinkCacheTest::GetSink, base::Unretained(this),
+ kRenderFrameId, kDefaultDeviceId, url::Origin(), &sink));
+
+ EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
+ EXPECT_EQ(1, sink_count());
+
+ // Request device information on the first thread again.
+ PostAndRunUntilDone(
+ thread1,
+ base::Bind(base::IgnoreResult(&AudioRendererSinkCacheImpl::GetSinkInfo),
+ base::Unretained(cache_.get()), kRenderFrameId, 0,
+ kDefaultDeviceId, url::Origin()));
+ EXPECT_EQ(1, sink_count());
+
+ // Release the sink on the second thread.
+ PostAndRunUntilDone(thread2,
+ base::Bind(&AudioRendererSinkCache::ReleaseSink,
+ base::Unretained(cache_.get()), sink));
+
+ EXPECT_EQ(0, sink_count());
+}
+
+// Intensive parallell access to the cache. Produces a ton of "Uninteresting
+// mock" warnings for Stop() calls - this is fine.
+TEST_F(AudioRendererSinkCacheTest, SmokeTest) {
+ const int kExperimentSize = 1000;
+ const int kSinkCount = 10;
+ const int kThreadCount = 3;
+
+ // Sleep no more than (kDeleteTimeoutMs * 3) in total per thread.
+ const base::TimeDelta kSleepTimeout =
+ base::TimeDelta::FromMilliseconds(kDeleteTimeoutMs * 3 / kExperimentSize);
+
+ srand(42); // Does not matter.
+
+ std::array<std::unique_ptr<base::Thread>, kThreadCount> threads;
+ for (int i = 0; i < kThreadCount; ++i) {
+ threads[i].reset(new base::Thread(std::to_string(i)));
+ threads[i]->Start();
+ }
+
+ for (int i = 0; i < kExperimentSize; ++i) {
+ for (auto& thread : threads) {
+ thread->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&AudioRendererSinkCacheTest::GetRandomSinkInfo,
+ base::Unretained(this), rand() % kSinkCount));
+ thread->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&AudioRendererSinkCacheTest::GetRandomSink,
+ base::Unretained(this), rand() % kSinkCount,
+ kSleepTimeout));
+ }
+ }
+
+ // Wait for completion of all the tasks posted to at least one thread.
+ media::WaitableMessageLoopEvent loop_event(
+ TestTimeouts::action_max_timeout());
+ threads[kThreadCount - 1]->task_runner()->PostTaskAndReply(
+ FROM_HERE, base::Bind(&base::DoNothing), loop_event.GetClosure());
+ // Runs the loop and waits for the thread to call event's closure.
+ loop_event.RunAndWait();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/audio_track_recorder.cc b/chromium/content/renderer/media/audio_track_recorder.cc
index 603cbd99597..5d5e75235fa 100644
--- a/chromium/content/renderer/media/audio_track_recorder.cc
+++ b/chromium/content/renderer/media/audio_track_recorder.cc
@@ -15,6 +15,7 @@
#include "media/base/audio_converter.h"
#include "media/base/audio_fifo.h"
#include "media/base/audio_parameters.h"
+#include "media/base/audio_sample_types.h"
#include "media/base/bind_to_current_loop.h"
#include "third_party/opus/src/include/opus.h"
@@ -76,19 +77,6 @@ bool DoEncode(OpusEncoder* opus_encoder,
return false;
}
-// Interleaves |audio_bus| channels() of floats into a single output linear
-// |buffer|.
-// TODO(mcasas) https://crbug.com/580391 use AudioBus::ToInterleavedFloat().
-void ToInterleaved(media::AudioBus* audio_bus, float* buffer) {
- for (int ch = 0; ch < audio_bus->channels(); ++ch) {
- const float* src = audio_bus->channel(ch);
- const float* const src_end = src + audio_bus->frames();
- float* dest = buffer + ch;
- for (; src < src_end; ++src, dest += audio_bus->channels())
- *dest = *src;
- }
-}
-
} // anonymous namespace
// Nested class encapsulating opus-related encoding details. It contains an
@@ -119,7 +107,7 @@ class AudioTrackRecorder::AudioEncoder
// media::AudioConverted::InputCallback implementation.
double ProvideInput(media::AudioBus* audio_bus,
- base::TimeDelta buffer_delay) override;
+ uint32_t frames_delayed) override;
void DestroyExistingOpusEncoder();
@@ -259,7 +247,8 @@ void AudioTrackRecorder::AudioEncoder::EncodeAudio(
std::unique_ptr<media::AudioBus> audio_bus = media::AudioBus::Create(
output_params_.channels(), kOpusPreferredFramesPerBuffer);
converter_->Convert(audio_bus.get());
- ToInterleaved(audio_bus.get(), buffer_.get());
+ audio_bus->ToInterleaved<media::Float32SampleTypeTraits>(
+ audio_bus->frames(), buffer_.get());
std::unique_ptr<std::string> encoded_data(new std::string());
if (DoEncode(opus_encoder_, buffer_.get(), kOpusPreferredFramesPerBuffer,
@@ -277,7 +266,7 @@ void AudioTrackRecorder::AudioEncoder::EncodeAudio(
double AudioTrackRecorder::AudioEncoder::ProvideInput(
media::AudioBus* audio_bus,
- base::TimeDelta buffer_delay) {
+ uint32_t frames_delayed) {
fifo_->Consume(audio_bus, 0, audio_bus->frames());
return 1.0; // Return volume greater than zero to indicate we have more data.
}
diff --git a/chromium/content/renderer/media/canvas_capture_handler.cc b/chromium/content/renderer/media/canvas_capture_handler.cc
index 91d67f7e5d6..11f9ed7d43c 100644
--- a/chromium/content/renderer/media/canvas_capture_handler.cc
+++ b/chromium/content/renderer/media/canvas_capture_handler.cc
@@ -20,6 +20,7 @@
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/libyuv/include/libyuv.h"
+#include "third_party/skia/include/core/SkImage.h"
namespace {
@@ -288,7 +289,7 @@ void CanvasCaptureHandler::AddVideoCapturerSourceToVideoTrack(
web_track->initialize(webkit_source);
blink::WebMediaConstraints constraints;
constraints.initialize();
- web_track->setExtraData(new MediaStreamVideoTrack(
+ web_track->setTrackData(new MediaStreamVideoTrack(
media_stream_source.release(), constraints,
MediaStreamVideoSource::ConstraintsCallback(), true));
}
diff --git a/chromium/content/renderer/media/canvas_capture_handler.h b/chromium/content/renderer/media/canvas_capture_handler.h
index 4df1692223a..d4cd2568311 100644
--- a/chromium/content/renderer/media/canvas_capture_handler.h
+++ b/chromium/content/renderer/media/canvas_capture_handler.h
@@ -19,7 +19,9 @@
#include "third_party/WebKit/public/platform/WebCanvasCaptureHandler.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+
+class SkImage;
namespace content {
diff --git a/chromium/content/renderer/media/canvas_capture_handler_unittest.cc b/chromium/content/renderer/media/canvas_capture_handler_unittest.cc
index 98fe1c7d4fc..117fa8953a9 100644
--- a/chromium/content/renderer/media/canvas_capture_handler_unittest.cc
+++ b/chromium/content/renderer/media/canvas_capture_handler_unittest.cc
@@ -15,6 +15,8 @@
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/web/WebHeap.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
using ::testing::_;
using ::testing::InSequence;
diff --git a/chromium/content/renderer/media/cdm/renderer_cdm_manager.cc b/chromium/content/renderer/media/cdm/renderer_cdm_manager.cc
index 67402da7a84..4bf322a15fa 100644
--- a/chromium/content/renderer/media/cdm/renderer_cdm_manager.cc
+++ b/chromium/content/renderer/media/cdm/renderer_cdm_manager.cc
@@ -50,6 +50,10 @@ bool RendererCdmManager::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
+void RendererCdmManager::OnDestruct() {
+ delete this;
+}
+
void RendererCdmManager::InitializeCdm(int cdm_id,
uint32_t promise_id,
ProxyMediaKeys* media_keys,
diff --git a/chromium/content/renderer/media/cdm/renderer_cdm_manager.h b/chromium/content/renderer/media/cdm/renderer_cdm_manager.h
index e25ce556d49..143d8035be4 100644
--- a/chromium/content/renderer/media/cdm/renderer_cdm_manager.h
+++ b/chromium/content/renderer/media/cdm/renderer_cdm_manager.h
@@ -74,6 +74,9 @@ class RendererCdmManager : public RenderFrameObserver {
void UnregisterMediaKeys(int cdm_id);
private:
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
// Gets the pointer to ProxyMediaKeys given the |cdm_id|.
ProxyMediaKeys* GetMediaKeys(int cdm_id);
diff --git a/chromium/content/renderer/media/gpu/OWNERS b/chromium/content/renderer/media/gpu/OWNERS
new file mode 100644
index 00000000000..a1be1928a1c
--- /dev/null
+++ b/chromium/content/renderer/media/gpu/OWNERS
@@ -0,0 +1,2 @@
+posciak@chromium.org
+wuchengli@chromium.org
diff --git a/chromium/content/renderer/media/rtc_video_decoder.cc b/chromium/content/renderer/media/gpu/rtc_video_decoder.cc
index 32de1175114..1729882ab0d 100644
--- a/chromium/content/renderer/media/rtc_video_decoder.cc
+++ b/chromium/content/renderer/media/gpu/rtc_video_decoder.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/renderer/media/rtc_video_decoder.h"
+#include "content/renderer/media/gpu/rtc_video_decoder.h"
#include <utility>
@@ -67,6 +67,7 @@ RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type,
video_codec_type_(type),
factories_(factories),
decoder_texture_target_(0),
+ pixel_format_(media::PIXEL_FORMAT_UNKNOWN),
next_picture_buffer_id_(0),
state_(UNINITIALIZED),
decode_complete_callback_(nullptr),
@@ -120,7 +121,8 @@ std::unique_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
return decoder;
}
- base::WaitableEvent waiter(true, false);
+ base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
decoder.reset(new RTCVideoDecoder(type, factories));
decoder->factories_->GetTaskRunner()->PostTask(
FROM_HERE,
@@ -234,6 +236,10 @@ int32_t RTCVideoDecoder::Decode(
reset_bitstream_buffer_id_)) {
// TODO(wuchengli): VDA should handle it. Remove this when
// http://crosbug.com/p/21913 is fixed.
+
+ // If we're are in an error condition, increase the counter.
+ vda_error_counter_ += vda_error_counter_ ? 1 : 0;
+
DVLOG(1) << "The first frame should be a key frame. Drop this.";
return WEBRTC_VIDEO_CODEC_ERROR;
}
@@ -267,8 +273,6 @@ int32_t RTCVideoDecoder::Decode(
base::AutoUnlock auto_unlock(lock_);
Release();
}
-
- TryResetVDAErrorCounter_Locked();
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -277,7 +281,6 @@ int32_t RTCVideoDecoder::Decode(
FROM_HERE,
base::Bind(&RTCVideoDecoder::RequestBufferDecode,
weak_factory_.GetWeakPtr()));
- TryResetVDAErrorCounter_Locked();
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -315,6 +318,7 @@ int32_t RTCVideoDecoder::Release() {
}
void RTCVideoDecoder::ProvidePictureBuffers(uint32_t count,
+ media::VideoPixelFormat format,
uint32_t textures_per_buffer,
const gfx::Size& size,
uint32_t texture_target) {
@@ -328,6 +332,17 @@ void RTCVideoDecoder::ProvidePictureBuffers(uint32_t count,
std::vector<uint32_t> texture_ids;
std::vector<gpu::Mailbox> texture_mailboxes;
decoder_texture_target_ = texture_target;
+
+ if (format == media::PIXEL_FORMAT_UNKNOWN)
+ format = media::PIXEL_FORMAT_ARGB;
+
+ if ((pixel_format_ != media::PIXEL_FORMAT_UNKNOWN) &&
+ (format != pixel_format_)) {
+ NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
+ return;
+ }
+
+ pixel_format_ = format;
if (!factories_->CreateTextures(count,
size,
&texture_ids,
@@ -404,12 +419,8 @@ void RTCVideoDecoder::PictureReady(const media::Picture& picture) {
return;
}
- media::VideoPixelFormat pixel_format = vda_->GetOutputFormat();
- if (pixel_format == media::PIXEL_FORMAT_UNKNOWN)
- pixel_format = media::PIXEL_FORMAT_ARGB;
-
scoped_refptr<media::VideoFrame> frame =
- CreateVideoFrame(picture, pb, timestamp, visible_rect, pixel_format);
+ CreateVideoFrame(picture, pb, timestamp, visible_rect, pixel_format_);
if (!frame) {
NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
return;
@@ -433,6 +444,8 @@ void RTCVideoDecoder::PictureReady(const media::Picture& picture) {
reset_bitstream_buffer_id_)) {
decode_complete_callback_->Decoded(decoded_image);
}
+ // Reset error counter as we successfully decoded a frame.
+ vda_error_counter_ = 0;
}
}
@@ -879,12 +892,4 @@ void RTCVideoDecoder::ClearPendingBuffers() {
pending_buffers_.clear();
}
-void RTCVideoDecoder::TryResetVDAErrorCounter_Locked() {
- lock_.AssertAcquired();
-
- if (vda_error_counter_ == 0)
- return;
- vda_error_counter_ = 0;
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/rtc_video_decoder.h b/chromium/content/renderer/media/gpu/rtc_video_decoder.h
index 68d1c4baa76..274f6dfb6f6 100644
--- a/chromium/content/renderer/media/rtc_video_decoder.h
+++ b/chromium/content/renderer/media/gpu/rtc_video_decoder.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_RENDERER_MEDIA_RTC_VIDEO_DECODER_H_
-#define CONTENT_RENDERER_MEDIA_RTC_VIDEO_DECODER_H_
+#ifndef CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_H_
+#define CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_H_
#include <stddef.h>
#include <stdint.h>
@@ -82,6 +82,7 @@ class CONTENT_EXPORT RTCVideoDecoder
// VideoDecodeAccelerator::Client implementation.
void ProvidePictureBuffers(uint32_t count,
+ media::VideoPixelFormat format,
uint32_t textures_per_buffer,
const gfx::Size& size,
uint32_t texture_target) override;
@@ -200,9 +201,6 @@ class CONTENT_EXPORT RTCVideoDecoder
// Clears the pending_buffers_ queue, freeing memory.
void ClearPendingBuffers();
- // Resets |vda_error_counter_| after a successfull run of decode.
- void TryResetVDAErrorCounter_Locked();
-
enum State {
UNINITIALIZED, // The decoder has not initialized.
INITIALIZED, // The decoder has initialized.
@@ -233,6 +231,9 @@ class CONTENT_EXPORT RTCVideoDecoder
// The texture target used for decoded pictures.
uint32_t decoder_texture_target_;
+ // The format of the decoded pictures.
+ media::VideoPixelFormat pixel_format_;
+
// Metadata of the buffers that have been sent for decode.
std::list<BufferData> input_buffer_data_;
@@ -302,4 +303,4 @@ class CONTENT_EXPORT RTCVideoDecoder
} // namespace content
-#endif // CONTENT_RENDERER_MEDIA_RTC_VIDEO_DECODER_H_
+#endif // CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_H_
diff --git a/chromium/content/renderer/media/rtc_video_decoder_factory.cc b/chromium/content/renderer/media/gpu/rtc_video_decoder_factory.cc
index 0802698385e..04b9c1c648b 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_factory.cc
+++ b/chromium/content/renderer/media/gpu/rtc_video_decoder_factory.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/renderer/media/rtc_video_decoder_factory.h"
+#include "content/renderer/media/gpu/rtc_video_decoder_factory.h"
#include <memory>
-#include "content/renderer/media/rtc_video_decoder.h"
+#include "content/renderer/media/gpu/rtc_video_decoder.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
namespace content {
diff --git a/chromium/content/renderer/media/rtc_video_decoder_factory.h b/chromium/content/renderer/media/gpu/rtc_video_decoder_factory.h
index 7212b98bc78..5d53b2b125a 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_factory.h
+++ b/chromium/content/renderer/media/gpu/rtc_video_decoder_factory.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_RENDERER_MEDIA_RTC_VIDEO_DECODER_FACTORY_H_
-#define CONTENT_RENDERER_MEDIA_RTC_VIDEO_DECODER_FACTORY_H_
+#ifndef CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_FACTORY_H_
+#define CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_FACTORY_H_
#include "base/macros.h"
#include "base/threading/thread.h"
@@ -46,4 +46,4 @@ class CONTENT_EXPORT RTCVideoDecoderFactory
} // namespace content
-#endif // CONTENT_RENDERER_MEDIA_RTC_VIDEO_DECODER_FACTORY_H_
+#endif // CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_DECODER_FACTORY_H_
diff --git a/chromium/content/renderer/media/rtc_video_decoder_unittest.cc b/chromium/content/renderer/media/gpu/rtc_video_decoder_unittest.cc
index a3150048e8e..151e8fcb285 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_unittest.cc
+++ b/chromium/content/renderer/media/gpu/rtc_video_decoder_unittest.cc
@@ -11,7 +11,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "content/renderer/media/rtc_video_decoder.h"
+#include "content/renderer/media/gpu/rtc_video_decoder.h"
#include "media/base/gmock_callback_support.h"
#include "media/renderers/mock_gpu_video_accelerator_factories.h"
#include "media/video/mock_video_decode_accelerator.h"
@@ -49,7 +49,8 @@ class RTCVideoDecoderTest
: mock_gpu_factories_(
new media::MockGpuVideoAcceleratorFactories(nullptr)),
vda_thread_("vda_thread"),
- idle_waiter_(false, false) {
+ idle_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED) {
memset(&codec_, 0, sizeof(codec_));
}
@@ -281,7 +282,8 @@ TEST_F(RTCVideoDecoderTest, IsFirstBufferAfterReset) {
rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST));
}
-
+// Tests/Verifies that |rtc_encoder_| drops incoming frames and its error
+// counter is increased when in an error condition.
TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForTesting) {
const webrtc::VideoCodecType codec_type = GetParam();
CreateDecoder(codec_type);
@@ -292,6 +294,7 @@ TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForTesting) {
input_image._encodedWidth = kMinResolutionWidth;
input_image._encodedHeight = kMaxResolutionHeight;
input_image._frameType = webrtc::kVideoFrameDelta;
+ input_image._length = kMinResolutionWidth * kMaxResolutionHeight;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
RunUntilIdle();
@@ -307,16 +310,11 @@ TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForTesting) {
rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
- // Decoder expects a keyframe after reset, so drops any other frames.
+ // Decoder expects a keyframe after reset, so drops any other frames. However,
+ // we should still increment the error counter.
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
- EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
-
- // Decoder resets error counter after a successfull decode.
- input_image._frameType = webrtc::kVideoFrameKey;
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
- rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 10));
- EXPECT_EQ(0, rtc_decoder_->GetVDAErrorCounterForTesting());
+ EXPECT_EQ(2, rtc_decoder_->GetVDAErrorCounterForTesting());
}
INSTANTIATE_TEST_CASE_P(CodecProfiles,
diff --git a/chromium/content/renderer/media/rtc_video_encoder.cc b/chromium/content/renderer/media/gpu/rtc_video_encoder.cc
index 103e0c102b0..9cf55df82d3 100644
--- a/chromium/content/renderer/media/rtc_video_encoder.cc
+++ b/chromium/content/renderer/media/gpu/rtc_video_encoder.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/renderer/media/rtc_video_encoder.h"
+#include "content/renderer/media/gpu/rtc_video_encoder.h"
#include <string.h>
@@ -149,7 +149,8 @@ class RTCVideoEncoder::Impl
size_t output_buffer_size) override;
void BitstreamBufferReady(int32_t bitstream_buffer_id,
size_t payload_size,
- bool key_frame) override;
+ bool key_frame,
+ base::TimeDelta timestamp) override;
void NotifyError(media::VideoEncodeAccelerator::Error error) override;
private:
@@ -449,12 +450,13 @@ void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
}
void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id,
- size_t payload_size,
- bool key_frame) {
- DVLOG(3) << "Impl::BitstreamBufferReady(): "
- "bitstream_buffer_id=" << bitstream_buffer_id
- << ", payload_size=" << payload_size
- << ", key_frame=" << key_frame;
+ size_t payload_size,
+ bool key_frame,
+ base::TimeDelta timestamp) {
+ DVLOG(3) << "Impl::BitstreamBufferReady(): bitstream_buffer_id="
+ << bitstream_buffer_id << ", payload_size=" << payload_size
+ << ", key_frame=" << key_frame
+ << ", timestamp ms=" << timestamp.InMilliseconds();
DCHECK(thread_checker_.CalledOnValidThread());
if (bitstream_buffer_id < 0 ||
@@ -471,14 +473,17 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id,
}
output_buffers_free_count_--;
- // Use webrtc timestamps to ensure correct RTP sender behavior.
- // TODO(hshi): obtain timestamp from the capturer, see crbug.com/350106.
+ // CrOS Nyan provides invalid timestamp. Use the current time for now.
+ // TODO(wuchengli): use the timestamp in BitstreamBufferReady after Nyan is
+ // fixed. http://crbug.com/620565.
const int64_t capture_time_us = rtc::TimeMicros();
// Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks).
- const int64_t capture_time_ms = capture_time_us / 1000;
- const uint32_t rtp_timestamp =
- static_cast<uint32_t>(capture_time_us * 90 / 1000);
+ const int64_t capture_time_ms =
+ capture_time_us / base::Time::kMicrosecondsPerMillisecond;
+
+ const uint32_t rtp_timestamp = static_cast<uint32_t>(
+ capture_time_us * 90 / base::Time::kMicrosecondsPerMillisecond);
webrtc::EncodedImage image(
reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size,
@@ -568,7 +573,7 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
gfx::Rect(input_visible_size_), input_visible_size_,
reinterpret_cast<uint8_t*>(input_buffer->memory()),
input_buffer->mapped_size(), input_buffer->handle(), 0,
- base::TimeDelta());
+ base::TimeDelta::FromMilliseconds(next_frame->ntp_time_ms()));
if (!frame.get()) {
LogAndNotifyError(FROM_HERE, "failed to create frame",
media::VideoEncodeAccelerator::kPlatformFailureError);
@@ -740,7 +745,9 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
const media::VideoCodecProfile profile = WebRTCVideoCodecToVideoCodecProfile(
impl_->video_codec_type(), codec_settings);
- base::WaitableEvent initialization_waiter(true, false);
+ base::WaitableEvent initialization_waiter(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
gpu_task_runner_->PostTask(
FROM_HERE,
@@ -770,7 +777,9 @@ int32_t RTCVideoEncoder::Encode(
const bool want_key_frame = frame_types && frame_types->size() &&
frame_types->front() == webrtc::kVideoFrameKey;
- base::WaitableEvent encode_waiter(true, false);
+ base::WaitableEvent encode_waiter(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
int32_t encode_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
gpu_task_runner_->PostTask(
FROM_HERE,
@@ -795,7 +804,9 @@ int32_t RTCVideoEncoder::RegisterEncodeCompleteCallback(
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
- base::WaitableEvent register_waiter(true, false);
+ base::WaitableEvent register_waiter(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
int32_t register_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
gpu_task_runner_->PostTask(
FROM_HERE,
@@ -810,7 +821,9 @@ int32_t RTCVideoEncoder::Release() {
if (!impl_.get())
return WEBRTC_VIDEO_CODEC_OK;
- base::WaitableEvent release_waiter(true, false);
+ base::WaitableEvent release_waiter(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
gpu_task_runner_->PostTask(
FROM_HERE,
base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_, &release_waiter));
diff --git a/chromium/content/renderer/media/rtc_video_encoder.h b/chromium/content/renderer/media/gpu/rtc_video_encoder.h
index c71c3baaf59..6f8053f3957 100644
--- a/chromium/content/renderer/media/rtc_video_encoder.h
+++ b/chromium/content/renderer/media/gpu/rtc_video_encoder.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_RENDERER_MEDIA_RTC_VIDEO_ENCODER_H_
-#define CONTENT_RENDERER_MEDIA_RTC_VIDEO_ENCODER_H_
+#ifndef CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_ENCODER_H_
+#define CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_ENCODER_H_
#include <stddef.h>
#include <stdint.h>
@@ -80,4 +80,4 @@ class CONTENT_EXPORT RTCVideoEncoder
} // namespace content
-#endif // CONTENT_RENDERER_MEDIA_RTC_VIDEO_ENCODER_H_
+#endif // CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_ENCODER_H_
diff --git a/chromium/content/renderer/media/rtc_video_encoder_factory.cc b/chromium/content/renderer/media/gpu/rtc_video_encoder_factory.cc
index 7e99b7c1386..9295464f758 100644
--- a/chromium/content/renderer/media/rtc_video_encoder_factory.cc
+++ b/chromium/content/renderer/media/gpu/rtc_video_encoder_factory.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/renderer/media/rtc_video_encoder_factory.h"
+#include "content/renderer/media/gpu/rtc_video_encoder_factory.h"
#include "base/command_line.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
-#include "content/renderer/media/rtc_video_encoder.h"
+#include "content/renderer/media/gpu/rtc_video_encoder.h"
#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
#include "media/video/video_encode_accelerator.h"
diff --git a/chromium/content/renderer/media/rtc_video_encoder_factory.h b/chromium/content/renderer/media/gpu/rtc_video_encoder_factory.h
index 45b48ca82e1..efe538d33e8 100644
--- a/chromium/content/renderer/media/rtc_video_encoder_factory.h
+++ b/chromium/content/renderer/media/gpu/rtc_video_encoder_factory.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_RENDERER_MEDIA_RTC_VIDEO_ENCODER_FACTORY_H_
-#define CONTENT_RENDERER_MEDIA_RTC_VIDEO_ENCODER_FACTORY_H_
+#ifndef CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_ENCODER_FACTORY_H_
+#define CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_ENCODER_FACTORY_H_
#include <vector>
@@ -45,4 +45,4 @@ class CONTENT_EXPORT RTCVideoEncoderFactory
} // namespace content
-#endif // CONTENT_RENDERER_MEDIA_RTC_VIDEO_ENCODER_FACTORY_H_
+#endif // CONTENT_RENDERER_MEDIA_GPU_RTC_VIDEO_ENCODER_FACTORY_H_
diff --git a/chromium/content/renderer/media/html_audio_element_capturer_source.cc b/chromium/content/renderer/media/html_audio_element_capturer_source.cc
new file mode 100644
index 00000000000..7e0edfc9768
--- /dev/null
+++ b/chromium/content/renderer/media/html_audio_element_capturer_source.cc
@@ -0,0 +1,90 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/html_audio_element_capturer_source.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "media/base/audio_parameters.h"
+#include "media/base/audio_renderer_sink.h"
+#include "media/blink/webaudiosourceprovider_impl.h"
+#include "media/blink/webmediaplayer_impl.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
+
+namespace content {
+
+//static
+HtmlAudioElementCapturerSource*
+HtmlAudioElementCapturerSource::CreateFromWebMediaPlayerImpl(
+ blink::WebMediaPlayer* player) {
+ DCHECK(player);
+ return new HtmlAudioElementCapturerSource(
+ static_cast<media::WebAudioSourceProviderImpl*>(
+ player->getAudioSourceProvider()));
+}
+
+HtmlAudioElementCapturerSource::HtmlAudioElementCapturerSource(
+ media::WebAudioSourceProviderImpl* audio_source)
+ : MediaStreamAudioSource(true /* is_local_source */),
+ audio_source_(audio_source),
+ is_started_(false),
+ last_sample_rate_(0),
+ last_num_channels_(0),
+ last_bus_frames_(0) {
+ DCHECK(audio_source_);
+}
+
+HtmlAudioElementCapturerSource::~HtmlAudioElementCapturerSource() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ EnsureSourceIsStopped();
+}
+
+bool HtmlAudioElementCapturerSource::EnsureSourceIsStarted() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (audio_source_ && !is_started_) {
+ // base:Unretained() is safe here since EnsureSourceIsStopped() guarantees
+ // no more calls to OnAudioBus().
+ audio_source_->SetCopyAudioCallback(base::Bind(
+ &HtmlAudioElementCapturerSource::OnAudioBus, base::Unretained(this)));
+ is_started_ = true;
+ }
+ return is_started_;
+}
+
+void HtmlAudioElementCapturerSource::EnsureSourceIsStopped() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!is_started_)
+ return;
+
+ if (audio_source_) {
+ audio_source_->ClearCopyAudioCallback();
+ audio_source_ = nullptr;
+ }
+ is_started_ = false;
+}
+
+void HtmlAudioElementCapturerSource::OnAudioBus(
+ std::unique_ptr<media::AudioBus> audio_bus,
+ uint32_t frames_delayed,
+ int sample_rate) {
+ const base::TimeTicks capture_time =
+ base::TimeTicks::Now() -
+ base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond *
+ frames_delayed / sample_rate);
+
+ if (sample_rate != last_sample_rate_ ||
+ audio_bus->channels() != last_num_channels_ ||
+ audio_bus->frames() != last_bus_frames_) {
+ MediaStreamAudioSource::SetFormat(
+ media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::GuessChannelLayout(audio_bus->channels()),
+ sample_rate, 16, audio_bus->frames()));
+ last_sample_rate_ = sample_rate;
+ last_num_channels_ = audio_bus->channels();
+ last_bus_frames_ = audio_bus->frames();
+ }
+
+ MediaStreamAudioSource::DeliverDataToTracks(*audio_bus, capture_time);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/html_audio_element_capturer_source.h b/chromium/content/renderer/media/html_audio_element_capturer_source.h
new file mode 100644
index 00000000000..48ea5006832
--- /dev/null
+++ b/chromium/content/renderer/media/html_audio_element_capturer_source.h
@@ -0,0 +1,63 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_HTML_AUDIO_ELEMENT_CAPTURER_SOURCE_H_
+#define CONTENT_RENDERER_MEDIA_HTML_AUDIO_ELEMENT_CAPTURER_SOURCE_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "content/renderer/media/media_stream_audio_source.h"
+
+namespace blink {
+class WebMediaPlayer;
+} // namespace blink
+
+namespace media {
+class AudioBus;
+class WebAudioSourceProviderImpl;
+} // namespace media
+
+namespace content {
+
+// This class is a MediaStreamAudioSource that registers to the constructor-
+// passed weak WebAudioSourceProviderImpl to receive a copy of the audio data
+// intended for rendering. This copied data is received on OnAudioBus() and sent
+// to all the registered Tracks.
+class CONTENT_EXPORT HtmlAudioElementCapturerSource final
+ : NON_EXPORTED_BASE(public MediaStreamAudioSource) {
+ public:
+ static HtmlAudioElementCapturerSource*
+ CreateFromWebMediaPlayerImpl(blink::WebMediaPlayer* player);
+
+ explicit HtmlAudioElementCapturerSource(
+ media::WebAudioSourceProviderImpl* audio_source);
+ ~HtmlAudioElementCapturerSource() override;
+
+ private:
+ // MediaStreamAudioSource implementation.
+ bool EnsureSourceIsStarted() final;
+ void EnsureSourceIsStopped() final;
+
+ // To act as an WebAudioSourceProviderImpl::CopyAudioCB.
+ void OnAudioBus(std::unique_ptr<media::AudioBus> audio_bus,
+ uint32_t frames_delayed,
+ int sample_rate);
+
+ scoped_refptr<media::WebAudioSourceProviderImpl> audio_source_;
+
+ bool is_started_;
+ int last_sample_rate_;
+ int last_num_channels_;
+ int last_bus_frames_;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(HtmlAudioElementCapturerSource);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_HTML_AUDIO_ELEMENT_CAPTURER_SOURCE_H_
diff --git a/chromium/content/renderer/media/html_audio_element_capturer_source_unittest.cc b/chromium/content/renderer/media/html_audio_element_capturer_source_unittest.cc
new file mode 100644
index 00000000000..10d24ed7ec5
--- /dev/null
+++ b/chromium/content/renderer/media/html_audio_element_capturer_source_unittest.cc
@@ -0,0 +1,154 @@
+// 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/memory/weak_ptr.h"
+#include "base/run_loop.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "content/public/renderer/media_stream_audio_sink.h"
+#include "content/renderer/media/html_audio_element_capturer_source.h"
+#include "content/renderer/media/media_stream_audio_track.h"
+#include "media/audio/null_audio_sink.h"
+#include "media/base/audio_parameters.h"
+#include "media/base/fake_audio_render_callback.h"
+#include "media/blink/webaudiosourceprovider_impl.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
+
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::InSequence;
+using ::testing::Mock;
+using ::testing::Property;
+
+namespace content {
+
+static const int kNumChannelsForTest = 1;
+static const int kBufferDurationMs = 10;
+
+static const int kAudioTrackSampleRate = 48000;
+static const int kAudioTrackSamplesPerBuffer =
+ kAudioTrackSampleRate * kBufferDurationMs /
+ base::Time::kMillisecondsPerSecond;
+
+ACTION_P(RunClosure, closure) {
+ closure.Run();
+}
+
+//
+class MockMediaStreamAudioSink final : public MediaStreamAudioSink {
+ public:
+ MockMediaStreamAudioSink() : MediaStreamAudioSink() {}
+ ~MockMediaStreamAudioSink() = default;
+
+ MOCK_METHOD1(OnSetFormat, void(const media::AudioParameters& params));
+ MOCK_METHOD2(OnData,
+ void(const media::AudioBus& audio_bus,
+ base::TimeTicks estimated_capture_time));
+
+ DISALLOW_COPY_AND_ASSIGN(MockMediaStreamAudioSink);
+};
+
+// This test needs to bundle together plenty of objects, namely:
+// - a WebAudioSourceProviderImpl, which in turn needs an Audio Sink, in this
+// case a NullAudioSink. This is needed to plug HTMLAudioElementCapturerSource
+// and inject audio.
+// - a WebMediaStreamSource, that owns the HTMLAudioElementCapturerSource under
+// test, and a WebMediaStreamAudioTrack, that the class under test needs to
+// connect to in order to operate correctly. This class has an inner content
+// MediaStreamAudioTrack.
+// - finally, a MockMediaStreamAudioSink to observe captured audio frames, and
+// that plugs into the former MediaStreamAudioTrack.
+class HTMLAudioElementCapturerSourceTest : public testing::Test {
+ public:
+ HTMLAudioElementCapturerSourceTest()
+ : fake_callback_(0.1),
+ audio_source_(new media::WebAudioSourceProviderImpl(
+ new media::NullAudioSink(base::ThreadTaskRunnerHandle::Get()))) {}
+
+ void SetUp() final {
+ const media::AudioParameters params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::GuessChannelLayout(kNumChannelsForTest),
+ kAudioTrackSampleRate /* sample_rate */, 16 /* bits_per_sample */,
+ kAudioTrackSamplesPerBuffer /* frames_per_buffer */);
+ audio_source_->Initialize(params, &fake_callback_);
+
+ blink_audio_source_.initialize(blink::WebString::fromUTF8("audio_id"),
+ blink::WebMediaStreamSource::TypeAudio,
+ blink::WebString::fromUTF8("audio_track"),
+ false /* remote */);
+ blink_audio_track_.initialize(blink_audio_source_.id(),
+ blink_audio_source_);
+
+ // |blink_audio_source_| takes ownership of HtmlAudioElementCapturerSource.
+ blink_audio_source_.setExtraData(
+ new HtmlAudioElementCapturerSource(audio_source_.get()));
+ ASSERT_TRUE(source()->ConnectToTrack(blink_audio_track_));
+ }
+
+ void TearDown() override {
+ blink_audio_track_.reset();
+ blink_audio_source_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
+ }
+
+ HtmlAudioElementCapturerSource* source() const {
+ return static_cast<HtmlAudioElementCapturerSource*>(
+ MediaStreamAudioSource::From(blink_audio_source_));
+ }
+
+ MediaStreamAudioTrack* track() const {
+ return MediaStreamAudioTrack::From(blink_audio_track_);
+ }
+
+ int InjectAudio(media::AudioBus* audio_bus) {
+ return audio_source_->RenderForTesting(audio_bus);
+ }
+
+ protected:
+ const base::MessageLoop message_loop_;
+
+ blink::WebMediaStreamSource blink_audio_source_;
+ blink::WebMediaStreamTrack blink_audio_track_;
+
+ media::FakeAudioRenderCallback fake_callback_;
+ scoped_refptr<media::WebAudioSourceProviderImpl> audio_source_;
+};
+
+// Constructs and destructs all objects. This is a non trivial sequence.
+TEST_F(HTMLAudioElementCapturerSourceTest, ConstructAndDestruct) {
+}
+
+// This test verifies that Audio can be properly captured when injected in the
+// WebAudioSourceProviderImpl.
+TEST_F(HTMLAudioElementCapturerSourceTest, CaptureAudio) {
+ InSequence s;
+
+ base::RunLoop run_loop;
+ base::Closure quit_closure = run_loop.QuitClosure();
+
+ MockMediaStreamAudioSink sink;
+ track()->AddSink(&sink);
+ EXPECT_CALL(sink, OnSetFormat(_)).Times(1);
+ EXPECT_CALL(
+ sink,
+ OnData(AllOf(Property(&media::AudioBus::channels, kNumChannelsForTest),
+ Property(&media::AudioBus::frames,
+ kAudioTrackSamplesPerBuffer)),
+ _))
+ .Times(1)
+ .WillOnce(RunClosure(quit_closure));
+
+ std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create(
+ kNumChannelsForTest, kAudioTrackSamplesPerBuffer);
+ InjectAudio(bus.get());
+ run_loop.Run();
+
+ track()->Stop();
+ track()->RemoveSink(&sink);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/html_video_element_capturer_source.cc b/chromium/content/renderer/media/html_video_element_capturer_source.cc
index 3087a47aae2..88108ee50e5 100644
--- a/chromium/content/renderer/media/html_video_element_capturer_source.cc
+++ b/chromium/content/renderer/media/html_video_element_capturer_source.cc
@@ -4,7 +4,9 @@
#include "content/renderer/media/html_video_element_capturer_source.h"
+#include "base/location.h"
#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "content/public/renderer/render_thread.h"
@@ -12,11 +14,13 @@
#include "content/renderer/media/webrtc_uma_histograms.h"
#include "media/base/limits.h"
#include "media/blink/webmediaplayer_impl.h"
+#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/libyuv/include/libyuv.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkXfermode.h"
namespace {
@@ -91,9 +95,12 @@ void HtmlVideoElementCapturerSource::StartCapture(
return;
}
const blink::WebSize resolution = web_media_player_->naturalSize();
- canvas_ = sk_sp<SkCanvas>(skia::CreatePlatformCanvas(resolution.width,
- resolution.height,
- true /* is_opaque */));
+ surface_ =
+ SkSurface::MakeRasterN32Premul(resolution.width, resolution.height);
+ if (!surface_) {
+ running_callback_.Run(false);
+ return;
+ }
new_frame_callback_ = new_frame_callback;
// Force |capture_frame_rate_| to be in between k{Min,Max}FramesPerSecond.
@@ -127,14 +134,15 @@ void HtmlVideoElementCapturerSource::sendNewFrame() {
const base::TimeTicks current_time = base::TimeTicks::Now();
const blink::WebSize resolution = web_media_player_->naturalSize();
+ SkCanvas* canvas = surface_->getCanvas();
web_media_player_->paint(
- canvas_.get(), blink::WebRect(0, 0, resolution.width, resolution.height),
+ canvas, blink::WebRect(0, 0, resolution.width, resolution.height),
0xFF /* alpha */, SkXfermode::kSrc_Mode);
- DCHECK_NE(kUnknown_SkColorType, canvas_->imageInfo().colorType());
- DCHECK_EQ(canvas_->imageInfo().width(), resolution.width);
- DCHECK_EQ(canvas_->imageInfo().height(), resolution.height);
+ DCHECK_NE(kUnknown_SkColorType, canvas->imageInfo().colorType());
+ DCHECK_EQ(canvas->imageInfo().width(), resolution.width);
+ DCHECK_EQ(canvas->imageInfo().height(), resolution.height);
- const SkBitmap bitmap = skia::ReadPixels(canvas_.get());
+ const SkBitmap bitmap = skia::ReadPixels(canvas);
DCHECK_NE(kUnknown_SkColorType, bitmap.colorType());
DCHECK(!bitmap.drawsNothing());
DCHECK(bitmap.getPixels());
@@ -160,8 +168,8 @@ void HtmlVideoElementCapturerSource::sendNewFrame() {
0 /* crop_y */,
bitmap.info().width(),
bitmap.info().height(),
- frame->natural_size().width(),
- frame->natural_size().height(),
+ frame->coded_size().width(),
+ frame->coded_size().height(),
libyuv::kRotate0,
libyuv::FOURCC_ARGB) == 0) {
// Success!
@@ -182,7 +190,7 @@ void HtmlVideoElementCapturerSource::sendNewFrame() {
next_capture_time_ = current_time;
}
// Schedule next capture.
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::Bind(&HtmlVideoElementCapturerSource::sendNewFrame,
weak_factory_.GetWeakPtr()),
next_capture_time_ - current_time);
diff --git a/chromium/content/renderer/media/html_video_element_capturer_source.h b/chromium/content/renderer/media/html_video_element_capturer_source.h
index e248358846d..2d7598b5ece 100644
--- a/chromium/content/renderer/media/html_video_element_capturer_source.h
+++ b/chromium/content/renderer/media/html_video_element_capturer_source.h
@@ -13,14 +13,15 @@
#include "media/base/video_capturer_source.h"
#include "media/base/video_frame_pool.h"
#include "media/base/video_types.h"
-#include "skia/ext/platform_canvas.h"
-#include "skia/ext/refptr.h"
#include "third_party/WebKit/public/platform/WebSize.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
namespace blink {
class WebMediaPlayer;
} // namespace blink
+class SkSurface;
+
namespace content {
// This class is a VideoCapturerSource taking video snapshots of the ctor-passed
@@ -56,7 +57,7 @@ class CONTENT_EXPORT HtmlVideoElementCapturerSource final
void sendNewFrame();
media::VideoFramePool frame_pool_;
- sk_sp<SkCanvas> canvas_;
+ sk_sp<SkSurface> surface_;
const base::WeakPtr<blink::WebMediaPlayer> web_media_player_;
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
diff --git a/chromium/content/renderer/media/image_capture_frame_grabber.cc b/chromium/content/renderer/media/image_capture_frame_grabber.cc
index a7a37bf4d98..faeb43f8382 100644
--- a/chromium/content/renderer/media/image_capture_frame_grabber.cc
+++ b/chromium/content/renderer/media/image_capture_frame_grabber.cc
@@ -88,7 +88,7 @@ void ImageCaptureFrameGrabber::grabFrame(
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!!callbacks);
- DCHECK(track && !track->isNull() && track->getExtraData());
+ DCHECK(track && !track->isNull() && track->getTrackData());
DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track->source().getType());
ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> scoped_callbacks =
diff --git a/chromium/content/renderer/media/media_interface_provider.cc b/chromium/content/renderer/media/media_interface_provider.cc
index 84faca9bb32..8e3968e2182 100644
--- a/chromium/content/renderer/media/media_interface_provider.cc
+++ b/chromium/content/renderer/media/media_interface_provider.cc
@@ -37,6 +37,9 @@ void MediaInterfaceProvider::GetInterface(const mojo::String& interface_name,
} else if (interface_name == media::mojom::AudioDecoder::Name_) {
GetMediaServiceFactory()->CreateAudioDecoder(
mojo::MakeRequest<media::mojom::AudioDecoder>(std::move(pipe)));
+ } else if (interface_name == media::mojom::VideoDecoder::Name_) {
+ GetMediaServiceFactory()->CreateVideoDecoder(
+ mojo::MakeRequest<media::mojom::VideoDecoder>(std::move(pipe)));
} else {
NOTREACHED();
}
diff --git a/chromium/content/renderer/media/media_permission_dispatcher.cc b/chromium/content/renderer/media/media_permission_dispatcher.cc
index 764a4a0b92f..b28bc0363e1 100644
--- a/chromium/content/renderer/media/media_permission_dispatcher.cc
+++ b/chromium/content/renderer/media/media_permission_dispatcher.cc
@@ -9,6 +9,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/base/bind_to_current_loop.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "url/gurl.h"
namespace {
@@ -98,6 +99,7 @@ void MediaPermissionDispatcher::RequestPermission(
permission_service_->RequestPermission(
MediaPermissionTypeToPermissionName(type), security_origin.spec(),
+ blink::WebUserGestureIndicator::isProcessingUserGesture(),
base::Bind(&MediaPermissionDispatcher::OnPermissionStatus, weak_ptr_,
request_id));
}
diff --git a/chromium/content/renderer/media/media_recorder_handler.cc b/chromium/content/renderer/media/media_recorder_handler.cc
index 3dc54b51ef4..19cec5a4e92 100644
--- a/chromium/content/renderer/media/media_recorder_handler.cc
+++ b/chromium/content/renderer/media/media_recorder_handler.cc
@@ -40,10 +40,8 @@ media::VideoCodec CodecIdToMediaVideoCodec(VideoTrackRecorder::CodecId id) {
return media::kCodecVP8;
case VideoTrackRecorder::CodecId::VP9:
return media::kCodecVP9;
-#if BUILDFLAG(RTC_USE_H264)
case VideoTrackRecorder::CodecId::H264:
return media::kCodecH264;
-#endif
}
NOTREACHED() << "Unsupported codec";
return media::kUnknownVideoCodec;
@@ -177,6 +175,11 @@ bool MediaRecorderHandler::start(int timeslice) {
audio_tracks[0].source().getReadyState() !=
blink::WebMediaStreamSource::ReadyStateEnded;
+ if (!use_video_tracks && !use_audio_tracks) {
+ LOG(WARNING) << __FUNCTION__ << ": no tracks to be recorded.";
+ return false;
+ }
+
webm_muxer_.reset(new media::WebmMuxer(
CodecIdToMediaVideoCodec(codec_id_), use_video_tracks, use_audio_tracks,
base::Bind(&MediaRecorderHandler::WriteData,
diff --git a/chromium/content/renderer/media/media_stream_audio_deliverer.h b/chromium/content/renderer/media/media_stream_audio_deliverer.h
index 80a6a1c4193..cb0774eed54 100644
--- a/chromium/content/renderer/media/media_stream_audio_deliverer.h
+++ b/chromium/content/renderer/media/media_stream_audio_deliverer.h
@@ -137,7 +137,7 @@ class MediaStreamAudioDeliverer {
// |consumers_| on the audio thread.
std::vector<Consumer*> pending_consumers_;
- // Consumers that are up-to-date on the current audio format and are receiving
+ // Consumers that are up to date on the current audio format and are receiving
// audio data are placed in this list.
std::vector<Consumer*> consumers_;
diff --git a/chromium/content/renderer/media/media_stream_audio_processor.cc b/chromium/content/renderer/media/media_stream_audio_processor.cc
index 68aefcbff88..c02696e0684 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor.cc
+++ b/chromium/content/renderer/media/media_stream_audio_processor.cc
@@ -136,6 +136,11 @@ class MediaStreamAudioBus {
thread_checker_.DetachFromThread();
}
+ void ReattachThreadChecker() {
+ thread_checker_.DetachFromThread();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ }
+
media::AudioBus* bus() {
DCHECK(thread_checker_.CalledOnValidThread());
return bus_.get();
@@ -194,6 +199,12 @@ class MediaStreamAudioFifo {
thread_checker_.DetachFromThread();
}
+ void ReattachThreadChecker() {
+ thread_checker_.DetachFromThread();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ destination_->ReattachThreadChecker();
+ }
+
void Push(const media::AudioBus& source, base::TimeDelta audio_delay) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(source.channels(), source_channels_);
@@ -276,6 +287,7 @@ MediaStreamAudioProcessor::MediaStreamAudioProcessor(
WebRtcPlayoutDataSource* playout_data_source)
: render_delay_ms_(0),
playout_data_source_(playout_data_source),
+ main_thread_message_loop_(base::MessageLoop::current()),
audio_mirroring_(false),
typing_detected_(false),
stopped_(false) {
@@ -378,6 +390,7 @@ bool MediaStreamAudioProcessor::ProcessAndConsumeData(
void MediaStreamAudioProcessor::Stop() {
DCHECK(main_thread_checker_.CalledOnValidThread());
+
if (stopped_)
return;
@@ -398,6 +411,9 @@ void MediaStreamAudioProcessor::Stop() {
playout_data_source_->RemovePlayoutSink(this);
playout_data_source_ = NULL;
}
+
+ if (echo_information_)
+ echo_information_->ReportAndResetAecDivergentFilterStats();
}
const media::AudioParameters& MediaStreamAudioProcessor::InputFormat() const {
@@ -474,6 +490,12 @@ void MediaStreamAudioProcessor::OnPlayoutDataSourceChanged() {
render_fifo_.reset();
}
+void MediaStreamAudioProcessor::OnRenderThreadChanged() {
+ render_thread_checker_.DetachFromThread();
+ DCHECK(render_thread_checker_.CalledOnValidThread());
+ render_fifo_->ReattachThreadChecker();
+}
+
void MediaStreamAudioProcessor::GetStats(AudioProcessorStats* stats) {
stats->typing_noise_detected =
(base::subtle::Acquire_Load(&typing_detected_) != false);
@@ -739,13 +761,18 @@ int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs,
base::subtle::Release_Store(&typing_detected_, detected);
}
- if (echo_information_) {
- echo_information_.get()->UpdateAecDelayStats(ap->echo_cancellation());
- }
+ main_thread_message_loop_->PostTask(
+ FROM_HERE, base::Bind(&MediaStreamAudioProcessor::UpdateAecStats, this));
// Return 0 if the volume hasn't been changed, and otherwise the new volume.
return (agc->stream_analog_level() == volume) ?
0 : agc->stream_analog_level();
}
+void MediaStreamAudioProcessor::UpdateAecStats() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ if (echo_information_)
+ echo_information_->UpdateAecStats(audio_processing_->echo_cancellation());
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_processor.h b/chromium/content/renderer/media/media_stream_audio_processor.h
index 66290159ce2..8b0c0943a46 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor.h
+++ b/chromium/content/renderer/media/media_stream_audio_processor.h
@@ -124,6 +124,7 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
int sample_rate,
int audio_delay_milliseconds) override;
void OnPlayoutDataSourceChanged() override;
+ void OnRenderThreadChanged() override;
// webrtc::AudioProcessorInterface implementation.
// This method is called on the libjingle thread.
@@ -152,6 +153,9 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
bool key_pressed,
float* const* output_ptrs);
+ // Update AEC stats. Called on the main render thread.
+ void UpdateAecStats();
+
// Cached value for the render delay latency. This member is accessed by
// both the capture audio thread and the render audio thread.
base::subtle::Atomic32 render_delay_ms_;
@@ -189,13 +193,17 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// Used to DCHECK that some methods are called on the render audio thread.
base::ThreadChecker render_thread_checker_;
+ // Message loop for the main render thread. We're assuming that we're created
+ // on the main render thread.
+ base::MessageLoop* main_thread_message_loop_;
+
// Flag to enable stereo channel mirroring.
bool audio_mirroring_;
+ // Typing detector. |typing_detected_| is used to show the result of typing
+ // detection. It can be accessed by the capture audio thread and by the
+ // libjingle thread which calls GetStats().
std::unique_ptr<webrtc::TypingDetection> typing_detector_;
- // This flag is used to show the result of typing detection.
- // It can be accessed by the capture audio thread and by the libjingle thread
- // which calls GetStats().
base::subtle::Atomic32 typing_detected_;
// Communication with browser for AEC dump.
@@ -204,8 +212,8 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// Flag to avoid executing Stop() more than once.
bool stopped_;
- // Object for logging echo information when the AEC is enabled. Accessible by
- // the libjingle thread through GetStats().
+ // Object for logging UMA stats for echo information when the AEC is enabled.
+ // Accessed on the main render thread.
std::unique_ptr<EchoInformation> echo_information_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioProcessor);
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.cc b/chromium/content/renderer/media/media_stream_audio_processor_options.cc
index 99bf7b590fb..d4ca596eac3 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor_options.cc
+++ b/chromium/content/renderer/media/media_stream_audio_processor_options.cc
@@ -48,6 +48,9 @@ const char MediaAudioConstraints::kGoogAudioMirroring[] = "googAudioMirroring";
namespace {
+// Controls whether the hotword audio stream is used on supported platforms.
+const char kMediaStreamAudioHotword[] = "googHotword";
+
// Constant constraint keys which enables default audio constraints on
// mediastreams with audio.
struct {
@@ -297,13 +300,32 @@ std::string MediaAudioConstraints::GetGoogArrayGeometry() const {
}
EchoInformation::EchoInformation()
- : num_chunks_(0), echo_frames_received_(false) {
+ : delay_stats_time_ms_(0),
+ echo_frames_received_(false),
+ divergent_filter_stats_time_ms_(0),
+ num_divergent_filter_fraction_(0),
+ num_non_zero_divergent_filter_fraction_(0) {}
+
+EchoInformation::~EchoInformation() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ ReportAndResetAecDivergentFilterStats();
}
-EchoInformation::~EchoInformation() {}
+void EchoInformation::UpdateAecStats(
+ webrtc::EchoCancellation* echo_cancellation) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!echo_cancellation->is_enabled())
+ return;
+
+ UpdateAecDelayStats(echo_cancellation);
+ UpdateAecDivergentFilterStats(echo_cancellation);
+}
void EchoInformation::UpdateAecDelayStats(
webrtc::EchoCancellation* echo_cancellation) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
// Only start collecting stats if we know echo cancellation has measured an
// echo. Otherwise we clutter the stats with for example cases where only the
// microphone is used.
@@ -311,19 +333,18 @@ void EchoInformation::UpdateAecDelayStats(
return;
echo_frames_received_ = true;
+
// In WebRTC, three echo delay metrics are calculated and updated every
// five seconds. We use one of them, |fraction_poor_delays| to log in a UMA
// histogram an Echo Cancellation quality metric. The stat in WebRTC has a
// fixed aggregation window of five seconds, so we use the same query
// frequency to avoid logging old values.
- const int kNumChunksInFiveSeconds = 500;
- if (!echo_cancellation->is_delay_logging_enabled() ||
- !echo_cancellation->is_enabled()) {
+ if (!echo_cancellation->is_delay_logging_enabled())
return;
- }
- num_chunks_++;
- if (num_chunks_ < kNumChunksInFiveSeconds) {
+ delay_stats_time_ms_ += webrtc::AudioProcessing::kChunkSizeMs;
+ if (delay_stats_time_ms_ <
+ 500 * webrtc::AudioProcessing::kChunkSizeMs) { // 5 seconds
return;
}
@@ -332,7 +353,7 @@ void EchoInformation::UpdateAecDelayStats(
if (echo_cancellation->GetDelayMetrics(
&dummy_median, &dummy_std, &fraction_poor_delays) ==
webrtc::AudioProcessing::kNoError) {
- num_chunks_ = 0;
+ delay_stats_time_ms_ = 0;
// Map |fraction_poor_delays| to an Echo Cancellation quality and log in UMA
// histogram. See DelayBasedEchoQuality for information on histogram
// buckets.
@@ -342,6 +363,53 @@ void EchoInformation::UpdateAecDelayStats(
}
}
+void EchoInformation::UpdateAecDivergentFilterStats(
+ webrtc::EchoCancellation* echo_cancellation) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!echo_cancellation->are_metrics_enabled())
+ return;
+
+ divergent_filter_stats_time_ms_ += webrtc::AudioProcessing::kChunkSizeMs;
+ if (divergent_filter_stats_time_ms_ <
+ 100 * webrtc::AudioProcessing::kChunkSizeMs) { // 1 second
+ return;
+ }
+
+ webrtc::EchoCancellation::Metrics metrics;
+ if (echo_cancellation->GetMetrics(&metrics) ==
+ webrtc::AudioProcessing::kNoError) {
+ // If not yet calculated, |metrics.divergent_filter_fraction| is -1.0. After
+ // being calculated the first time, it is updated periodically.
+ if (metrics.divergent_filter_fraction < 0.0f) {
+ DCHECK_EQ(num_divergent_filter_fraction_, 0);
+ return;
+ }
+ if (metrics.divergent_filter_fraction > 0.0f) {
+ ++num_non_zero_divergent_filter_fraction_;
+ }
+ } else {
+ DLOG(WARNING) << "Get echo cancellation metrics failed.";
+ }
+ ++num_divergent_filter_fraction_;
+ divergent_filter_stats_time_ms_ = 0;
+}
+
+void EchoInformation::ReportAndResetAecDivergentFilterStats() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (num_divergent_filter_fraction_ == 0)
+ return;
+
+ int non_zero_percent = 100 * num_non_zero_divergent_filter_fraction_ /
+ num_divergent_filter_fraction_;
+ UMA_HISTOGRAM_PERCENTAGE("WebRTC.AecFilterHasDivergence", non_zero_percent);
+
+ divergent_filter_stats_time_ms_ = 0;
+ num_non_zero_divergent_filter_fraction_ = 0;
+ num_divergent_filter_fraction_ = 0;
+}
+
void EnableEchoCancellation(AudioProcessing* audio_processing) {
#if defined(OS_ANDROID)
// Mobile devices are using AECM.
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.h b/chromium/content/renderer/media/media_stream_audio_processor_options.h
index 2d5af1d4f41..a0c6a56f4d4 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor_options.h
+++ b/chromium/content/renderer/media/media_stream_audio_processor_options.h
@@ -9,6 +9,7 @@
#include "base/files/file.h"
#include "base/macros.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "content/public/common/media_stream_request.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
@@ -103,14 +104,36 @@ class CONTENT_EXPORT EchoInformation {
EchoInformation();
virtual ~EchoInformation();
- void UpdateAecDelayStats(webrtc::EchoCancellation* echo_cancellation);
+ // Updates stats, and reports delay metrics as UMA stats every 5 seconds.
+ // Must be called every time AudioProcessing::ProcessStream() is called.
+ void UpdateAecStats(webrtc::EchoCancellation* echo_cancellation);
+
+ // Reports AEC divergent filter metrics as UMA and resets the associated data.
+ void ReportAndResetAecDivergentFilterStats();
private:
- // Counter to track 5 seconds of processed 10 ms chunks in order to query a
- // new metric from webrtc::EchoCancellation::GetEchoDelayMetrics().
- int num_chunks_;
+ void UpdateAecDelayStats(webrtc::EchoCancellation* echo_cancellation);
+ void UpdateAecDivergentFilterStats(
+ webrtc::EchoCancellation* echo_cancellation);
+
+ // Counter to track 5 seconds of data in order to query a new metric from
+ // webrtc::EchoCancellation::GetEchoDelayMetrics().
+ int delay_stats_time_ms_;
bool echo_frames_received_;
+ // Counter to track 1 second of data in order to query a new divergent filter
+ // fraction metric from webrtc::EchoCancellation::GetMetrics().
+ int divergent_filter_stats_time_ms_;
+
+ // Total number of times we queried for the divergent filter fraction metric.
+ int num_divergent_filter_fraction_;
+
+ // Number of non-zero divergent filter fraction metrics.
+ int num_non_zero_divergent_filter_fraction_;
+
+ // Ensures that this class is accessed on the same thread.
+ base::ThreadChecker thread_checker_;
+
DISALLOW_COPY_AND_ASSIGN(EchoInformation);
};
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
index 8cf5cccdccf..0b5e138e7cb 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
@@ -208,6 +208,7 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
#define MAYBE_WithAudioProcessing WithAudioProcessing
#endif
TEST_F(MediaStreamAudioProcessorTest, MAYBE_WithAudioProcessing) {
+ base::MessageLoop message_loop;
MockConstraintFactory constraint_factory;
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
@@ -223,9 +224,10 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_WithAudioProcessing) {
kAudioProcessingSampleRate,
kAudioProcessingNumberOfChannel,
kAudioProcessingSampleRate / 100);
- // Set |audio_processor| to NULL to make sure |webrtc_audio_device| outlives
- // |audio_processor|.
- audio_processor = NULL;
+
+ // Stop |audio_processor| so that it removes itself from
+ // |webrtc_audio_device| and clears its pointer to it.
+ audio_processor->Stop();
}
TEST_F(MediaStreamAudioProcessorTest, VerifyTabCaptureWithoutAudioProcessing) {
@@ -259,9 +261,9 @@ TEST_F(MediaStreamAudioProcessorTest, VerifyTabCaptureWithoutAudioProcessing) {
input_device_params_, webrtc_audio_device.get());
EXPECT_FALSE(audio_processor->has_audio_processing());
- // Set |audio_processor| to NULL to make sure |webrtc_audio_device| outlives
- // |audio_processor|.
- audio_processor = NULL;
+ // Stop |audio_processor| so that it removes itself from
+ // |webrtc_audio_device| and clears its pointer to it.
+ audio_processor->Stop();
}
TEST_F(MediaStreamAudioProcessorTest, TurnOffDefaultConstraints) {
@@ -281,9 +283,10 @@ TEST_F(MediaStreamAudioProcessorTest, TurnOffDefaultConstraints) {
params_.sample_rate(),
params_.channels(),
params_.sample_rate() / 100);
- // Set |audio_processor| to NULL to make sure |webrtc_audio_device| outlives
- // |audio_processor|.
- audio_processor = NULL;
+
+ // Stop |audio_processor| so that it removes itself from
+ // |webrtc_audio_device| and clears its pointer to it.
+ audio_processor->Stop();
}
TEST_F(MediaStreamAudioProcessorTest, VerifyConstraints) {
@@ -440,6 +443,7 @@ TEST_F(MediaStreamAudioProcessorTest, SelectsConstraintsArrayGeometryIfExists) {
#define MAYBE_TestAllSampleRates TestAllSampleRates
#endif
TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestAllSampleRates) {
+ base::MessageLoop message_loop;
MockConstraintFactory constraint_factory;
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
@@ -467,9 +471,9 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestAllSampleRates) {
kAudioProcessingSampleRate / 100);
}
- // Set |audio_processor| to NULL to make sure |webrtc_audio_device|
- // outlives |audio_processor|.
- audio_processor = NULL;
+ // Stop |audio_processor| so that it removes itself from
+ // |webrtc_audio_device| and clears its pointer to it.
+ audio_processor->Stop();
}
// Test that if we have an AEC dump message filter created, we are getting it
@@ -491,7 +495,9 @@ TEST_F(MediaStreamAudioProcessorTest, GetAecDumpMessageFilter) {
EXPECT_TRUE(audio_processor->aec_dump_message_filter_.get());
- audio_processor = NULL;
+ // Stop |audio_processor| so that it removes itself from
+ // |webrtc_audio_device| and clears its pointer to it.
+ audio_processor->Stop();
}
TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
@@ -549,9 +555,9 @@ TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
EXPECT_EQ(pushed_capture_delay, capture_delay);
}
- // Set |audio_processor| to NULL to make sure |webrtc_audio_device| outlives
- // |audio_processor|.
- audio_processor = NULL;
+ // Stop |audio_processor| so that it removes itself from
+ // |webrtc_audio_device| and clears its pointer to it.
+ audio_processor->Stop();
}
// Disabled on android clang builds due to crbug.com/470499
@@ -560,8 +566,8 @@ TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
#else
#define MAYBE_TestWithKeyboardMicChannel TestWithKeyboardMicChannel
#endif
-
TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestWithKeyboardMicChannel) {
+ base::MessageLoop message_loop;
MockConstraintFactory constraint_factory;
constraint_factory.basic().googExperimentalNoiseSuppression.setExact(true);
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
@@ -581,9 +587,10 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestWithKeyboardMicChannel) {
kAudioProcessingSampleRate,
kAudioProcessingNumberOfChannel,
kAudioProcessingSampleRate / 100);
- // Set |audio_processor| to NULL to make sure |webrtc_audio_device| outlives
- // |audio_processor|.
- audio_processor = NULL;
+
+ // Stop |audio_processor| so that it removes itself from
+ // |webrtc_audio_device| and clears its pointer to it.
+ audio_processor->Stop();
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_source.cc b/chromium/content/renderer/media/media_stream_audio_source.cc
index 6e99deb54cd..8db50426ebc 100644
--- a/chromium/content/renderer/media/media_stream_audio_source.cc
+++ b/chromium/content/renderer/media/media_stream_audio_source.cc
@@ -58,7 +58,7 @@ bool MediaStreamAudioSource::ConnectToTrack(
// Create and initialize a new MediaStreamAudioTrack and pass ownership of it
// to the WebMediaStreamTrack.
blink::WebMediaStreamTrack mutable_blink_track = blink_track;
- mutable_blink_track.setExtraData(
+ mutable_blink_track.setTrackData(
CreateMediaStreamAudioTrack(blink_track.id().utf8()).release());
// Propagate initial "enabled" state.
diff --git a/chromium/content/renderer/media/media_stream_audio_track.cc b/chromium/content/renderer/media/media_stream_audio_track.cc
index 575c277e8e3..b6ec78e871f 100644
--- a/chromium/content/renderer/media/media_stream_audio_track.cc
+++ b/chromium/content/renderer/media/media_stream_audio_track.cc
@@ -31,7 +31,7 @@ MediaStreamAudioTrack* MediaStreamAudioTrack::From(
track.source().getType() != blink::WebMediaStreamSource::TypeAudio) {
return nullptr;
}
- return static_cast<MediaStreamAudioTrack*>(track.getExtraData());
+ return static_cast<MediaStreamAudioTrack*>(track.getTrackData());
}
void MediaStreamAudioTrack::AddSink(MediaStreamAudioSink* sink) {
@@ -131,4 +131,10 @@ void MediaStreamAudioTrack::OnData(const media::AudioBus& audio_bus,
}
}
+void MediaStreamAudioTrack::getSettings(
+ blink::WebMediaStreamTrack::Settings& settings) {
+ // TODO(hta): Extract the real value.
+ settings.deviceId = blink::WebString("audio device ID");
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_track.h b/chromium/content/renderer/media/media_stream_audio_track.h
index c8c2b8482a8..2e43b42e756 100644
--- a/chromium/content/renderer/media/media_stream_audio_track.h
+++ b/chromium/content/renderer/media/media_stream_audio_track.h
@@ -90,6 +90,8 @@ class CONTENT_EXPORT MediaStreamAudioTrack : public MediaStreamTrack {
// delivered to the sinks instead of the content of |audio_bus|.
void OnData(const media::AudioBus& audio_bus, base::TimeTicks reference_time);
+ void getSettings(blink::WebMediaStreamTrack::Settings& settings) override;
+
private:
// In debug builds, check that all methods that could cause object graph
// or data flow changes are being called on the main thread.
diff --git a/chromium/content/renderer/media/media_stream_audio_unittest.cc b/chromium/content/renderer/media/media_stream_audio_unittest.cc
index 060dca37b07..022bedd37e3 100644
--- a/chromium/content/renderer/media/media_stream_audio_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_audio_unittest.cc
@@ -38,8 +38,11 @@ class FakeMediaStreamAudioSource
public base::PlatformThread::Delegate {
public:
FakeMediaStreamAudioSource()
- : MediaStreamAudioSource(true), stop_event_(true, false),
- next_buffer_size_(kBufferSize), sample_count_(0) {}
+ : MediaStreamAudioSource(true),
+ stop_event_(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ next_buffer_size_(kBufferSize),
+ sample_count_(0) {}
~FakeMediaStreamAudioSource() final {
CHECK(main_thread_checker_.CalledOnValidThread());
diff --git a/chromium/content/renderer/media/media_stream_center.cc b/chromium/content/renderer/media/media_stream_center.cc
index c08fcb56f27..2f5e1a40635 100644
--- a/chromium/content/renderer/media/media_stream_center.cc
+++ b/chromium/content/renderer/media/media_stream_center.cc
@@ -65,7 +65,7 @@ void CreateNativeAudioMediaStreamTrack(
void CreateNativeVideoMediaStreamTrack(
const blink::WebMediaStreamTrack& track) {
- DCHECK(track.getExtraData() == NULL);
+ DCHECK(track.getTrackData() == NULL);
blink::WebMediaStreamSource source = track.source();
DCHECK_EQ(source.getType(), blink::WebMediaStreamSource::TypeVideo);
MediaStreamVideoSource* native_source =
@@ -80,10 +80,9 @@ void CreateNativeVideoMediaStreamTrack(
blink::WebMediaConstraints constraints = source.constraints();
if (constraints.isNull())
constraints.initialize();
- writable_track.setExtraData(
- new MediaStreamVideoTrack(native_source, constraints,
- MediaStreamVideoSource::ConstraintsCallback(),
- track.isEnabled()));
+ writable_track.setTrackData(new MediaStreamVideoTrack(
+ native_source, constraints, MediaStreamVideoSource::ConstraintsCallback(),
+ track.isEnabled()));
}
} // namespace
@@ -97,7 +96,7 @@ MediaStreamCenter::~MediaStreamCenter() {}
void MediaStreamCenter::didCreateMediaStreamTrack(
const blink::WebMediaStreamTrack& track) {
DVLOG(1) << "MediaStreamCenter::didCreateMediaStreamTrack";
- DCHECK(!track.isNull() && !track.getExtraData());
+ DCHECK(!track.isNull() && !track.getTrackData());
DCHECK(!track.source().isNull());
switch (track.source().getType()) {
@@ -139,7 +138,7 @@ MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack(
const blink::WebMediaStreamTrack& track) {
DVLOG(1) << "MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack";
MediaStreamTrack* media_stream_track =
- static_cast<MediaStreamTrack*>(track.getExtraData());
+ static_cast<MediaStreamTrack*>(track.getTrackData());
if (!media_stream_track) {
DLOG(ERROR) << "Native track missing for webaudio source.";
return nullptr;
diff --git a/chromium/content/renderer/media/media_stream_renderer_factory_impl.cc b/chromium/content/renderer/media/media_stream_renderer_factory_impl.cc
index 78cd37500f0..b3d137883b8 100644
--- a/chromium/content/renderer/media/media_stream_renderer_factory_impl.cc
+++ b/chromium/content/renderer/media/media_stream_renderer_factory_impl.cc
@@ -57,17 +57,17 @@ MediaStreamRendererFactoryImpl::MediaStreamRendererFactoryImpl() {
MediaStreamRendererFactoryImpl::~MediaStreamRendererFactoryImpl() {
}
-scoped_refptr<VideoFrameProvider>
-MediaStreamRendererFactoryImpl::GetVideoFrameProvider(
+scoped_refptr<MediaStreamVideoRenderer>
+MediaStreamRendererFactoryImpl::GetVideoRenderer(
const blink::WebMediaStream& web_stream,
const base::Closure& error_cb,
- const VideoFrameProvider::RepaintCB& repaint_cb,
+ const MediaStreamVideoRenderer::RepaintCB& repaint_cb,
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
const scoped_refptr<base::TaskRunner>& worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories) {
DCHECK(!web_stream.isNull());
- DVLOG(1) << "MediaStreamRendererFactoryImpl::GetVideoFrameProvider stream:"
+ DVLOG(1) << "MediaStreamRendererFactoryImpl::GetVideoRenderer stream:"
<< base::UTF16ToUTF8(base::StringPiece16(web_stream.id()));
blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
diff --git a/chromium/content/renderer/media/media_stream_renderer_factory_impl.h b/chromium/content/renderer/media/media_stream_renderer_factory_impl.h
index 33519efe73d..1305e086932 100644
--- a/chromium/content/renderer/media/media_stream_renderer_factory_impl.h
+++ b/chromium/content/renderer/media/media_stream_renderer_factory_impl.h
@@ -15,10 +15,10 @@ class MediaStreamRendererFactoryImpl : public MediaStreamRendererFactory {
MediaStreamRendererFactoryImpl();
~MediaStreamRendererFactoryImpl() override;
- scoped_refptr<VideoFrameProvider> GetVideoFrameProvider(
+ scoped_refptr<MediaStreamVideoRenderer> GetVideoRenderer(
const blink::WebMediaStream& web_stream,
const base::Closure& error_cb,
- const VideoFrameProvider::RepaintCB& repaint_cb,
+ const MediaStreamVideoRenderer::RepaintCB& repaint_cb,
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
const scoped_refptr<base::TaskRunner>& worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories) override;
diff --git a/chromium/content/renderer/media/media_stream_source.cc b/chromium/content/renderer/media/media_stream_source.cc
index d2b4cbf7f9b..23a459dcbfa 100644
--- a/chromium/content/renderer/media/media_stream_source.cc
+++ b/chromium/content/renderer/media/media_stream_source.cc
@@ -15,13 +15,15 @@ MediaStreamSource::MediaStreamSource() {
MediaStreamSource::~MediaStreamSource() {
DCHECK(thread_checker_.CalledOnValidThread());
- RunStopCallbackAndEndStream();
+ DCHECK(stop_callback_.is_null());
}
void MediaStreamSource::StopSource() {
DCHECK(thread_checker_.CalledOnValidThread());
DoStopSource();
- RunStopCallbackAndEndStream();
+ if (!stop_callback_.is_null())
+ base::ResetAndReturn(&stop_callback_).Run(owner());
+ owner().setReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
}
void MediaStreamSource::SetDeviceInfo(const StreamDeviceInfo& device_info) {
@@ -42,12 +44,4 @@ void MediaStreamSource::ResetSourceStoppedCallback() {
stop_callback_.Reset();
}
-void MediaStreamSource::RunStopCallbackAndEndStream() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!stop_callback_.is_null())
- base::ResetAndReturn(&stop_callback_).Run(owner());
- if (!owner().isNull())
- owner().setReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_source.h b/chromium/content/renderer/media/media_stream_source.h
index 7c451564d6f..23b896ae88e 100644
--- a/chromium/content/renderer/media/media_stream_source.h
+++ b/chromium/content/renderer/media/media_stream_source.h
@@ -66,11 +66,6 @@ class CONTENT_EXPORT MediaStreamSource
virtual void DoStopSource() = 0;
private:
- // Called by both StopSource() and the destructor to ensure the
- // |stop_callback_| has been run and the blink::WebMediaStreamSource's ready
- // state has been set to "ended."
- void RunStopCallbackAndEndStream();
-
StreamDeviceInfo device_info_;
SourceStoppedCallback stop_callback_;
diff --git a/chromium/content/renderer/media/media_stream_track.cc b/chromium/content/renderer/media/media_stream_track.cc
index fa0cb90d266..27fff26a874 100644
--- a/chromium/content/renderer/media/media_stream_track.cc
+++ b/chromium/content/renderer/media/media_stream_track.cc
@@ -10,7 +10,7 @@ namespace content {
MediaStreamTrack* MediaStreamTrack::GetTrack(
const blink::WebMediaStreamTrack& track) {
return track.isNull() ? nullptr
- : static_cast<MediaStreamTrack*>(track.getExtraData());
+ : static_cast<MediaStreamTrack*>(track.getTrackData());
}
MediaStreamTrack::MediaStreamTrack(bool is_local_track)
diff --git a/chromium/content/renderer/media/media_stream_track.h b/chromium/content/renderer/media/media_stream_track.h
index 8640f6a8238..c09c5088e1e 100644
--- a/chromium/content/renderer/media/media_stream_track.h
+++ b/chromium/content/renderer/media/media_stream_track.h
@@ -18,7 +18,7 @@ namespace content {
// It is owned by blink::WebMediaStreamTrack as
// blink::WebMediaStreamTrack::ExtraData.
class CONTENT_EXPORT MediaStreamTrack
- : NON_EXPORTED_BASE(public blink::WebMediaStreamTrack::ExtraData) {
+ : NON_EXPORTED_BASE(public blink::WebMediaStreamTrack::TrackData) {
public:
explicit MediaStreamTrack(bool is_local_track);
~MediaStreamTrack() override;
@@ -29,6 +29,9 @@ class CONTENT_EXPORT MediaStreamTrack
virtual void Stop() = 0;
+ // TODO(hta): Make method pure virtual when all tracks have the method.
+ void getSettings(blink::WebMediaStreamTrack::Settings& settings) override {}
+
bool is_local_track() const { return is_local_track_; }
protected:
diff --git a/chromium/content/renderer/media/media_stream_video_capturer_source.h b/chromium/content/renderer/media/media_stream_video_capturer_source.h
index a6013d0fcbb..62301bc27e3 100644
--- a/chromium/content/renderer/media/media_stream_video_capturer_source.h
+++ b/chromium/content/renderer/media/media_stream_video_capturer_source.h
@@ -56,8 +56,7 @@ class CONTENT_EXPORT MediaStreamVideoCapturerSource
const VideoCaptureDeliverFrameCB& frame_callback) override;
void StopSourceImpl() override;
- // RenderFrame does NOT own this object. Avoid unintended multiple destruction
- // by overriding RenderFrameObserver::OnDestruct().
+ // RenderFrameObserver implementation.
void OnDestruct() final {}
// Method to bind as RunningCallback in VideoCapturerSource::StartCapture().
diff --git a/chromium/content/renderer/media/media_stream_video_renderer_sink.cc b/chromium/content/renderer/media/media_stream_video_renderer_sink.cc
index f9ce2df942e..1fe5e6501a2 100644
--- a/chromium/content/renderer/media/media_stream_video_renderer_sink.cc
+++ b/chromium/content/renderer/media/media_stream_video_renderer_sink.cc
@@ -75,7 +75,7 @@ void MediaStreamVideoRendererSink::Stop() {
frame_size_.set_height(kMinFrameSize);
}
-void MediaStreamVideoRendererSink::Play() {
+void MediaStreamVideoRendererSink::Resume() {
DCHECK(task_runner_->BelongsToCurrentThread());
if (state_ == PAUSED)
state_ = STARTED;
diff --git a/chromium/content/renderer/media/media_stream_video_renderer_sink.h b/chromium/content/renderer/media/media_stream_video_renderer_sink.h
index d858062a453..425ca6cc2c2 100644
--- a/chromium/content/renderer/media/media_stream_video_renderer_sink.h
+++ b/chromium/content/renderer/media/media_stream_video_renderer_sink.h
@@ -10,8 +10,8 @@
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/common/media/video_capture.h"
+#include "content/public/renderer/media_stream_video_renderer.h"
#include "content/public/renderer/media_stream_video_sink.h"
-#include "content/public/renderer/video_frame_provider.h"
#include "media/video/gpu_memory_buffer_video_frame_pool.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "ui/gfx/geometry/size.h"
@@ -27,12 +27,12 @@ class GpuVideoAcceleratorFactories;
namespace content {
-// MediaStreamVideoRendererSink is a VideoFrameProvider designed for rendering
-// Video MediaStreamTracks [1], MediaStreamVideoRendererSink implements
-// MediaStreamVideoSink in order to render video frames provided from a
-// MediaStreamVideoTrack, to which it connects itself when the
-// VideoFrameProvider is Start()ed, and disconnects itself when the latter is
-// Stop()ed.
+// MediaStreamVideoRendererSink is a MediaStreamVideoRenderer designed for
+// rendering Video MediaStreamTracks [1], MediaStreamVideoRendererSink
+// implements MediaStreamVideoSink in order to render video frames provided from
+// a MediaStreamVideoTrack, to which it connects itself when the
+// MediaStreamVideoRenderer is Start()ed, and disconnects itself when the latter
+// is Stop()ed.
//
// [1] http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreamtrack
//
@@ -40,22 +40,23 @@ namespace content {
// http://src.chromium.org/viewvc/chrome/trunk/src/content/renderer/media/rtc_vi
// deo_decoder_unittest.cc?revision=180591&view=markup
class CONTENT_EXPORT MediaStreamVideoRendererSink
- : NON_EXPORTED_BASE(public VideoFrameProvider),
+ : NON_EXPORTED_BASE(public MediaStreamVideoRenderer),
NON_EXPORTED_BASE(public MediaStreamVideoSink) {
public:
MediaStreamVideoRendererSink(
const blink::WebMediaStreamTrack& video_track,
const base::Closure& error_cb,
- const RepaintCB& repaint_cb,
+ const MediaStreamVideoRenderer::RepaintCB& repaint_cb,
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
const scoped_refptr<base::TaskRunner>& worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories);
- // VideoFrameProvider implementation. Called on the main thread.
+ // MediaStreamVideoRenderer implementation. Called on the main thread.
void Start() override;
void Stop() override;
- void Play() override;
+ void Resume() override;
void Pause() override;
+
void SetGpuMemoryBufferVideoForTesting(
media::GpuMemoryBufferVideoFramePool* gpu_memory_buffer_pool);
diff --git a/chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc b/chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
index 77edaf85ce1..258b7a7bb39 100644
--- a/chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
@@ -108,7 +108,7 @@ TEST_F(MediaStreamVideoRendererSinkTest, StartStop) {
media_stream_video_renderer_sink_->Pause();
EXPECT_TRUE(IsInPausedState());
- media_stream_video_renderer_sink_->Play(); // Should be called Resume().
+ media_stream_video_renderer_sink_->Resume();
EXPECT_TRUE(IsInStartedState());
media_stream_video_renderer_sink_->Stop();
diff --git a/chromium/content/renderer/media/media_stream_video_source.cc b/chromium/content/renderer/media/media_stream_video_source.cc
index 09ebd0ad76b..ae3df0fa96f 100644
--- a/chromium/content/renderer/media/media_stream_video_source.cc
+++ b/chromium/content/renderer/media/media_stream_video_source.cc
@@ -18,28 +18,6 @@
namespace content {
-// Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b
-const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio";
-const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio";
-const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth";
-const char MediaStreamVideoSource::kMinWidth[] = "minWidth";
-const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight";
-const char MediaStreamVideoSource::kMinHeight[] = "minHeight";
-const char MediaStreamVideoSource::kMaxFrameRate[] = "maxFrameRate";
-const char MediaStreamVideoSource::kMinFrameRate[] = "minFrameRate";
-
-// TODO(mcasas): Find a way to guarantee all constraints are added to the array.
-const char* const kSupportedConstraints[] = {
- MediaStreamVideoSource::kMaxAspectRatio,
- MediaStreamVideoSource::kMinAspectRatio,
- MediaStreamVideoSource::kMaxWidth,
- MediaStreamVideoSource::kMinWidth,
- MediaStreamVideoSource::kMaxHeight,
- MediaStreamVideoSource::kMinHeight,
- MediaStreamVideoSource::kMaxFrameRate,
- MediaStreamVideoSource::kMinFrameRate,
-};
-
namespace {
const char* const kLegalVideoConstraints[] = {
@@ -305,14 +283,6 @@ MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource(
return static_cast<MediaStreamVideoSource*>(source.getExtraData());
}
-// static, deprecated
-bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) {
- return std::find(kSupportedConstraints,
- kSupportedConstraints + arraysize(kSupportedConstraints),
- name) !=
- kSupportedConstraints + arraysize(kSupportedConstraints);
-}
-
MediaStreamVideoSource::MediaStreamVideoSource()
: state_(NEW),
track_adapter_(
diff --git a/chromium/content/renderer/media/media_stream_video_source.h b/chromium/content/renderer/media/media_stream_video_source.h
index 550adea207b..3d79aeafb77 100644
--- a/chromium/content/renderer/media/media_stream_video_source.h
+++ b/chromium/content/renderer/media/media_stream_video_source.h
@@ -47,17 +47,6 @@ class CONTENT_EXPORT MediaStreamVideoSource
: public MediaStreamSource,
NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
- // Constraint keys used by a video source.
- // Specified by draft-alvestrand-constraints-resolution-00b
- static const char kMinAspectRatio[]; // minAspectRatio
- static const char kMaxAspectRatio[]; // maxAspectRatio
- static const char kMaxWidth[]; // maxWidth
- static const char kMinWidth[]; // minWidth
- static const char kMaxHeight[]; // maxHeight
- static const char kMinHeight[]; // minHeight
- static const char kMaxFrameRate[]; // maxFrameRate
- static const char kMinFrameRate[]; // minFrameRate
-
enum {
// Default resolution. If no constraints are specified and the delegate
// support it, this is the resolution that will be used.
@@ -84,9 +73,6 @@ class CONTENT_EXPORT MediaStreamVideoSource
void UpdateCapturingLinkSecure(MediaStreamVideoTrack* track, bool is_secure);
- // Return true if |name| is a constraint supported by MediaStreamVideoSource.
- static bool IsConstraintSupported(const std::string& name);
-
// Request underlying source to capture a new frame.
virtual void RequestRefreshFrame() {}
diff --git a/chromium/content/renderer/media/media_stream_video_source_unittest.cc b/chromium/content/renderer/media/media_stream_video_source_unittest.cc
index 8509243a8ac..64395970c04 100644
--- a/chromium/content/renderer/media/media_stream_video_source_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_video_source_unittest.cc
@@ -681,28 +681,6 @@ TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) {
sink.DisconnectFromTrack();
}
-TEST_F(MediaStreamVideoSourceTest, IsConstraintSupported) {
- EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
- MediaStreamVideoSource::kMaxFrameRate));
- EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
- MediaStreamVideoSource::kMinFrameRate));
- EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
- MediaStreamVideoSource::kMaxWidth));
- EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
- MediaStreamVideoSource::kMinWidth));
- EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
- MediaStreamVideoSource::kMaxHeight));
- EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
- MediaStreamVideoSource::kMinHeight));
- EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
- MediaStreamVideoSource::kMaxAspectRatio));
- EXPECT_TRUE(MediaStreamVideoSource::IsConstraintSupported(
- MediaStreamVideoSource::kMinAspectRatio));
-
- EXPECT_FALSE(MediaStreamVideoSource::IsConstraintSupported(
- "something unsupported"));
-}
-
// Test that the constraint negotiation can handle 0.0 fps as frame rate.
TEST_F(MediaStreamVideoSourceTest, Use0FpsSupportedFormat) {
media::VideoCaptureFormats formats;
diff --git a/chromium/content/renderer/media/media_stream_video_track.cc b/chromium/content/renderer/media/media_stream_video_track.cc
index 74893dcc424..e23b290328d 100644
--- a/chromium/content/renderer/media/media_stream_video_track.cc
+++ b/chromium/content/renderer/media/media_stream_video_track.cc
@@ -202,10 +202,8 @@ blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack(
bool enabled) {
blink::WebMediaStreamTrack track;
track.initialize(source->owner());
- track.setExtraData(new MediaStreamVideoTrack(source,
- constraints,
- callback,
- enabled));
+ track.setTrackData(
+ new MediaStreamVideoTrack(source, constraints, callback, enabled));
return track;
}
@@ -216,7 +214,7 @@ MediaStreamVideoTrack* MediaStreamVideoTrack::GetVideoTrack(
track.source().getType() != blink::WebMediaStreamSource::TypeVideo) {
return nullptr;
}
- return static_cast<MediaStreamVideoTrack*>(track.getExtraData());
+ return static_cast<MediaStreamVideoTrack*>(track.getTrackData());
}
MediaStreamVideoTrack::MediaStreamVideoTrack(
@@ -290,6 +288,20 @@ void MediaStreamVideoTrack::Stop() {
OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded);
}
+void MediaStreamVideoTrack::getSettings(
+ blink::WebMediaStreamTrack::Settings& settings) {
+ if (source_) {
+ const media::VideoCaptureFormat* format = source_->GetCurrentFormat();
+ if (format) {
+ settings.frameRate = format->frame_rate;
+ settings.width = format->frame_size.width();
+ settings.height = format->frame_size.height();
+ }
+ }
+ // TODO(hta): Extract the real value.
+ settings.deviceId = blink::WebString("video device ID");
+}
+
void MediaStreamVideoTrack::OnReadyStateChanged(
blink::WebMediaStreamSource::ReadyState state) {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
diff --git a/chromium/content/renderer/media/media_stream_video_track.h b/chromium/content/renderer/media/media_stream_video_track.h
index e74e3bc2924..436c15f86ac 100644
--- a/chromium/content/renderer/media/media_stream_video_track.h
+++ b/chromium/content/renderer/media/media_stream_video_track.h
@@ -53,6 +53,7 @@ class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
// MediaStreamTrack overrides.
void SetEnabled(bool enabled) override;
void Stop() override;
+ void getSettings(blink::WebMediaStreamTrack::Settings& settings) override;
void OnReadyStateChanged(blink::WebMediaStreamSource::ReadyState state);
diff --git a/chromium/content/renderer/media/midi_dispatcher.cc b/chromium/content/renderer/media/midi_dispatcher.cc
index 65f42a95d44..f870105dee7 100644
--- a/chromium/content/renderer/media/midi_dispatcher.cc
+++ b/chromium/content/renderer/media/midi_dispatcher.cc
@@ -5,10 +5,11 @@
#include "content/renderer/media/midi_dispatcher.h"
#include "base/bind.h"
-#include "content/public/common/service_registry.h"
#include "content/public/renderer/render_frame.h"
+#include "services/shell/public/cpp/interface_provider.h"
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/modules/webmidi/WebMIDIOptions.h"
#include "third_party/WebKit/public/web/modules/webmidi/WebMIDIPermissionRequest.h"
@@ -24,12 +25,14 @@ MidiDispatcher::MidiDispatcher(RenderFrame* render_frame)
MidiDispatcher::~MidiDispatcher() {}
+void MidiDispatcher::OnDestruct() {
+ delete this;
+}
+
void MidiDispatcher::requestPermission(const WebMIDIPermissionRequest& request,
const WebMIDIOptions& options) {
- if (!permission_service_.get()) {
- render_frame()->GetServiceRegistry()->ConnectToRemoteService(
- mojo::GetProxy(&permission_service_));
- }
+ if (!permission_service_.get())
+ render_frame()->GetRemoteInterfaces()->GetInterface(&permission_service_);
int permission_request_id =
requests_.Add(new WebMIDIPermissionRequest(request));
@@ -41,6 +44,7 @@ void MidiDispatcher::requestPermission(const WebMIDIPermissionRequest& request,
permission_service_->RequestPermission(
permission_name, request.getSecurityOrigin().toString().utf8(),
+ blink::WebUserGestureIndicator::isProcessingUserGesture(),
base::Bind(&MidiDispatcher::OnPermissionSet, base::Unretained(this),
permission_request_id));
}
diff --git a/chromium/content/renderer/media/midi_dispatcher.h b/chromium/content/renderer/media/midi_dispatcher.h
index 802328a770c..2d98117d092 100644
--- a/chromium/content/renderer/media/midi_dispatcher.h
+++ b/chromium/content/renderer/media/midi_dispatcher.h
@@ -28,6 +28,9 @@ class MidiDispatcher : public RenderFrameObserver,
~MidiDispatcher() override;
private:
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
// blink::WebMIDIClient implementation.
void requestPermission(const blink::WebMIDIPermissionRequest& request,
const blink::WebMIDIOptions& options) override;
diff --git a/chromium/content/renderer/media/mock_media_stream_registry.cc b/chromium/content/renderer/media/mock_media_stream_registry.cc
index bad1ae790c6..91fb227ecf1 100644
--- a/chromium/content/renderer/media/mock_media_stream_registry.cc
+++ b/chromium/content/renderer/media/mock_media_stream_registry.cc
@@ -72,7 +72,7 @@ void MockMediaStreamRegistry::AddVideoTrack(const std::string& track_id) {
MediaStreamVideoTrack* native_track = new MediaStreamVideoTrack(
native_source, constraints, MediaStreamVideoSource::ConstraintsCallback(),
true /* enabled */);
- blink_track.setExtraData(native_track);
+ blink_track.setTrackData(native_track);
test_stream_.addTrack(blink_track);
}
diff --git a/chromium/content/renderer/media/peer_connection_identity_store.h b/chromium/content/renderer/media/peer_connection_identity_store.h
index cdd0ec29836..3172a2cabf4 100644
--- a/chromium/content/renderer/media/peer_connection_identity_store.h
+++ b/chromium/content/renderer/media/peer_connection_identity_store.h
@@ -16,6 +16,8 @@ namespace content {
// This class is associated with a peer connection and handles WebRTC DTLS
// identity requests by delegating to the per-renderer WebRTCIdentityProxy.
+// TODO(hbos): Remove this store, it is no longer used.
+// See bugs.webrtc.org/5707, bugs.webrtc.org/5708.
class PeerConnectionIdentityStore
: public webrtc::DtlsIdentityStoreInterface {
public:
diff --git a/chromium/content/renderer/media/pepper_to_video_track_adapter.cc b/chromium/content/renderer/media/pepper_to_video_track_adapter.cc
index f1dfa51f6fe..afd3b20be0f 100644
--- a/chromium/content/renderer/media/pepper_to_video_track_adapter.cc
+++ b/chromium/content/renderer/media/pepper_to_video_track_adapter.cc
@@ -209,7 +209,7 @@ class PpFrameWriterProxy : public FrameWriterInterface {
public:
explicit PpFrameWriterProxy(const base::WeakPtr<PpFrameWriter>& writer)
: writer_(writer) {
- DCHECK(writer_ != NULL);
+ DCHECK(writer_);
}
~PpFrameWriterProxy() override {}
diff --git a/chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc b/chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc
index 0c13cb6fff7..da0d50cb975 100644
--- a/chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc
+++ b/chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc
@@ -98,7 +98,7 @@ TEST_F(PepperToVideoTrackAdapterTest, PutFrame) {
// PostTaskAndReply to the IO thread and expects the reply to process
// on the main render thread to clean up its resources. However, the
// QuitClosure above ends before that.
- base::MessageLoop::current()->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
EXPECT_EQ(1, sink.number_of_frames());
native_track->RemoveSink(&sink);
diff --git a/chromium/content/renderer/media/remote_media_stream_impl.cc b/chromium/content/renderer/media/remote_media_stream_impl.cc
index 5f449c03821..8dca0e663cd 100644
--- a/chromium/content/renderer/media/remote_media_stream_impl.cc
+++ b/chromium/content/renderer/media/remote_media_stream_impl.cc
@@ -167,7 +167,7 @@ class RemoteVideoTrackAdapter
MediaStreamVideoTrack* media_stream_track =
new MediaStreamVideoTrack(video_source.release(), constraints,
MediaStreamVideoSource::ConstraintsCallback(), enabled);
- webkit_track()->setExtraData(media_stream_track);
+ webkit_track()->setTrackData(media_stream_track);
}
};
diff --git a/chromium/content/renderer/media/render_media_log.cc b/chromium/content/renderer/media/render_media_log.cc
index bcc3301aa35..25defe5c466 100644
--- a/chromium/content/renderer/media/render_media_log.cc
+++ b/chromium/content/renderer/media/render_media_log.cc
@@ -13,6 +13,8 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "content/common/view_messages.h"
+#include "content/public/common/content_client.h"
+#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_thread.h"
namespace {
@@ -34,8 +36,9 @@ void Log(media::MediaLogEvent* event) {
namespace content {
-RenderMediaLog::RenderMediaLog()
- : task_runner_(base::ThreadTaskRunnerHandle::Get()),
+RenderMediaLog::RenderMediaLog(const GURL& security_origin)
+ : security_origin_(security_origin),
+ task_runner_(base::ThreadTaskRunnerHandle::Get()),
tick_clock_(new base::DefaultTickClock()),
last_ipc_send_time_(tick_clock_->NowTicks()),
ipc_send_pending_(false) {
@@ -118,6 +121,17 @@ std::string RenderMediaLog::GetLastErrorMessage() {
return result.str();
}
+void RenderMediaLog::RecordRapporWithSecurityOrigin(const std::string& metric) {
+ if (!task_runner_->BelongsToCurrentThread()) {
+ task_runner_->PostTask(
+ FROM_HERE, base::Bind(&RenderMediaLog::RecordRapporWithSecurityOrigin,
+ this, metric));
+ return;
+ }
+
+ GetContentClient()->renderer()->RecordRapporURL(metric, security_origin_);
+}
+
void RenderMediaLog::SendQueuedMediaEvents() {
DCHECK(task_runner_->BelongsToCurrentThread());
diff --git a/chromium/content/renderer/media/render_media_log.h b/chromium/content/renderer/media/render_media_log.h
index 3606b98e928..e9b655aed4b 100644
--- a/chromium/content/renderer/media/render_media_log.h
+++ b/chromium/content/renderer/media/render_media_log.h
@@ -13,6 +13,7 @@
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "media/base/media_log.h"
+#include "url/gurl.h"
namespace base {
class TickClock;
@@ -32,11 +33,12 @@ namespace content {
// It must be constructed on the render thread.
class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
public:
- RenderMediaLog();
+ explicit RenderMediaLog(const GURL& security_origin);
// MediaLog implementation.
void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override;
std::string GetLastErrorMessage() override;
+ void RecordRapporWithSecurityOrigin(const std::string& metric) override;
// Will reset |last_ipc_send_time_| with the value of NowTicks().
void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock);
@@ -50,6 +52,9 @@ class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
// frequency.
void SendQueuedMediaEvents();
+ // Security origin of the current frame.
+ const GURL security_origin_;
+
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// |lock_| protects access to all of the following member variables. It
diff --git a/chromium/content/renderer/media/render_media_log_unittest.cc b/chromium/content/renderer/media/render_media_log_unittest.cc
index 131da078c19..c383dcd86a1 100644
--- a/chromium/content/renderer/media/render_media_log_unittest.cc
+++ b/chromium/content/renderer/media/render_media_log_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 <tuple>
+
#include "base/macros.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/test_mock_time_task_runner.h"
@@ -15,7 +17,7 @@ namespace content {
class RenderMediaLogTest : public testing::Test {
public:
RenderMediaLogTest()
- : log_(new RenderMediaLog()),
+ : log_(new RenderMediaLog(GURL("http://foo.com"))),
tick_clock_(new base::SimpleTestTickClock()),
task_runner_(new base::TestMockTimeTaskRunner()) {
log_->SetTickClockForTesting(std::unique_ptr<base::TickClock>(tick_clock_));
@@ -47,9 +49,9 @@ class RenderMediaLogTest : public testing::Test {
return std::vector<media::MediaLogEvent>();
}
- base::Tuple<std::vector<media::MediaLogEvent>> events;
+ std::tuple<std::vector<media::MediaLogEvent>> events;
ViewHostMsg_MediaLogEvents::Read(msg, &events);
- return base::get<0>(events);
+ return std::get<0>(events);
}
private:
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
index a9fba3b4e21..7f648538c69 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -72,7 +72,7 @@ void RendererWebAudioDeviceImpl::start() {
RenderFrame* const render_frame =
web_frame ? RenderFrame::FromWebFrame(web_frame) : NULL;
sink_ = AudioDeviceFactory::NewAudioRendererSink(
- AudioDeviceFactory::kSourceWebAudio,
+ AudioDeviceFactory::kSourceWebAudioInteractive,
render_frame ? render_frame->GetRoutingID() : MSG_ROUTING_NONE,
session_id_, std::string(), security_origin_);
sink_->Initialize(params_, this);
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
index 57a25e69958..f3b8125aa29 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -174,4 +174,8 @@ void RendererWebMediaPlayerDelegate::CleanupIdleDelegates() {
idle_cleanup_timer_.Stop();
}
+void RendererWebMediaPlayerDelegate::OnDestruct() {
+ delete this;
+}
+
} // namespace media
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
index b12a58f971d..0e8307744c1 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
@@ -53,6 +53,7 @@ class CONTENT_EXPORT RendererWebMediaPlayerDelegate
void WasHidden() override;
void WasShown() override;
bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnDestruct() override;
// Zeros out |idle_cleanup_interval_|, and sets |idle_timeout_| to
// |idle_timeout|. A zero cleanup interval will cause the idle timer to run
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
index 4872ec891cd..4fe4fdb4525 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
@@ -2,11 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <tuple>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/location.h"
#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
#include "base/test/simple_test_tick_clock.h"
-#include "base/tuple.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/common/media/media_player_delegate_messages.h"
#include "content/public/renderer/render_view.h"
#include "content/public/test/render_view_test.h"
@@ -78,13 +82,13 @@ TEST_F(RendererWebMediaPlayerDelegateTest, SendsMessagesCorrectly) {
MediaPlayerDelegateHostMsg_OnMediaPlaying::ID);
ASSERT_TRUE(msg);
- base::Tuple<int, bool, bool, bool, base::TimeDelta> result;
+ std::tuple<int, bool, bool, bool, base::TimeDelta> result;
ASSERT_TRUE(MediaPlayerDelegateHostMsg_OnMediaPlaying::Read(msg, &result));
- EXPECT_EQ(delegate_id, base::get<0>(result));
- EXPECT_EQ(kHasVideo, base::get<1>(result));
- EXPECT_EQ(kHasAudio, base::get<2>(result));
- EXPECT_EQ(kIsRemote, base::get<3>(result));
- EXPECT_EQ(kDuration, base::get<4>(result));
+ EXPECT_EQ(delegate_id, std::get<0>(result));
+ EXPECT_EQ(kHasVideo, std::get<1>(result));
+ EXPECT_EQ(kHasAudio, std::get<2>(result));
+ EXPECT_EQ(kIsRemote, std::get<3>(result));
+ EXPECT_EQ(kDuration, std::get<4>(result));
}
// Verify the paused message.
@@ -97,10 +101,10 @@ TEST_F(RendererWebMediaPlayerDelegateTest, SendsMessagesCorrectly) {
MediaPlayerDelegateHostMsg_OnMediaPaused::ID);
ASSERT_TRUE(msg);
- base::Tuple<int, bool> result;
+ std::tuple<int, bool> result;
ASSERT_TRUE(MediaPlayerDelegateHostMsg_OnMediaPaused::Read(msg, &result));
- EXPECT_EQ(delegate_id, base::get<0>(result));
- EXPECT_EQ(kReachedEndOfStream, base::get<1>(result));
+ EXPECT_EQ(delegate_id, std::get<0>(result));
+ EXPECT_EQ(kReachedEndOfStream, std::get<1>(result));
}
// Verify the destruction message.
@@ -111,10 +115,10 @@ TEST_F(RendererWebMediaPlayerDelegateTest, SendsMessagesCorrectly) {
MediaPlayerDelegateHostMsg_OnMediaDestroyed::ID);
ASSERT_TRUE(msg);
- base::Tuple<int> result;
+ std::tuple<int> result;
ASSERT_TRUE(
MediaPlayerDelegateHostMsg_OnMediaDestroyed::Read(msg, &result));
- EXPECT_EQ(delegate_id, base::get<0>(result));
+ EXPECT_EQ(delegate_id, std::get<0>(result));
}
delegate_manager_->RemoveObserver(delegate_id);
@@ -184,7 +188,8 @@ TEST_F(RendererWebMediaPlayerDelegateTest, IdleDelegatesAreSuspended) {
&RendererWebMediaPlayerDelegate::PlayerGone,
base::Unretained(delegate_manager_.get()), delegate_id_2)));
base::RunLoop run_loop;
- base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
tick_clock.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1));
run_loop.Run();
}
@@ -203,7 +208,8 @@ TEST_F(RendererWebMediaPlayerDelegateTest, IdleDelegatesAreSuspended) {
EXPECT_CALL(observer_1, OnSuspendRequested(false))
.Times(testing::AtLeast(1));
base::RunLoop run_loop;
- base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
tick_clock.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1));
run_loop.Run();
}
@@ -222,7 +228,8 @@ TEST_F(RendererWebMediaPlayerDelegateTest, IdleDelegatesAreSuspended) {
&RendererWebMediaPlayerDelegate::PlayerGone,
base::Unretained(delegate_manager_.get()), delegate_id_1)));
base::RunLoop run_loop;
- base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
tick_clock.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1));
run_loop.Run();
}
@@ -253,7 +260,8 @@ TEST_F(RendererWebMediaPlayerDelegateTest, IdleDelegatesIgnoresSuspendRequest) {
// Wait for the suspend request, but don't call PlayerGone().
EXPECT_CALL(observer_1, OnSuspendRequested(false));
base::RunLoop run_loop;
- base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
tick_clock.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1));
run_loop.Run();
diff --git a/chromium/content/renderer/media/rtc_certificate_generator.cc b/chromium/content/renderer/media/rtc_certificate_generator.cc
index 94b94fb1c89..94626e50063 100644
--- a/chromium/content/renderer/media/rtc_certificate_generator.cc
+++ b/chromium/content/renderer/media/rtc_certificate_generator.cc
@@ -9,11 +9,13 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "content/renderer/media/peer_connection_identity_store.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
#include "content/renderer/media/rtc_certificate.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/render_thread_impl.h"
#include "third_party/webrtc/base/rtccertificate.h"
+#include "third_party/webrtc/base/rtccertificategenerator.h"
#include "third_party/webrtc/base/scoped_ref_ptr.h"
#include "url/gurl.h"
@@ -35,158 +37,109 @@ rtc::KeyParams WebRTCKeyParamsToKeyParams(
}
}
-// Observer used by RTCCertificateGenerator::generateCertificate.
-class RTCCertificateIdentityObserver
- : public webrtc::DtlsIdentityRequestObserver {
+// A certificate generation request spawned by
+// |RTCCertificateGenerator::generateCertificateWithOptionalExpiration|. This
+// is handled by a separate class so that reference counting can keep the
+// request alive independently of the |RTCCertificateGenerator| that spawned it.
+class RTCCertificateGeneratorRequest
+ : public base::RefCountedThreadSafe<RTCCertificateGeneratorRequest> {
public:
- RTCCertificateIdentityObserver(
+ RTCCertificateGeneratorRequest(
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
- const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread)
+ const scoped_refptr<base::SingleThreadTaskRunner>& worker_thread)
: main_thread_(main_thread),
- signaling_thread_(signaling_thread),
- observer_(nullptr) {
+ worker_thread_(worker_thread) {
DCHECK(main_thread_);
- DCHECK(signaling_thread_);
+ DCHECK(worker_thread_);
}
- ~RTCCertificateIdentityObserver() override {}
- // Perform |store|->RequestIdentity with this identity observer and ensure
- // that this identity observer is not deleted until the request has completed
- // by holding on to a reference to itself for the duration of the request.
- void RequestIdentity(
+ void GenerateCertificateAsync(
const blink::WebRTCKeyParams& key_params,
- const GURL& url,
- const GURL& first_party_for_cookies,
const rtc::Optional<uint64_t>& expires_ms,
std::unique_ptr<blink::WebRTCCertificateCallback> observer) {
DCHECK(main_thread_->BelongsToCurrentThread());
- DCHECK(!observer_) << "Already have a RequestIdentity in progress.";
- key_params_ = key_params;
- observer_ = std::move(observer);
- DCHECK(observer_);
- // Identity request must be performed on the WebRTC signaling thread.
- signaling_thread_->PostTask(FROM_HERE, base::Bind(
- &RTCCertificateIdentityObserver::RequestIdentityOnWebRtcSignalingThread,
- this, url, first_party_for_cookies, expires_ms));
+ DCHECK(observer);
+ worker_thread_->PostTask(FROM_HERE, base::Bind(
+ &RTCCertificateGeneratorRequest::GenerateCertificateOnWorkerThread,
+ this,
+ key_params,
+ expires_ms,
+ base::Passed(std::move(observer))));
}
private:
- void RequestIdentityOnWebRtcSignalingThread(
- GURL url,
- GURL first_party_for_cookies,
- rtc::Optional<uint64_t> expires_ms) {
- DCHECK(signaling_thread_->BelongsToCurrentThread());
- std::unique_ptr<PeerConnectionIdentityStore> store(
- new PeerConnectionIdentityStore(main_thread_, signaling_thread_, url,
- first_party_for_cookies));
- // Request identity with |this| as the observer. OnSuccess/OnFailure will be
- // called asynchronously.
- store->RequestIdentity(WebRTCKeyParamsToKeyParams(key_params_),
- expires_ms, this);
- }
+ friend class base::RefCountedThreadSafe<RTCCertificateGeneratorRequest>;
+ ~RTCCertificateGeneratorRequest() {}
+
+ void GenerateCertificateOnWorkerThread(
+ const blink::WebRTCKeyParams key_params,
+ const rtc::Optional<uint64_t> expires_ms,
+ std::unique_ptr<blink::WebRTCCertificateCallback> observer) {
+ DCHECK(worker_thread_->BelongsToCurrentThread());
- // webrtc::DtlsIdentityRequestObserver implementation.
- void OnFailure(int error) override {
- DCHECK(signaling_thread_->BelongsToCurrentThread());
- DCHECK(observer_);
- main_thread_->PostTask(FROM_HERE, base::Bind(
- &RTCCertificateIdentityObserver::DoCallbackOnMainThread,
- this, nullptr));
- }
- void OnSuccess(const std::string& der_cert,
- const std::string& der_private_key) override {
- std::string pem_cert = rtc::SSLIdentity::DerToPem(
- rtc::kPemTypeCertificate,
- reinterpret_cast<const unsigned char*>(der_cert.data()),
- der_cert.length());
- std::string pem_key = rtc::SSLIdentity::DerToPem(
- rtc::kPemTypeRsaPrivateKey,
- reinterpret_cast<const unsigned char*>(der_private_key.data()),
- der_private_key.length());
- OnSuccess(std::unique_ptr<rtc::SSLIdentity>(
- rtc::SSLIdentity::FromPEMStrings(pem_key, pem_cert)));
- }
- void OnSuccess(std::unique_ptr<rtc::SSLIdentity> identity) override {
- DCHECK(signaling_thread_->BelongsToCurrentThread());
- DCHECK(observer_);
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
- rtc::RTCCertificate::Create(std::move(identity));
- main_thread_->PostTask(
- FROM_HERE,
- base::Bind(&RTCCertificateIdentityObserver::DoCallbackOnMainThread,
- this, base::Passed(base::WrapUnique(
- new RTCCertificate(certificate)))));
+ rtc::RTCCertificateGenerator::GenerateCertificate(
+ WebRTCKeyParamsToKeyParams(key_params), expires_ms);
+
+ main_thread_->PostTask(FROM_HERE, base::Bind(
+ &RTCCertificateGeneratorRequest::DoCallbackOnMainThread,
+ this,
+ base::Passed(std::move(observer)),
+ base::Passed(base::WrapUnique(new RTCCertificate(certificate)))));
}
void DoCallbackOnMainThread(
+ std::unique_ptr<blink::WebRTCCertificateCallback> observer,
std::unique_ptr<blink::WebRTCCertificate> certificate) {
DCHECK(main_thread_->BelongsToCurrentThread());
- DCHECK(observer_);
+ DCHECK(observer);
if (certificate)
- observer_->onSuccess(std::move(certificate));
+ observer->onSuccess(std::move(certificate));
else
- observer_->onError();
- observer_.reset();
+ observer->onError();
}
// The main thread is the renderer thread.
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
- // The signaling thread is a WebRTC thread used to invoke
- // PeerConnectionIdentityStore::RequestIdentity on, as is required.
- const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
- blink::WebRTCKeyParams key_params_;
- std::unique_ptr<blink::WebRTCCertificateCallback> observer_;
-
- DISALLOW_COPY_AND_ASSIGN(RTCCertificateIdentityObserver);
+ // The WebRTC worker thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> worker_thread_;
};
} // namespace
void RTCCertificateGenerator::generateCertificate(
const blink::WebRTCKeyParams& key_params,
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies,
std::unique_ptr<blink::WebRTCCertificateCallback> observer) {
generateCertificateWithOptionalExpiration(
- key_params, url, first_party_for_cookies, rtc::Optional<uint64_t>(),
- std::move(observer));
+ key_params, rtc::Optional<uint64_t>(), std::move(observer));
}
void RTCCertificateGenerator::generateCertificateWithExpiration(
const blink::WebRTCKeyParams& key_params,
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies,
uint64_t expires_ms,
std::unique_ptr<blink::WebRTCCertificateCallback> observer) {
generateCertificateWithOptionalExpiration(
- key_params, url, first_party_for_cookies,
- rtc::Optional<uint64_t>(expires_ms), std::move(observer));
+ key_params, rtc::Optional<uint64_t>(expires_ms), std::move(observer));
}
void RTCCertificateGenerator::generateCertificateWithOptionalExpiration(
const blink::WebRTCKeyParams& key_params,
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies,
const rtc::Optional<uint64_t>& expires_ms,
std::unique_ptr<blink::WebRTCCertificateCallback> observer) {
DCHECK(isSupportedKeyParams(key_params));
-
#if defined(ENABLE_WEBRTC)
const scoped_refptr<base::SingleThreadTaskRunner> main_thread =
base::ThreadTaskRunnerHandle::Get();
-
PeerConnectionDependencyFactory* pc_dependency_factory =
RenderThreadImpl::current()->GetPeerConnectionDependencyFactory();
pc_dependency_factory->EnsureInitialized();
- const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread =
- pc_dependency_factory->GetWebRtcSignalingThread();
-
- rtc::scoped_refptr<RTCCertificateIdentityObserver> identity_observer(
- new rtc::RefCountedObject<RTCCertificateIdentityObserver>(
- main_thread, signaling_thread));
- // |identity_observer| lives until request has completed.
- identity_observer->RequestIdentity(key_params, url, first_party_for_cookies,
- expires_ms, std::move(observer));
+
+ scoped_refptr<RTCCertificateGeneratorRequest> request =
+ new RTCCertificateGeneratorRequest(
+ main_thread,
+ pc_dependency_factory->GetWebRtcWorkerThread());
+ request->GenerateCertificateAsync(
+ key_params, expires_ms, std::move(observer));
#else
observer->onError();
#endif
diff --git a/chromium/content/renderer/media/rtc_certificate_generator.h b/chromium/content/renderer/media/rtc_certificate_generator.h
index 3858db265cc..38811e5ef95 100644
--- a/chromium/content/renderer/media/rtc_certificate_generator.h
+++ b/chromium/content/renderer/media/rtc_certificate_generator.h
@@ -24,13 +24,9 @@ class RTCCertificateGenerator : public blink::WebRTCCertificateGenerator {
// blink::WebRTCCertificateGenerator implementation.
void generateCertificate(
const blink::WebRTCKeyParams& key_params,
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies,
std::unique_ptr<blink::WebRTCCertificateCallback> observer) override;
void generateCertificateWithExpiration(
const blink::WebRTCKeyParams& key_params,
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies,
uint64_t expires_ms,
std::unique_ptr<blink::WebRTCCertificateCallback> observer) override;
bool isSupportedKeyParams(const blink::WebRTCKeyParams& key_params) override;
@@ -41,8 +37,6 @@ class RTCCertificateGenerator : public blink::WebRTCCertificateGenerator {
private:
void generateCertificateWithOptionalExpiration(
const blink::WebRTCKeyParams& key_params,
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies,
const rtc::Optional<uint64_t>& expires_ms,
std::unique_ptr<blink::WebRTCCertificateCallback> observer);
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.cc b/chromium/content/renderer/media/rtc_peer_connection_handler.cc
index e273e5113a9..361948cde06 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler.cc
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler.cc
@@ -722,21 +722,6 @@ void ConvertConstraintsToWebrtcOfferOptions(
base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
-void OverrideDefaultCertificateBasedOnExperiment(
- webrtc::PeerConnectionInterface::RTCConfiguration* config) {
- if (base::FeatureList::IsEnabled(features::kWebRtcEcdsaDefault)) {
- if (config->certificates.empty()) {
- rtc::scoped_refptr<rtc::RTCCertificate> certificate =
- PeerConnectionDependencyFactory::GenerateDefaultCertificate();
- config->certificates.push_back(certificate);
- }
- }
- // If the ECDSA experiment is not running we rely on the default being RSA for
- // the control group. See bug related to this: crbug.com/611698.
- static_assert(rtc::KT_DEFAULT == rtc::KT_RSA, "This code relies on "
- "KT_DEFAULT == KT_RSA for RSA certificate generation.");
-}
-
} // namespace
// Implementation of LocalRTCStatsRequest.
@@ -811,7 +796,7 @@ class RTCPeerConnectionHandler::Observer
}
}
- void OnAddStream(MediaStreamInterface* stream) override {
+ void OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) override {
DCHECK(stream);
std::unique_ptr<RemoteMediaStreamImpl> remote_stream(
new RemoteMediaStreamImpl(main_thread_, stream));
@@ -824,13 +809,16 @@ class RTCPeerConnectionHandler::Observer
this, base::Passed(&remote_stream)));
}
- void OnRemoveStream(MediaStreamInterface* stream) override {
- main_thread_->PostTask(FROM_HERE,
+ void OnRemoveStream(
+ rtc::scoped_refptr<MediaStreamInterface> stream) override {
+ main_thread_->PostTask(
+ FROM_HERE,
base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl,
- this, make_scoped_refptr(stream)));
+ this, make_scoped_refptr(stream.get())));
}
- void OnDataChannel(DataChannelInterface* data_channel) override {
+ void OnDataChannel(
+ rtc::scoped_refptr<DataChannelInterface> data_channel) override {
std::unique_ptr<RtcDataChannelHandler> handler(
new RtcDataChannelHandler(main_thread_, data_channel));
main_thread_->PostTask(FROM_HERE,
@@ -967,7 +955,6 @@ bool RTCPeerConnectionHandler::initialize(
webrtc::PeerConnectionInterface::RTCConfiguration config;
GetNativeRtcConfiguration(server_configuration, &config);
- OverrideDefaultCertificateBasedOnExperiment(&config);
// Choose between RTC smoothness algorithm and prerenderer smoothing.
// Prerenderer smoothing is turned on if RTC smoothness is turned off.
@@ -1004,7 +991,6 @@ bool RTCPeerConnectionHandler::InitializeForTest(
DCHECK(thread_checker_.CalledOnValidThread());
webrtc::PeerConnectionInterface::RTCConfiguration config;
GetNativeRtcConfiguration(server_configuration, &config);
- OverrideDefaultCertificateBasedOnExperiment(&config);
peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
CopyConstraintsIntoRtcConfiguration(options, &config);
@@ -1270,6 +1256,12 @@ bool RTCPeerConnectionHandler::updateICE(
return native_peer_connection_->UpdateIce(config.servers);
}
+void RTCPeerConnectionHandler::logSelectedRtcpMuxPolicy(
+ blink::RtcpMuxPolicy selectedRtcpMuxPolicy) {
+ UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.SelectedRtcpMuxPolicy",
+ selectedRtcpMuxPolicy, blink::RtcpMuxPolicyMax);
+}
+
bool RTCPeerConnectionHandler::addICECandidate(
const blink::WebRTCVoidRequest& request,
const blink::WebRTCICECandidate& candidate) {
@@ -1779,7 +1771,8 @@ void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
TRACE_EVENT0("webrtc", trace_event_name);
closure.Run();
} else {
- base::WaitableEvent event(false, false);
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
thread->PostTask(FROM_HERE,
base::Bind(&RunSynchronousClosure, closure,
base::Unretained(trace_event_name),
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.h b/chromium/content/renderer/media/rtc_peer_connection_handler.h
index 7fe3bf259b7..04941df562c 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler.h
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler.h
@@ -135,6 +135,8 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
bool updateICE(
const blink::WebRTCConfiguration& server_configuration) override;
+ void logSelectedRtcpMuxPolicy(
+ blink::RtcpMuxPolicy selectedRtcpMuxPolicy) override;
bool addICECandidate(const blink::WebRTCICECandidate& candidate) override;
bool addICECandidate(const blink::WebRTCVoidRequest& request,
const blink::WebRTCICECandidate& candidate) override;
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
index cd65ee7bca9..1032489c621 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -305,19 +305,19 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
// Creates a remote MediaStream and adds it to the mocked native
// peer connection.
- scoped_refptr<webrtc::MediaStreamInterface>
- AddRemoteMockMediaStream(const std::string& stream_label,
- const std::string& video_track_label,
- const std::string& audio_track_label) {
- scoped_refptr<webrtc::MediaStreamInterface> stream(
- mock_dependency_factory_->CreateLocalMediaStream(stream_label));
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> AddRemoteMockMediaStream(
+ const std::string& stream_label,
+ const std::string& video_track_label,
+ const std::string& audio_track_label) {
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
+ mock_dependency_factory_->CreateLocalMediaStream(stream_label).get());
if (!video_track_label.empty()) {
stream->AddTrack(MockWebRtcVideoTrack::Create(video_track_label).get());
}
if (!audio_track_label.empty()) {
stream->AddTrack(MockWebRtcAudioTrack::Create(audio_track_label).get());
}
- mock_peer_connection_->AddRemoteStream(stream.get());
+ mock_peer_connection_->AddRemoteStream(stream);
return stream;
}
@@ -376,18 +376,18 @@ TEST_F(RTCPeerConnectionHandlerTest, NoCallbacksToClientAfterStop) {
EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(_)).Times(0);
std::string remote_stream_label("remote_stream");
- scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
- pc_handler_->observer()->OnAddStream(remote_stream.get());
+ pc_handler_->observer()->OnAddStream(remote_stream);
EXPECT_CALL(*mock_client_.get(), didRemoveRemoteStream(_)).Times(0);
- pc_handler_->observer()->OnRemoveStream(remote_stream.get());
+ pc_handler_->observer()->OnRemoveStream(remote_stream);
EXPECT_CALL(*mock_client_.get(), didAddRemoteDataChannel(_)).Times(0);
webrtc::DataChannelInit config;
- scoped_refptr<webrtc::DataChannelInterface> remote_data_channel(
+ rtc::scoped_refptr<webrtc::DataChannelInterface> remote_data_channel(
new rtc::RefCountedObject<MockDataChannel>("dummy", &config));
- pc_handler_->observer()->OnDataChannel(remote_data_channel.get());
+ pc_handler_->observer()->OnDataChannel(remote_data_channel);
base::RunLoop().RunUntilIdle();
}
@@ -599,9 +599,9 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithLocalSelector) {
}
TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithRemoteSelector) {
- scoped_refptr<webrtc::MediaStreamInterface> stream(
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
AddRemoteMockMediaStream("remote_stream", "video", "audio"));
- pc_handler_->observer()->OnAddStream(stream.get());
+ pc_handler_->observer()->OnAddStream(stream);
base::RunLoop().RunUntilIdle();
const blink::WebMediaStream& remote_stream = mock_client_->remote_stream();
@@ -781,7 +781,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceGatheringChange) {
TEST_F(RTCPeerConnectionHandlerTest, OnAddAndOnRemoveStream) {
std::string remote_stream_label("remote_stream");
- scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
testing::InSequence sequence;
@@ -803,23 +803,23 @@ TEST_F(RTCPeerConnectionHandlerTest, OnAddAndOnRemoveStream) {
testing::Property(&blink::WebMediaStream::id,
base::UTF8ToUTF16(remote_stream_label))));
- pc_handler_->observer()->OnAddStream(remote_stream.get());
+ pc_handler_->observer()->OnAddStream(remote_stream);
base::RunLoop().RunUntilIdle();
- pc_handler_->observer()->OnRemoveStream(remote_stream.get());
+ pc_handler_->observer()->OnRemoveStream(remote_stream);
base::RunLoop().RunUntilIdle();
}
// This test that WebKit is notified about remote track state changes.
TEST_F(RTCPeerConnectionHandlerTest, RemoteTrackState) {
std::string remote_stream_label("remote_stream");
- scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
testing::InSequence sequence;
EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
testing::Property(&blink::WebMediaStream::id,
base::UTF8ToUTF16(remote_stream_label))));
- pc_handler_->observer()->OnAddStream(remote_stream.get());
+ pc_handler_->observer()->OnAddStream(remote_stream);
base::RunLoop().RunUntilIdle();
const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
@@ -859,9 +859,9 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
DoAll(SaveArg<0>(&webkit_stream),
ExitMessageLoop(&message_loop_, run_loop.QuitClosure())));
- scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
- pc_handler_->observer()->OnAddStream(remote_stream.get());
+ pc_handler_->observer()->OnAddStream(remote_stream);
run_loop.Run();
{
@@ -907,9 +907,9 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) {
DoAll(SaveArg<0>(&webkit_stream),
ExitMessageLoop(&message_loop_, run_loop.QuitClosure())));
- scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
- pc_handler_->observer()->OnAddStream(remote_stream.get());
+ pc_handler_->observer()->OnAddStream(remote_stream);
run_loop.Run();
{
@@ -954,9 +954,9 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddTracksFromRemoteStream) {
DoAll(SaveArg<0>(&webkit_stream),
ExitMessageLoop(&message_loop_, run_loop.QuitClosure())));
- scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
- pc_handler_->observer()->OnAddStream(remote_stream.get());
+ pc_handler_->observer()->OnAddStream(remote_stream);
run_loop.Run();
{
diff --git a/chromium/content/renderer/media/speech_recognition_audio_sink.cc b/chromium/content/renderer/media/speech_recognition_audio_sink.cc
index 08bb010a210..e09431ef4e5 100644
--- a/chromium/content/renderer/media/speech_recognition_audio_sink.cc
+++ b/chromium/content/renderer/media/speech_recognition_audio_sink.cc
@@ -162,7 +162,7 @@ void SpeechRecognitionAudioSink::OnData(
}
double SpeechRecognitionAudioSink::ProvideInput(media::AudioBus* audio_bus,
- base::TimeDelta buffer_delay) {
+ uint32_t frames_delayed) {
DCHECK(capture_thread_checker_.CalledOnValidThread());
if (fifo_->frames() >= audio_bus->frames())
fifo_->Consume(audio_bus, 0, audio_bus->frames());
diff --git a/chromium/content/renderer/media/speech_recognition_audio_sink.h b/chromium/content/renderer/media/speech_recognition_audio_sink.h
index e756638363a..a7fa2800b3a 100644
--- a/chromium/content/renderer/media/speech_recognition_audio_sink.h
+++ b/chromium/content/renderer/media/speech_recognition_audio_sink.h
@@ -62,7 +62,7 @@ class CONTENT_EXPORT SpeechRecognitionAudioSink
// media::AudioConverter::Inputcallback implementation.
double ProvideInput(media::AudioBus* audio_bus,
- base::TimeDelta buffer_delay) override;
+ uint32_t frames_delayed) override;
// Returns the pointer to the audio input buffer mapped in the shared memory.
media::AudioInputBuffer* GetAudioInputBuffer() const;
diff --git a/chromium/content/renderer/media/track_audio_renderer.cc b/chromium/content/renderer/media/track_audio_renderer.cc
index 7cadedc02ce..625a65d127b 100644
--- a/chromium/content/renderer/media/track_audio_renderer.cc
+++ b/chromium/content/renderer/media/track_audio_renderer.cc
@@ -12,8 +12,8 @@
#include "base/trace_event/trace_event.h"
#include "content/renderer/media/audio_device_factory.h"
#include "content/renderer/media/media_stream_audio_track.h"
-#include "content/renderer/media/webrtc_audio_renderer.h"
#include "media/base/audio_bus.h"
+#include "media/base/audio_latency.h"
#include "media/base/audio_shifter.h"
namespace content {
@@ -311,7 +311,7 @@ void TrackAudioRenderer::MaybeStartSink() {
media::AudioParameters sink_params(
hardware_params.format(), source_params_.channel_layout(),
source_params_.sample_rate(), source_params_.bits_per_sample(),
- WebRtcAudioRenderer::GetOptimalBufferSize(
+ media::AudioLatency::GetRtcBufferSize(
source_params_.sample_rate(), hardware_params.frames_per_buffer()));
DVLOG(1) << ("TrackAudioRenderer::MaybeStartSink() -- Starting sink. "
"source_params_={")
diff --git a/chromium/content/renderer/media/track_audio_renderer.h b/chromium/content/renderer/media/track_audio_renderer.h
index 43c0d7fa71b..509f31988cc 100644
--- a/chromium/content/renderer/media/track_audio_renderer.h
+++ b/chromium/content/renderer/media/track_audio_renderer.h
@@ -127,7 +127,7 @@ class CONTENT_EXPORT TrackAudioRenderer
// with the audio track.
blink::WebMediaStreamTrack audio_track_;
- // The render view and frame in which the audio is rendered into |sink_|.
+ // The RenderFrame in which the audio is rendered into |sink_|.
const int playout_render_frame_id_;
const int session_id_;
diff --git a/chromium/content/renderer/media/user_media_client_impl.cc b/chromium/content/renderer/media/user_media_client_impl.cc
index 1a8df36355c..cba0545d2d5 100644
--- a/chromium/content/renderer/media/user_media_client_impl.cc
+++ b/chromium/content/renderer/media/user_media_client_impl.cc
@@ -1186,4 +1186,8 @@ bool UserMediaClientImpl::UserMediaRequestInfo::HasPendingSources() const {
return !sources_waiting_for_callback_.empty();
}
+void UserMediaClientImpl::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/user_media_client_impl.h b/chromium/content/renderer/media/user_media_client_impl.h
index f920ca7420d..0b189f52040 100644
--- a/chromium/content/renderer/media/user_media_client_impl.h
+++ b/chromium/content/renderer/media/user_media_client_impl.h
@@ -196,6 +196,9 @@ class CONTENT_EXPORT UserMediaClientImpl
struct MediaDevicesRequestInfo;
typedef ScopedVector<MediaDevicesRequestInfo> MediaDevicesRequests;
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
// Creates a WebKit representation of stream sources based on
// |devices| from the MediaStreamDispatcher.
void InitializeSourceObject(
diff --git a/chromium/content/renderer/media/video_capture_impl.cc b/chromium/content/renderer/media/video_capture_impl.cc
index 90026160a5e..1ccd6c63fce 100644
--- a/chromium/content/renderer/media/video_capture_impl.cc
+++ b/chromium/content/renderer/media/video_capture_impl.cc
@@ -191,7 +191,6 @@ void VideoCaptureImpl::StartCapture(
}
DVLOG(1) << "StartCapture: starting with first resolution "
<< params_.requested_format.frame_size.ToString();
- first_frame_timestamp_ = base::TimeTicks();
StartCaptureInternal();
}
}
@@ -304,7 +303,7 @@ void VideoCaptureImpl::OnBufferDestroyed(int buffer_id) {
void VideoCaptureImpl::OnBufferReceived(
int buffer_id,
- base::TimeTicks timestamp,
+ base::TimeDelta timestamp,
const base::DictionaryValue& metadata,
media::VideoPixelFormat pixel_format,
media::VideoFrame::StorageType storage_type,
@@ -324,14 +323,31 @@ void VideoCaptureImpl::OnBufferReceived(
gpu::SyncToken(), -1.0));
return;
}
- if (first_frame_timestamp_.is_null())
- first_frame_timestamp_ = timestamp;
+ base::TimeTicks reference_time;
+ media::VideoFrameMetadata frame_metadata;
+ frame_metadata.MergeInternalValuesFrom(metadata);
+ const bool success = frame_metadata.GetTimeTicks(
+ media::VideoFrameMetadata::REFERENCE_TIME, &reference_time);
+ DCHECK(success);
+
+ if (first_frame_ref_time_.is_null())
+ first_frame_ref_time_ = reference_time;
+
+ // If the timestamp is not prepared, we use reference time to make a rough
+ // estimate. e.g. ThreadSafeCaptureOracle::DidCaptureFrame().
+ // TODO(miu): Fix upstream capturers to always set timestamp and reference
+ // time. See http://crbug/618407/ for tracking.
+ if (timestamp.is_zero())
+ timestamp = reference_time - first_frame_ref_time_;
+
+ // TODO(qiangchen): Change the metric name to "reference_time" and
+ // "timestamp", so that we have consistent naming everywhere.
// Used by chrome/browser/extension/api/cast_streaming/performance_test.cc
TRACE_EVENT_INSTANT2("cast_perf_test", "OnBufferReceived",
TRACE_EVENT_SCOPE_THREAD, "timestamp",
- timestamp.ToInternalValue(), "time_delta",
- (timestamp - first_frame_timestamp_).ToInternalValue());
+ (reference_time - base::TimeTicks()).InMicroseconds(),
+ "time_delta", timestamp.InMicroseconds());
scoped_refptr<media::VideoFrame> frame;
BufferFinishedCallback buffer_finished_callback;
@@ -343,11 +359,8 @@ void VideoCaptureImpl::OnBufferReceived(
scoped_refptr<ClientBuffer2> buffer = iter->second;
const auto& handles = buffer->gpu_memory_buffer_handles();
frame = media::VideoFrame::WrapExternalYuvGpuMemoryBuffers(
- media::PIXEL_FORMAT_I420,
- coded_size,
- gfx::Rect(coded_size),
- coded_size,
- buffer->stride(media::VideoFrame::kYPlane),
+ media::PIXEL_FORMAT_I420, coded_size, gfx::Rect(coded_size),
+ coded_size, buffer->stride(media::VideoFrame::kYPlane),
buffer->stride(media::VideoFrame::kUPlane),
buffer->stride(media::VideoFrame::kVPlane),
buffer->data(media::VideoFrame::kYPlane),
@@ -355,8 +368,7 @@ void VideoCaptureImpl::OnBufferReceived(
buffer->data(media::VideoFrame::kVPlane),
handles[media::VideoFrame::kYPlane],
handles[media::VideoFrame::kUPlane],
- handles[media::VideoFrame::kVPlane],
- timestamp - first_frame_timestamp_);
+ handles[media::VideoFrame::kVPlane], timestamp);
buffer_finished_callback = media::BindToCurrentLoop(
base::Bind(&VideoCaptureImpl::OnClientBufferFinished2,
weak_factory_.GetWeakPtr(), buffer_id, buffer));
@@ -371,7 +383,7 @@ void VideoCaptureImpl::OnBufferReceived(
gfx::Size(visible_rect.width(), visible_rect.height()),
reinterpret_cast<uint8_t*>(buffer->buffer()->memory()),
buffer->buffer_size(), buffer->buffer()->handle(),
- 0 /* shared_memory_offset */, timestamp - first_frame_timestamp_);
+ 0 /* shared_memory_offset */, timestamp);
buffer_finished_callback = media::BindToCurrentLoop(
base::Bind(&VideoCaptureImpl::OnClientBufferFinished,
weak_factory_.GetWeakPtr(), buffer_id, buffer));
@@ -387,16 +399,16 @@ void VideoCaptureImpl::OnBufferReceived(
return;
}
- frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
- timestamp);
frame->AddDestructionObserver(
base::Bind(&VideoCaptureImpl::DidFinishConsumingFrame, frame->metadata(),
base::Passed(&release_sync_token), buffer_finished_callback));
frame->metadata()->MergeInternalValuesFrom(metadata);
+ // TODO(qiangchen): Dive into the full code path to let frame metadata hold
+ // reference time rather than using an extra parameter.
for (const auto& client : clients_)
- client.second.deliver_frame_cb.Run(frame, timestamp);
+ client.second.deliver_frame_cb.Run(frame, reference_time);
}
void VideoCaptureImpl::OnClientBufferFinished(
diff --git a/chromium/content/renderer/media/video_capture_impl.h b/chromium/content/renderer/media/video_capture_impl.h
index b07823486d8..74c4d19d33f 100644
--- a/chromium/content/renderer/media/video_capture_impl.h
+++ b/chromium/content/renderer/media/video_capture_impl.h
@@ -120,14 +120,13 @@ class CONTENT_EXPORT VideoCaptureImpl
const gfx::Size& size,
int buffer_id) override;
void OnBufferDestroyed(int buffer_id) override;
- void OnBufferReceived(
- int buffer_id,
- base::TimeTicks timestamp,
- const base::DictionaryValue& metadata,
- media::VideoPixelFormat pixel_format,
- media::VideoFrame::StorageType storage_type,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect) override;
+ void OnBufferReceived(int buffer_id,
+ base::TimeDelta timestamp,
+ const base::DictionaryValue& metadata,
+ media::VideoPixelFormat pixel_format,
+ media::VideoFrame::StorageType storage_type,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect) override;
void OnStateChanged(VideoCaptureState state) override;
void OnDeviceSupportedFormatsEnumerated(
const media::VideoCaptureFormats& supported_formats) override;
@@ -189,8 +188,9 @@ class CONTENT_EXPORT VideoCaptureImpl
// client to this class via StartCapture().
media::VideoCaptureParams params_;
- // The device's first captured frame timestamp sent from browser process side.
- base::TimeTicks first_frame_timestamp_;
+ // The device's first captured frame referecne time sent from browser process
+ // side.
+ base::TimeTicks first_frame_ref_time_;
bool suspended_;
VideoCaptureState state_;
diff --git a/chromium/content/renderer/media/video_capture_impl_unittest.cc b/chromium/content/renderer/media/video_capture_impl_unittest.cc
index 1fc43c024b8..7ad265e1919 100644
--- a/chromium/content/renderer/media/video_capture_impl_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_impl_unittest.cc
@@ -168,10 +168,18 @@ class VideoCaptureImplTest : public ::testing::Test {
}
void BufferReceived(int buffer_id, const gfx::Size& size) {
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeDelta timestamp = now - base::TimeTicks();
+
+ media::VideoFrameMetadata frame_metadata;
+ frame_metadata.SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
+ now);
+ base::DictionaryValue metadata;
+ frame_metadata.MergeInternalValuesInto(&metadata);
+
video_capture_impl_->OnBufferReceived(
- buffer_id, base::TimeTicks::Now(), base::DictionaryValue(),
- media::PIXEL_FORMAT_I420, media::VideoFrame::STORAGE_SHMEM, size,
- gfx::Rect(size));
+ buffer_id, timestamp, metadata, media::PIXEL_FORMAT_I420,
+ media::VideoFrame::STORAGE_SHMEM, size, gfx::Rect(size));
}
void BufferDestroyed(int buffer_id) {
diff --git a/chromium/content/renderer/media/video_capture_message_filter.h b/chromium/content/renderer/media/video_capture_message_filter.h
index 9088cd38f24..05939715957 100644
--- a/chromium/content/renderer/media/video_capture_message_filter.h
+++ b/chromium/content/renderer/media/video_capture_message_filter.h
@@ -48,14 +48,13 @@ class CONTENT_EXPORT VideoCaptureMessageFilter : public IPC::MessageFilter {
// Called when a buffer referencing a captured VideoFrame is received from
// Browser process.
- virtual void OnBufferReceived(
- int buffer_id,
- base::TimeTicks timestamp,
- const base::DictionaryValue& metadata,
- media::VideoPixelFormat pixel_format,
- media::VideoFrame::StorageType storage_type,
- const gfx::Size& coded_size,
- const gfx::Rect& visible_rect) = 0;
+ virtual void OnBufferReceived(int buffer_id,
+ base::TimeDelta timestamp,
+ const base::DictionaryValue& metadata,
+ media::VideoPixelFormat pixel_format,
+ media::VideoFrame::StorageType storage_type,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect) = 0;
// Called when state of a video capture device has changed in the browser
// process.
diff --git a/chromium/content/renderer/media/video_capture_message_filter_unittest.cc b/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
index 6a339404de1..05845bf3232 100644
--- a/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
@@ -43,7 +43,7 @@ class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate {
MOCK_METHOD1(OnBufferDestroyed, void(int buffer_id));
MOCK_METHOD7(OnBufferReceived,
void(int buffer_id,
- base::TimeTicks timestamp,
+ base::TimeDelta timestamp,
const base::DictionaryValue& metadata,
media::VideoPixelFormat pixel_format,
media::VideoFrame::StorageType storage_type,
@@ -122,8 +122,12 @@ TEST(VideoCaptureMessageFilterTest, Basic) {
VideoCaptureMsg_BufferReady_Params params;
params.device_id = delegate.device_id();
params.buffer_id = 22;
- params.timestamp = base::TimeTicks::FromInternalValue(1);
+ params.timestamp = base::TimeDelta::FromMicroseconds(1);
params.metadata.SetString("foo", "bar");
+ media::VideoFrameMetadata frame_metadata;
+ frame_metadata.SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
+ base::TimeTicks::FromInternalValue(1));
+ frame_metadata.MergeInternalValuesInto(&params.metadata);
params.pixel_format = media::PIXEL_FORMAT_I420;
params.storage_type = media::VideoFrame::STORAGE_SHMEM;
params.coded_size = gfx::Size(234, 512);
diff --git a/chromium/content/renderer/media/video_track_recorder.cc b/chromium/content/renderer/media/video_track_recorder.cc
index 8da8f308492..d65e238e879 100644
--- a/chromium/content/renderer/media/video_track_recorder.cc
+++ b/chromium/content/renderer/media/video_track_recorder.cc
@@ -10,11 +10,17 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/sys_info.h"
+#include "base/task_runner_util.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+#include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
+#include "content/renderer/render_thread_impl.h"
+#include "media/base/bind_to_current_loop.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
+#include "third_party/libyuv/include/libyuv/convert.h"
#include "ui/gfx/geometry/size.h"
#if BUILDFLAG(RTC_USE_H264)
@@ -36,6 +42,62 @@ using media::VideoFrameMetadata;
namespace content {
+namespace {
+
+const int kVEAEncoderMinResolutionWidth = 640;
+const int kVEAEncoderMinResolutionHeight = 480;
+const int kVEAEncoderOutputBufferCount = 4;
+
+static struct {
+ VideoTrackRecorder::CodecId codec_id;
+ media::VideoCodecProfile min_profile;
+ media::VideoCodecProfile max_profile;
+} const kSupportedVideoCodecIdToProfile[] = {
+ {VideoTrackRecorder::CodecId::VP8,
+ media::VP8PROFILE_MIN,
+ media::VP8PROFILE_MAX},
+ {VideoTrackRecorder::CodecId::VP9,
+ media::VP9PROFILE_MIN,
+ media::VP9PROFILE_MAX},
+ {VideoTrackRecorder::CodecId::H264,
+ media::H264PROFILE_MIN,
+ media::H264PROFILE_MAX}};
+
+// Returns the corresponding codec profile from VEA supported codecs. If no
+// profile is found, returns VIDEO_CODEC_PROFILE_UNKNOWN.
+media::VideoCodecProfile CodecIdToVEAProfile(
+ content::VideoTrackRecorder::CodecId codec) {
+ // See https://crbug.com/616659.
+#if defined(OS_CHROMEOS)
+ return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+#endif // defined(OS_CHROMEOS)
+ content::RenderThreadImpl* render_thread_impl =
+ content::RenderThreadImpl::current();
+ if (!render_thread_impl)
+ return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+
+ media::GpuVideoAcceleratorFactories* gpu_factories =
+ content::RenderThreadImpl::current()->GetGpuFactories();
+ if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) {
+ DVLOG(3) << "Couldn't initialize GpuVideoAcceleratorFactories";
+ return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+ }
+
+ const media::VideoEncodeAccelerator::SupportedProfiles& vea_profiles =
+ gpu_factories->GetVideoEncodeAcceleratorSupportedProfiles();
+ for (const auto& vea_profile : vea_profiles) {
+ for (const auto& supported_profile : kSupportedVideoCodecIdToProfile) {
+ if (codec == supported_profile.codec_id &&
+ vea_profile.profile >= supported_profile.min_profile &&
+ vea_profile.profile <= supported_profile.max_profile)
+ return vea_profile.profile;
+ }
+ }
+ return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+}
+
+} // anonymous namespace
+
// Base class to describe a generic Encoder, encapsulating all actual encoder
// (re)configurations, encoding and delivery of received frames. This class is
// ref-counted to allow the MediaStreamVideoTrack to hold a reference to it (via
@@ -56,13 +118,13 @@ class VideoTrackRecorder::Encoder : public base::RefCountedThreadSafe<Encoder> {
int32_t bits_per_second,
scoped_refptr<base::SingleThreadTaskRunner> encoding_task_runner =
nullptr)
- : main_task_runner_(base::MessageLoop::current()->task_runner()),
+ : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
encoding_task_runner_(encoding_task_runner),
paused_(false),
on_encoded_video_callback_(on_encoded_video_callback),
bits_per_second_(bits_per_second) {
DCHECK(!on_encoded_video_callback_.is_null());
- if (encoding_thread_)
+ if (encoding_task_runner_)
return;
encoding_thread_.reset(new base::Thread("EncodingThread"));
encoding_thread_->Start();
@@ -116,7 +178,7 @@ void VideoTrackRecorder::Encoder::StartFrameEncode(
base::TimeTicks capture_timestamp) {
// Cache the thread sending frames on first frame arrival.
if (!origin_task_runner_.get())
- origin_task_runner_ = base::MessageLoop::current()->task_runner();
+ origin_task_runner_ = base::ThreadTaskRunnerHandle::Get();
DCHECK(origin_task_runner_->BelongsToCurrentThread());
if (paused_)
return;
@@ -179,6 +241,69 @@ static int GetNumberOfThreadsForEncoding() {
return std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2);
}
+// Class encapsulating VideoEncodeAccelerator interactions.
+// This class is created and destroyed in its owner thread. All other methods
+// operate on the task runner pointed by GpuFactories.
+class VEAEncoder final : public VideoTrackRecorder::Encoder,
+ public media::VideoEncodeAccelerator::Client {
+ public:
+ VEAEncoder(
+ const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
+ int32_t bits_per_second,
+ media::VideoCodecProfile codec);
+
+ // media::VideoEncodeAccelerator::Client implementation.
+ void RequireBitstreamBuffers(unsigned int input_count,
+ const gfx::Size& input_coded_size,
+ size_t output_buffer_size) override;
+ void BitstreamBufferReady(int32_t bitstream_buffer_id,
+ size_t payload_size,
+ bool key_frame,
+ base::TimeDelta timestamp) override;
+ void NotifyError(media::VideoEncodeAccelerator::Error error) override;
+
+ private:
+ using VideoFrameAndTimestamp =
+ std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>;
+
+ void UseOutputBitstreamBufferId(int32_t bitstream_buffer_id);
+ void FrameFinished(std::unique_ptr<base::SharedMemory> shm);
+
+ // VideoTrackRecorder::Encoder implementation.
+ ~VEAEncoder() override;
+ void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame,
+ base::TimeTicks capture_timestamp) override;
+ void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override;
+
+ media::GpuVideoAcceleratorFactories* const gpu_factories_;
+
+ const media::VideoCodecProfile codec_;
+
+ // The underlying VEA to perform encoding on.
+ std::unique_ptr<media::VideoEncodeAccelerator> video_encoder_;
+
+ // Shared memory buffers for output with the VEA.
+ std::vector<std::unique_ptr<base::SharedMemory>> output_buffers_;
+
+ // Shared memory buffers for output with the VEA as FIFO.
+ std::queue<std::unique_ptr<base::SharedMemory>> input_buffers_;
+
+ // Tracks error status.
+ bool error_notified_;
+
+ // Tracks the first frame to encode.
+ std::unique_ptr<VideoFrameAndTimestamp> first_frame_;
+
+ // Size used to initialize encoder.
+ gfx::Size input_size_;
+
+ // Coded size that encoder requests as input.
+ gfx::Size vea_requested_input_size_;
+
+ // Frames and corresponding timestamps in encode as FIFO.
+ std::queue<VideoFrameAndTimestamp> frames_in_encode_;
+};
+
// Class encapsulating all libvpx interactions for VP8/VP9 encoding.
class VpxEncoder final : public VideoTrackRecorder::Encoder {
public:
@@ -191,10 +316,10 @@ class VpxEncoder final : public VideoTrackRecorder::Encoder {
int32_t bits_per_second);
private:
- // VideoTrackRecorder::Encoder
+ // VideoTrackRecorder::Encoder implementation.
~VpxEncoder() override;
void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame,
- base::TimeTicks capture_timestamp) override;
+ base::TimeTicks capture_timestamp) override;
void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) override;
// Returns true if |codec_config_| has been filled in at least once.
@@ -243,7 +368,7 @@ class H264Encoder final : public VideoTrackRecorder::Encoder {
int32_t bits_per_second);
private:
- // VideoTrackRecorder::Encoder
+ // VideoTrackRecorder::Encoder implementation.
~H264Encoder() override;
void EncodeOnEncodingTaskRunner(const scoped_refptr<VideoFrame>& frame,
base::TimeTicks capture_timestamp) override;
@@ -264,6 +389,196 @@ class H264Encoder final : public VideoTrackRecorder::Encoder {
#endif // #if BUILDFLAG(RTC_USE_H264)
+VEAEncoder::VEAEncoder(
+ const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback,
+ int32_t bits_per_second,
+ media::VideoCodecProfile codec)
+ : Encoder(on_encoded_video_callback,
+ bits_per_second,
+ RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()),
+ gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()),
+ codec_(codec),
+ error_notified_(false) {
+ DCHECK(gpu_factories_);
+}
+
+VEAEncoder::~VEAEncoder() {
+ encoding_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&media::VideoEncodeAccelerator::Destroy,
+ base::Unretained(video_encoder_.release())));
+}
+
+void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/,
+ const gfx::Size& input_coded_size,
+ size_t output_buffer_size) {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+
+ vea_requested_input_size_ = input_coded_size;
+ output_buffers_.clear();
+ std::queue<std::unique_ptr<base::SharedMemory>>().swap(input_buffers_);
+
+ for (int i = 0; i < kVEAEncoderOutputBufferCount; ++i) {
+ std::unique_ptr<base::SharedMemory> shm =
+ gpu_factories_->CreateSharedMemory(output_buffer_size);
+ if (shm)
+ output_buffers_.push_back(base::WrapUnique(shm.release()));
+ }
+
+ for (size_t i = 0; i < output_buffers_.size(); ++i)
+ UseOutputBitstreamBufferId(i);
+}
+
+void VEAEncoder::BitstreamBufferReady(int32_t bitstream_buffer_id,
+ size_t payload_size,
+ bool keyframe,
+ base::TimeDelta timestamp) {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+
+ base::SharedMemory* output_buffer =
+ output_buffers_[bitstream_buffer_id].get();
+
+ std::unique_ptr<std::string> data(new std::string);
+ data->append(reinterpret_cast<char*>(output_buffer->memory()), payload_size);
+
+ const auto front_frame = frames_in_encode_.front();
+ frames_in_encode_.pop();
+ origin_task_runner_->PostTask(
+ FROM_HERE, base::Bind(OnFrameEncodeCompleted, on_encoded_video_callback_,
+ front_frame.first, base::Passed(&data),
+ front_frame.second, keyframe));
+ UseOutputBitstreamBufferId(bitstream_buffer_id);
+}
+
+void VEAEncoder::NotifyError(media::VideoEncodeAccelerator::Error error) {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+
+ // TODO(emircan): Notify the owner via a callback.
+ error_notified_ = true;
+}
+
+void VEAEncoder::UseOutputBitstreamBufferId(int32_t bitstream_buffer_id) {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+
+ video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
+ bitstream_buffer_id, output_buffers_[bitstream_buffer_id]->handle(),
+ output_buffers_[bitstream_buffer_id]->mapped_size()));
+}
+
+void VEAEncoder::FrameFinished(std::unique_ptr<base::SharedMemory> shm) {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+ input_buffers_.push(std::move(shm));
+}
+
+void VEAEncoder::EncodeOnEncodingTaskRunner(
+ const scoped_refptr<VideoFrame>& frame,
+ base::TimeTicks capture_timestamp) {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+
+ if (input_size_ != frame->visible_rect().size() && video_encoder_) {
+ video_encoder_->Destroy();
+ video_encoder_.reset();
+ }
+
+ if (!video_encoder_) {
+ ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size());
+ first_frame_.reset(
+ new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>(
+ frame, capture_timestamp));
+ }
+
+ if (error_notified_) {
+ DVLOG(3) << "An error occurred in VEA encoder";
+ return;
+ }
+
+ // Drop frames if there is no output buffers available.
+ if (output_buffers_.empty()) {
+ // TODO(emircan): Investigate if resetting encoder would help.
+ DVLOG(3) << "Dropped frame.";
+ return;
+ }
+
+ // If first frame hasn't been encoded, do it first.
+ if (first_frame_) {
+ std::unique_ptr<VideoFrameAndTimestamp> first_frame(first_frame_.release());
+ EncodeOnEncodingTaskRunner(first_frame->first, first_frame->second);
+ }
+
+ // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac.
+ // In that case, the encoder expects more frames before returning result.
+ // Therefore, a copy is necessary to release the current frame.
+ scoped_refptr<media::VideoFrame> video_frame = frame;
+ if (vea_requested_input_size_ != input_size_ ||
+ input_size_.width() < kVEAEncoderMinResolutionWidth ||
+ input_size_.height() < kVEAEncoderMinResolutionHeight) {
+ // Create SharedMemory backed input buffers as necessary. These SharedMemory
+ // instances will be shared with GPU process.
+ std::unique_ptr<base::SharedMemory> input_buffer;
+ const size_t desired_mapped_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, vea_requested_input_size_);
+ if (input_buffers_.empty()) {
+ input_buffer = gpu_factories_->CreateSharedMemory(desired_mapped_size);
+ } else {
+ do {
+ input_buffer = std::move(input_buffers_.front());
+ input_buffers_.pop();
+ } while (!input_buffers_.empty() &&
+ input_buffer->mapped_size() < desired_mapped_size);
+ if (!input_buffer || input_buffer->mapped_size() < desired_mapped_size)
+ return;
+ }
+
+ video_frame = media::VideoFrame::WrapExternalSharedMemory(
+ media::PIXEL_FORMAT_I420, vea_requested_input_size_,
+ gfx::Rect(input_size_), input_size_,
+ reinterpret_cast<uint8_t*>(input_buffer->memory()),
+ input_buffer->mapped_size(), input_buffer->handle(), 0,
+ frame->timestamp());
+ video_frame->AddDestructionObserver(media::BindToCurrentLoop(
+ base::Bind(&VEAEncoder::FrameFinished, this,
+ base::Passed(std::move(input_buffer)))));
+ libyuv::I420Copy(frame->visible_data(media::VideoFrame::kYPlane),
+ frame->stride(media::VideoFrame::kYPlane),
+ frame->visible_data(media::VideoFrame::kUPlane),
+ frame->stride(media::VideoFrame::kUPlane),
+ frame->visible_data(media::VideoFrame::kVPlane),
+ frame->stride(media::VideoFrame::kVPlane),
+ video_frame->visible_data(media::VideoFrame::kYPlane),
+ video_frame->stride(media::VideoFrame::kYPlane),
+ video_frame->visible_data(media::VideoFrame::kUPlane),
+ video_frame->stride(media::VideoFrame::kUPlane),
+ video_frame->visible_data(media::VideoFrame::kVPlane),
+ video_frame->stride(media::VideoFrame::kVPlane),
+ input_size_.width(), input_size_.height());
+ }
+ frames_in_encode_.push(std::make_pair(video_frame, capture_timestamp));
+
+ encoding_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&media::VideoEncodeAccelerator::Encode,
+ base::Unretained(video_encoder_.get()), video_frame, false));
+}
+
+void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+ DCHECK(gpu_factories_->GetTaskRunner()->BelongsToCurrentThread());
+
+ input_size_ = size;
+ video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator();
+ if (!video_encoder_ ||
+ !video_encoder_->Initialize(media::PIXEL_FORMAT_I420, input_size_, codec_,
+ bits_per_second_, this)) {
+ NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
+ }
+}
+
// static
void VpxEncoder::ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread,
ScopedVpxCodecCtxPtr encoder) {
@@ -624,21 +939,28 @@ VideoTrackRecorder::VideoTrackRecorder(
: track_(track) {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
DCHECK(!track_.isNull());
- DCHECK(track_.getExtraData());
+ DCHECK(track_.getTrackData());
- switch (codec) {
+ const auto& vea_supported_profile = CodecIdToVEAProfile(codec);
+ // TODO(emircan): Prioritize software based encoders in lower resolutions.
+ if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN) {
+ encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second,
+ vea_supported_profile);
+ } else {
+ switch (codec) {
#if BUILDFLAG(RTC_USE_H264)
- case CodecId::H264:
- encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second);
- break;
+ case CodecId::H264:
+ encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second);
+ break;
#endif
- case CodecId::VP8:
- case CodecId::VP9:
- encoder_ = new VpxEncoder(codec == CodecId::VP9,
- on_encoded_video_callback, bits_per_second);
- break;
- default:
- NOTREACHED() << "Unsupported codec";
+ case CodecId::VP8:
+ case CodecId::VP9:
+ encoder_ = new VpxEncoder(codec == CodecId::VP9,
+ on_encoded_video_callback, bits_per_second);
+ break;
+ default:
+ NOTREACHED() << "Unsupported codec";
+ }
}
// StartFrameEncode() will be called on Render IO thread.
diff --git a/chromium/content/renderer/media/video_track_recorder.h b/chromium/content/renderer/media/video_track_recorder.h
index a49733f9d70..5e624549224 100644
--- a/chromium/content/renderer/media/video_track_recorder.h
+++ b/chromium/content/renderer/media/video_track_recorder.h
@@ -32,9 +32,7 @@ class CONTENT_EXPORT VideoTrackRecorder
enum class CodecId {
VP8,
VP9,
-#if BUILDFLAG(RTC_USE_H264)
H264,
-#endif
};
class Encoder;
diff --git a/chromium/content/renderer/media/video_track_recorder_unittest.cc b/chromium/content/renderer/media/video_track_recorder_unittest.cc
index 0ca52bb3397..a8390825af8 100644
--- a/chromium/content/renderer/media/video_track_recorder_unittest.cc
+++ b/chromium/content/renderer/media/video_track_recorder_unittest.cc
@@ -65,7 +65,7 @@ class VideoTrackRecorderTest
track_ = new MediaStreamVideoTrack(mock_source_, constraints,
MediaStreamSource::ConstraintsCallback(),
true /* enabled */);
- blink_track_.setExtraData(track_);
+ blink_track_.setTrackData(track_);
video_track_recorder_.reset(new VideoTrackRecorder(
GetParam() /* codec */, blink_track_,
diff --git a/chromium/content/renderer/media/webmediaplayer_ms.cc b/chromium/content/renderer/media/webmediaplayer_ms.cc
index 489d65bc707..d437247d180 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms.cc
+++ b/chromium/content/renderer/media/webmediaplayer_ms.cc
@@ -18,7 +18,7 @@
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/public/renderer/media_stream_audio_renderer.h"
#include "content/public/renderer/media_stream_renderer_factory.h"
-#include "content/public/renderer/video_frame_provider.h"
+#include "content/public/renderer/media_stream_video_renderer.h"
#include "content/renderer/media/web_media_element_source_utils.h"
#include "content/renderer/media/webmediaplayer_ms_compositor.h"
#include "content/renderer/render_frame_impl.h"
@@ -124,7 +124,7 @@ void WebMediaPlayerMS::load(LoadType load_type,
web_stream.isNull() ? std::string() : web_stream.id().utf8();
media_log_->AddEvent(media_log_->CreateLoadEvent(stream_id));
- video_frame_provider_ = renderer_factory_->GetVideoFrameProvider(
+ video_frame_provider_ = renderer_factory_->GetVideoRenderer(
web_stream, base::Bind(&WebMediaPlayerMS::OnSourceError, AsWeakPtr()),
base::Bind(&WebMediaPlayerMS::OnFrameAvailable, AsWeakPtr()),
media_task_runner_, worker_task_runner_, gpu_factories_);
@@ -168,7 +168,7 @@ void WebMediaPlayerMS::play() {
return;
if (video_frame_provider_)
- video_frame_provider_->Play();
+ video_frame_provider_->Resume();
compositor_->StartRendering();
diff --git a/chromium/content/renderer/media/webmediaplayer_ms.h b/chromium/content/renderer/media/webmediaplayer_ms.h
index 76b8da1991a..51d116099d7 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms.h
+++ b/chromium/content/renderer/media/webmediaplayer_ms.h
@@ -45,7 +45,7 @@ class GLES2Interface;
namespace content {
class MediaStreamAudioRenderer;
class MediaStreamRendererFactory;
-class VideoFrameProvider;
+class MediaStreamVideoRenderer;
class WebMediaPlayerMSCompositor;
class RenderFrameObserver;
@@ -57,7 +57,7 @@ class RenderFrameObserver;
//
// WebMediaPlayerMS works with multiple objects, the most important ones are:
//
-// VideoFrameProvider
+// MediaStreamVideoRenderer
// provides video frames for rendering.
//
// blink::WebMediaPlayerClient
@@ -68,7 +68,7 @@ class CONTENT_EXPORT WebMediaPlayerMS
public NON_EXPORTED_BASE(base::SupportsWeakPtr<WebMediaPlayerMS>) {
public:
// Construct a WebMediaPlayerMS with reference to the client, and
- // a MediaStreamClient which provides VideoFrameProvider.
+ // a MediaStreamClient which provides MediaStreamVideoRenderer.
WebMediaPlayerMS(
blink::WebFrame* frame,
blink::WebMediaPlayerClient* client,
@@ -161,7 +161,8 @@ class CONTENT_EXPORT WebMediaPlayerMS
private:
friend class WebMediaPlayerMSTest;
- // The callback for VideoFrameProvider to signal a new frame is available.
+ // The callback for MediaStreamVideoRenderer to signal a new frame is
+ // available.
void OnFrameAvailable(const scoped_refptr<media::VideoFrame>& frame);
// Need repaint due to state change.
void RepaintInternal();
@@ -193,12 +194,11 @@ class CONTENT_EXPORT WebMediaPlayerMS
const base::WeakPtr<media::WebMediaPlayerDelegate> delegate_;
int delegate_id_;
- // Specify content:: to disambiguate from cc::.
- scoped_refptr<content::VideoFrameProvider> video_frame_provider_; // Weak
+ scoped_refptr<MediaStreamVideoRenderer> video_frame_provider_; // Weak
std::unique_ptr<cc_blink::WebLayerImpl> video_weblayer_;
- scoped_refptr<MediaStreamAudioRenderer> audio_renderer_; // Weak
+ scoped_refptr<MediaStreamAudioRenderer> audio_renderer_; // Weak
media::SkCanvasVideoRenderer video_renderer_;
bool paused_;
diff --git a/chromium/content/renderer/media/webmediaplayer_ms_unittest.cc b/chromium/content/renderer/media/webmediaplayer_ms_unittest.cc
index 37078750f50..d02bb0d1ec5 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms_unittest.cc
+++ b/chromium/content/renderer/media/webmediaplayer_ms_unittest.cc
@@ -112,13 +112,13 @@ class ReusableMessageLoopEvent {
};
// The class is used mainly to inject VideoFrames into WebMediaPlayerMS.
-class MockVideoFrameProvider : public VideoFrameProvider {
+class MockMediaStreamVideoRenderer : public MediaStreamVideoRenderer {
public:
- MockVideoFrameProvider(
+ MockMediaStreamVideoRenderer(
const scoped_refptr<base::SingleThreadTaskRunner> task_runner,
ReusableMessageLoopEvent* message_loop_controller,
const base::Closure& error_cb,
- const VideoFrameProvider::RepaintCB& repaint_cb)
+ const MediaStreamVideoRenderer::RepaintCB& repaint_cb)
: started_(false),
task_runner_(task_runner),
message_loop_controller_(message_loop_controller),
@@ -127,10 +127,10 @@ class MockVideoFrameProvider : public VideoFrameProvider {
delay_till_next_generated_frame_(
base::TimeDelta::FromSecondsD(1.0 / 30.0)) {}
- // Implementation of VideoFrameProvider
+ // Implementation of MediaStreamVideoRenderer
void Start() override;
void Stop() override;
- void Play() override;
+ void Resume() override;
void Pause() override;
// Methods for test use
@@ -142,7 +142,7 @@ class MockVideoFrameProvider : public VideoFrameProvider {
bool Paused() { return paused_; }
private:
- ~MockVideoFrameProvider() override {}
+ ~MockMediaStreamVideoRenderer() override {}
// Main function that pushes a frame into WebMediaPlayerMS
void InjectFrame();
@@ -157,42 +157,43 @@ class MockVideoFrameProvider : public VideoFrameProvider {
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
ReusableMessageLoopEvent* const message_loop_controller_;
const base::Closure error_cb_;
- const VideoFrameProvider::RepaintCB repaint_cb_;
+ const MediaStreamVideoRenderer::RepaintCB repaint_cb_;
std::deque<TestFrame> frames_;
base::TimeDelta delay_till_next_generated_frame_;
};
-void MockVideoFrameProvider::Start() {
+void MockMediaStreamVideoRenderer::Start() {
started_ = true;
paused_ = false;
task_runner_->PostTask(
FROM_HERE,
- base::Bind(&MockVideoFrameProvider::InjectFrame, base::Unretained(this)));
+ base::Bind(&MockMediaStreamVideoRenderer::InjectFrame,
+ base::Unretained(this)));
}
-void MockVideoFrameProvider::Stop() {
+void MockMediaStreamVideoRenderer::Stop() {
started_ = false;
frames_.clear();
}
-void MockVideoFrameProvider::Play() {
+void MockMediaStreamVideoRenderer::Resume() {
CHECK(started_);
paused_ = false;
}
-void MockVideoFrameProvider::Pause() {
+void MockMediaStreamVideoRenderer::Pause() {
CHECK(started_);
paused_ = true;
}
-void MockVideoFrameProvider::AddFrame(
+void MockMediaStreamVideoRenderer::AddFrame(
FrameType category,
const scoped_refptr<media::VideoFrame>& frame) {
frames_.push_back(std::make_pair(category, frame));
}
-void MockVideoFrameProvider::QueueFrames(
+void MockMediaStreamVideoRenderer::QueueFrames(
const std::vector<int>& timestamp_or_frame_type,
bool opaque_frame,
bool odd_size_frame,
@@ -236,7 +237,7 @@ void MockVideoFrameProvider::QueueFrames(
}
}
-void MockVideoFrameProvider::InjectFrame() {
+void MockMediaStreamVideoRenderer::InjectFrame() {
DCHECK(task_runner_->BelongsToCurrentThread());
if (!started_)
return;
@@ -272,7 +273,8 @@ void MockVideoFrameProvider::InjectFrame() {
task_runner_->PostDelayedTask(
FROM_HERE,
- base::Bind(&MockVideoFrameProvider::InjectFrame, base::Unretained(this)),
+ base::Bind(&MockMediaStreamVideoRenderer::InjectFrame,
+ base::Unretained(this)),
delay_till_next_generated_frame_);
// This will pause the |message_loop_|, and the purpose is to allow the main
@@ -293,16 +295,16 @@ class MockRenderFactory : public MediaStreamRendererFactory {
: task_runner_(task_runner),
message_loop_controller_(message_loop_controller) {}
- scoped_refptr<VideoFrameProvider> GetVideoFrameProvider(
+ scoped_refptr<MediaStreamVideoRenderer> GetVideoRenderer(
const blink::WebMediaStream& web_stream,
const base::Closure& error_cb,
- const VideoFrameProvider::RepaintCB& repaint_cb,
+ const MediaStreamVideoRenderer::RepaintCB& repaint_cb,
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
const scoped_refptr<base::TaskRunner>& worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories) override;
- MockVideoFrameProvider* provider() {
- return static_cast<MockVideoFrameProvider*>(provider_.get());
+ MockMediaStreamVideoRenderer* provider() {
+ return static_cast<MockMediaStreamVideoRenderer*>(provider_.get());
}
scoped_refptr<MediaStreamAudioRenderer> GetAudioRenderer(
@@ -315,19 +317,19 @@ class MockRenderFactory : public MediaStreamRendererFactory {
private:
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_refptr<VideoFrameProvider> provider_;
+ scoped_refptr<MediaStreamVideoRenderer> provider_;
ReusableMessageLoopEvent* const message_loop_controller_;
};
-scoped_refptr<VideoFrameProvider> MockRenderFactory::GetVideoFrameProvider(
+scoped_refptr<MediaStreamVideoRenderer> MockRenderFactory::GetVideoRenderer(
const blink::WebMediaStream& web_stream,
const base::Closure& error_cb,
- const VideoFrameProvider::RepaintCB& repaint_cb,
+ const MediaStreamVideoRenderer::RepaintCB& repaint_cb,
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
const scoped_refptr<base::TaskRunner>& worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories) {
- provider_ = new MockVideoFrameProvider(task_runner_, message_loop_controller_,
- error_cb, repaint_cb);
+ provider_ = new MockMediaStreamVideoRenderer(task_runner_,
+ message_loop_controller_, error_cb, repaint_cb);
return provider_;
}
@@ -335,8 +337,8 @@ scoped_refptr<VideoFrameProvider> MockRenderFactory::GetVideoFrameProvider(
// This is the main class coordinating the tests.
// Basic workflow:
// 1. WebMediaPlayerMS::Load will generate and start
-// content::VideoFrameProvider.
-// 2. content::VideoFrameProvider will start pushing frames into
+// content::MediaStreamVideoRenderer.
+// 2. content::MediaStreamVideoRenderer will start pushing frames into
// WebMediaPlayerMS repeatedly.
// 3. On WebMediaPlayerMS receiving the first frame, a WebLayer will be created.
// 4. The WebLayer will call
@@ -346,7 +348,7 @@ scoped_refptr<VideoFrameProvider> MockRenderFactory::GetVideoFrameProvider(
// WebMediaPlayerMSCompositor::UpdateCurrentFrame, GetCurrentFrame for
// rendering repeatedly.
// 6. When WebMediaPlayerMS::pause gets called, it should trigger
-// content::VideoFrameProvider::Pause, and then the provider will stop
+// content::MediaStreamVideoRenderer::Pause, and then the provider will stop
// pushing frames into WebMediaPlayerMS, but instead digesting them;
// simultanously, it should call cc::VideoFrameProviderClient::StopRendering,
// so cc::VideoFrameProviderClient will stop asking frames from
@@ -380,7 +382,7 @@ class WebMediaPlayerMSTest
base::RunLoop().RunUntilIdle();
}
- MockVideoFrameProvider* LoadAndGetFrameProvider(bool algorithm_enabled);
+ MockMediaStreamVideoRenderer* LoadAndGetFrameProvider(bool algorithm_enabled);
// Implementation of WebMediaPlayerClient
void networkStateChanged() override;
@@ -396,7 +398,7 @@ class WebMediaPlayerMSTest
const blink::WebString& label,
const blink::WebString& language,
bool enabled) override {
- return 0;
+ return blink::WebMediaPlayer::TrackId();
}
void removeAudioTrack(blink::WebMediaPlayer::TrackId) override {}
blink::WebMediaPlayer::TrackId addVideoTrack(const blink::WebString& id,
@@ -404,7 +406,7 @@ class WebMediaPlayerMSTest
const blink::WebString& label,
const blink::WebString& language,
bool selected) override {
- return 0;
+ return blink::WebMediaPlayer::TrackId();
}
void removeVideoTrack(blink::WebMediaPlayer::TrackId) override {}
void addTextTrack(blink::WebInbandTextTrack*) override {}
@@ -454,7 +456,7 @@ class WebMediaPlayerMSTest
bool background_rendering_;
};
-MockVideoFrameProvider* WebMediaPlayerMSTest::LoadAndGetFrameProvider(
+MockMediaStreamVideoRenderer* WebMediaPlayerMSTest::LoadAndGetFrameProvider(
bool algorithm_enabled) {
EXPECT_FALSE(!!render_factory_->provider()) << "There should not be a "
"FrameProvider yet.";
@@ -470,7 +472,7 @@ MockVideoFrameProvider* WebMediaPlayerMSTest::LoadAndGetFrameProvider(
EXPECT_TRUE(!!compositor_);
compositor_->SetAlgorithmEnabledForTesting(algorithm_enabled);
- MockVideoFrameProvider* const provider = render_factory_->provider();
+ MockMediaStreamVideoRenderer* const provider = render_factory_->provider();
EXPECT_TRUE(!!provider);
EXPECT_TRUE(provider->Started());
@@ -556,7 +558,7 @@ TEST_F(WebMediaPlayerMSTest, Playing_Normal) {
// and verifies that they are produced by WebMediaPlayerMS in appropriate
// order.
- MockVideoFrameProvider* provider = LoadAndGetFrameProvider(true);
+ MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
int tokens[] = {0, 33, 66, 100, 133, 166, 200, 233, 266, 300,
333, 366, 400, 433, 466, 500, 533, 566, 600};
@@ -583,7 +585,7 @@ TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) {
// This tests sends a broken frame to WebMediaPlayerMS, and verifies
// OnSourceError function works as expected.
- MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false);
+ MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(false);
const int kBrokenFrame = static_cast<int>(FrameType::BROKEN_FRAME);
int tokens[] = {0, 33, 66, 100, 133, 166, 200, 233, 266, 300,
@@ -615,7 +617,7 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPause) {
// In the middle of this test, WebMediaPlayerMS::pause will be called, and we
// are going to verify that during the pause stage, a frame gets freezed, and
// cc::VideoFrameProviderClient should also be paused.
- MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false);
+ MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(false);
const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE);
int tokens[] = {0, 33, 66, 100, 133, kTestBrake, 166, 200, 233, 266,
@@ -655,7 +657,7 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
const bool odd_size_frame = testing::get<1>(GetParam());
// Similary to PlayAndPause test above, this one focuses on testing that
// WebMediaPlayerMS can be resumed after a period of paused status.
- MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false);
+ MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(false);
const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE);
int tokens[] = {0, 33, 66, 100, 133, kTestBrake, 166,
@@ -714,7 +716,7 @@ TEST_F(WebMediaPlayerMSTest, BackgroundRendering) {
// WebMediaPlayerMS without an explicit notification. We should expect that
// WebMediaPlayerMS can digest old frames, rather than piling frames up and
// explode.
- MockVideoFrameProvider* provider = LoadAndGetFrameProvider(true);
+ MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
const int kTestBrake = static_cast<int>(FrameType::TEST_BRAKE);
int tokens[] = {0, 33, 66, 100, 133, kTestBrake, 166,
@@ -760,7 +762,7 @@ TEST_F(WebMediaPlayerMSTest, FrameSizeChange) {
// During this test, the frame size of the input changes.
// We need to make sure, when sizeChanged() gets called, new size should be
// returned by GetCurrentSize().
- MockVideoFrameProvider* provider = LoadAndGetFrameProvider(true);
+ MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
int tokens[] = {0, 33, 66, 100, 133, 166, 200, 233, 266, 300,
333, 366, 400, 433, 466, 500, 533, 566, 600};
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
index 928b1804c68..78ac79672cf 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -72,6 +72,10 @@ MediaStreamRemoteVideoSource::
RemoteVideoSourceDelegate::~RemoteVideoSourceDelegate() {
}
+namespace {
+void DoNothing(const scoped_refptr<rtc::RefCountInterface>& ref) {}
+} // anonymous
+
void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
const cricket::VideoFrame& incoming_frame) {
const base::TimeDelta incoming_timestamp = base::TimeDelta::FromMicroseconds(
@@ -89,16 +93,19 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
incoming_timestamp - start_timestamp_;
scoped_refptr<media::VideoFrame> video_frame;
- if (incoming_frame.video_frame_buffer()->native_handle() != NULL) {
+ scoped_refptr<webrtc::VideoFrameBuffer> buffer(
+ incoming_frame.video_frame_buffer());
+
+ if (buffer->native_handle() != NULL) {
video_frame =
- static_cast<media::VideoFrame*>(
- incoming_frame.video_frame_buffer()->native_handle());
+ static_cast<media::VideoFrame*>(buffer->native_handle());
video_frame->set_timestamp(elapsed_timestamp);
} else {
- const cricket::VideoFrame* frame =
- incoming_frame.GetCopyWithRotationApplied();
-
- gfx::Size size(frame->width(), frame->height());
+ // Note that the GetCopyWithRotationApplied returns a pointer to a
+ // frame owned by incoming_frame.
+ buffer =
+ incoming_frame.GetCopyWithRotationApplied()->video_frame_buffer();
+ gfx::Size size(buffer->width(), buffer->height());
// Make a shallow copy. Both |frame| and |video_frame| will share a single
// reference counted frame buffer. Const cast and hope no one will overwrite
@@ -107,17 +114,17 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
// need to const cast here.
video_frame = media::VideoFrame::WrapExternalYuvData(
media::PIXEL_FORMAT_YV12, size, gfx::Rect(size), size,
- frame->video_frame_buffer()->StrideY(),
- frame->video_frame_buffer()->StrideU(),
- frame->video_frame_buffer()->StrideV(),
- const_cast<uint8_t*>(frame->video_frame_buffer()->DataY()),
- const_cast<uint8_t*>(frame->video_frame_buffer()->DataU()),
- const_cast<uint8_t*>(frame->video_frame_buffer()->DataV()),
+ buffer->StrideY(),
+ buffer->StrideU(),
+ buffer->StrideV(),
+ const_cast<uint8_t*>(buffer->DataY()),
+ const_cast<uint8_t*>(buffer->DataU()),
+ const_cast<uint8_t*>(buffer->DataV()),
elapsed_timestamp);
if (!video_frame)
return;
- video_frame->AddDestructionObserver(
- base::Bind(&base::DeletePointer<cricket::VideoFrame>, frame->Copy()));
+ // The bind ensures that we keep a reference to the underlying buffer.
+ video_frame->AddDestructionObserver(base::Bind(&DoNothing, buffer));
}
video_frame->metadata()->SetTimeTicks(
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
index 5cd94260e38..b921adb8422 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
@@ -128,9 +128,13 @@ TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
base::Closure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(sink, OnVideoFrame()).WillOnce(
RunClosure(quit_closure));
- cricket::WebRtcVideoFrame webrtc_frame;
- webrtc_frame.InitToBlack(320, 240, 1);
- source()->SinkInterfaceForTest()->OnFrame(webrtc_frame);
+ rtc::scoped_refptr<webrtc::I420Buffer> buffer(
+ new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240));
+
+ buffer->SetToBlack();
+
+ source()->SinkInterfaceForTest()->OnFrame(
+ cricket::WebRtcVideoFrame(buffer, 1, webrtc::kVideoRotation_0));
run_loop.Run();
EXPECT_EQ(1, sink.number_of_frames());
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 76888542d54..ea6e87ba9ad 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -20,6 +20,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/common/media/media_stream_messages.h"
#include "content/public/common/content_client.h"
@@ -29,13 +30,12 @@
#include "content/public/common/renderer_preferences.h"
#include "content/public/common/webrtc_ip_handling_policy.h"
#include "content/public/renderer/content_renderer_client.h"
+#include "content/renderer/media/gpu/rtc_video_decoder_factory.h"
+#include "content/renderer/media/gpu/rtc_video_encoder_factory.h"
#include "content/renderer/media/media_stream.h"
#include "content/renderer/media/media_stream_video_source.h"
#include "content/renderer/media/media_stream_video_track.h"
-#include "content/renderer/media/peer_connection_identity_store.h"
#include "content/renderer/media/rtc_peer_connection_handler.h"
-#include "content/renderer/media/rtc_video_decoder_factory.h"
-#include "content/renderer/media/rtc_video_encoder_factory.h"
#include "content/renderer/media/webrtc/stun_field_trial.h"
#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
@@ -61,7 +61,6 @@
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/webrtc/api/dtlsidentitystore.h"
#include "third_party/webrtc/api/mediaconstraintsinterface.h"
#include "third_party/webrtc/base/ssladapter.h"
#include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h"
@@ -186,13 +185,17 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
CHECK(chrome_signaling_thread_.Start());
CHECK(chrome_worker_thread_.Start());
- base::WaitableEvent start_worker_event(true, false);
+ base::WaitableEvent start_worker_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
chrome_worker_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&PeerConnectionDependencyFactory::InitializeWorkerThread,
base::Unretained(this), &worker_thread_, &start_worker_event));
- base::WaitableEvent create_network_manager_event(true, false);
+ base::WaitableEvent create_network_manager_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
chrome_worker_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&PeerConnectionDependencyFactory::
@@ -211,7 +214,9 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
return;
}
- base::WaitableEvent start_signaling_event(true, false);
+ base::WaitableEvent start_signaling_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
chrome_signaling_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&PeerConnectionDependencyFactory::InitializeSignalingThread,
@@ -290,12 +295,6 @@ PeerConnectionDependencyFactory::CreatePeerConnection(
if (!GetPcFactory().get())
return NULL;
- std::unique_ptr<PeerConnectionIdentityStore> identity_store(
- new PeerConnectionIdentityStore(
- base::ThreadTaskRunnerHandle::Get(), GetWebRtcSignalingThread(),
- GURL(web_frame->document().url()),
- GURL(web_frame->document().firstPartyForCookies())));
-
// Copy the flag from Preference associated with this WebFrame.
P2PPortAllocator::Config port_config;
@@ -387,36 +386,20 @@ PeerConnectionDependencyFactory::CreatePeerConnection(
FilteringNetworkManager* filtering_network_manager =
new FilteringNetworkManager(network_manager_, requesting_origin,
media_permission);
- if (media_permission) {
- // Start permission check earlier to reduce any impact to call set up
- // time. It's safe to use Unretained here since both destructor and
- // Initialize can only be called on the worker thread.
- chrome_worker_thread_.task_runner()->PostTask(
- FROM_HERE, base::Bind(&FilteringNetworkManager::Initialize,
- base::Unretained(filtering_network_manager)));
- }
network_manager.reset(filtering_network_manager);
} else {
network_manager.reset(new EmptyNetworkManager(network_manager_));
}
std::unique_ptr<P2PPortAllocator> port_allocator(new P2PPortAllocator(
p2p_socket_dispatcher_, std::move(network_manager), socket_factory_.get(),
- port_config, requesting_origin, chrome_worker_thread_.task_runner()));
+ port_config, requesting_origin));
return GetPcFactory()
->CreatePeerConnection(config, std::move(port_allocator),
- std::move(identity_store), observer)
+ nullptr, observer)
.get();
}
-// static
-rtc::scoped_refptr<rtc::RTCCertificate>
-PeerConnectionDependencyFactory::GenerateDefaultCertificate() {
- std::unique_ptr<rtc::SSLIdentity> identity(rtc::SSLIdentity::Generate(
- webrtc::kIdentityName, rtc::KeyParams::ECDSA(rtc::EC_NIST_P256)));
- return rtc::RTCCertificate::Create(std::move(identity));
-}
-
scoped_refptr<webrtc::MediaStreamInterface>
PeerConnectionDependencyFactory::CreateLocalMediaStream(
const std::string& label) {
@@ -496,7 +479,7 @@ void PeerConnectionDependencyFactory::TryScheduleStunProbeTrial() {
// The underneath IPC channel has to be connected before sending any IPC
// message.
if (!p2p_socket_dispatcher_->connected()) {
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::Bind(&PeerConnectionDependencyFactory::TryScheduleStunProbeTrial,
base::Unretained(this)),
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
index e5e017c5a7c..fc69d224759 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -67,9 +67,6 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
blink::WebRTCPeerConnectionHandler* CreateRTCPeerConnectionHandler(
blink::WebRTCPeerConnectionHandlerClient* client);
- // Generate an ECDSA certificate.
- static rtc::scoped_refptr<rtc::RTCCertificate> GenerateDefaultCertificate();
-
// Asks the PeerConnection factory to create a Local MediaStream object.
virtual scoped_refptr<webrtc::MediaStreamInterface>
CreateLocalMediaStream(const std::string& label);
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc
index 213b2b0d650..2d789a9acc6 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc
@@ -11,7 +11,7 @@
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
+#include "base/threading/thread_task_runner_handle.h"
namespace content {
@@ -109,7 +109,7 @@ WebRtcAudioSink::Adapter::Adapter(
: webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label),
source_(std::move(source)),
signaling_task_runner_(std::move(signaling_task_runner)),
- main_task_runner_(base::MessageLoop::current()->task_runner()) {
+ main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
DCHECK(signaling_task_runner_);
}
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h
index ce302fa88dc..3c437c69431 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h
@@ -21,7 +21,6 @@
#include "media/base/audio_parameters.h"
#include "media/base/audio_push_fifo.h"
#include "third_party/webrtc/api/mediastreamtrack.h"
-#include "third_party/webrtc/media/base/audiorenderer.h"
namespace content {
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc
index 35843d0515c..17641916639 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.cc
@@ -7,21 +7,6 @@
#include "base/logging.h"
namespace content {
-namespace {
-int WebRtcToMediaPlaneType(webrtc::PlaneType type) {
- switch (type) {
- case webrtc::kYPlane:
- return media::VideoFrame::kYPlane;
- case webrtc::kUPlane:
- return media::VideoFrame::kUPlane;
- case webrtc::kVPlane:
- return media::VideoFrame::kVPlane;
- default:
- NOTREACHED();
- return media::VideoFrame::kMaxPlanes;
- }
-}
-} // anonymous namespace
WebRtcVideoFrameAdapter::WebRtcVideoFrameAdapter(
const scoped_refptr<media::VideoFrame>& frame)
@@ -39,12 +24,24 @@ int WebRtcVideoFrameAdapter::height() const {
return frame_->visible_rect().height();
}
-const uint8_t* WebRtcVideoFrameAdapter::data(webrtc::PlaneType type) const {
- return frame_->visible_data(WebRtcToMediaPlaneType(type));
+const uint8_t* WebRtcVideoFrameAdapter::DataY() const {
+ return frame_->visible_data(media::VideoFrame::kYPlane);
+}
+const uint8_t* WebRtcVideoFrameAdapter::DataU() const {
+ return frame_->visible_data(media::VideoFrame::kUPlane);
+}
+const uint8_t* WebRtcVideoFrameAdapter::DataV() const {
+ return frame_->visible_data(media::VideoFrame::kVPlane);
}
-int WebRtcVideoFrameAdapter::stride(webrtc::PlaneType type) const {
- return frame_->stride(WebRtcToMediaPlaneType(type));
+int WebRtcVideoFrameAdapter::StrideY() const {
+ return frame_->stride(media::VideoFrame::kYPlane);
+}
+int WebRtcVideoFrameAdapter::StrideU() const {
+ return frame_->stride(media::VideoFrame::kUPlane);
+}
+int WebRtcVideoFrameAdapter::StrideV() const {
+ return frame_->stride(media::VideoFrame::kVPlane);
}
void* WebRtcVideoFrameAdapter::native_handle() const {
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
index 61555d032ec..46dd87683d0 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
@@ -24,9 +24,13 @@ class WebRtcVideoFrameAdapter : public webrtc::VideoFrameBuffer {
int width() const override;
int height() const override;
- const uint8_t* data(webrtc::PlaneType type) const override;
+ const uint8_t* DataY() const override;
+ const uint8_t* DataU() const override;
+ const uint8_t* DataV() const override;
- int stride(webrtc::PlaneType type) const override;
+ int StrideY() const override;
+ int StrideU() const override;
+ int StrideV() const override;
void* native_handle() const override;
diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.cc b/chromium/content/renderer/media/webrtc_audio_device_impl.cc
index 7f46506fada..2cb2eacbb32 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/chromium/content/renderer/media/webrtc_audio_device_impl.cc
@@ -4,6 +4,7 @@
#include "content/renderer/media/webrtc_audio_device_impl.h"
+#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
#include "base/win/windows_version.h"
@@ -62,9 +63,15 @@ void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus,
int sample_rate,
int audio_delay_milliseconds,
base::TimeDelta* current_time) {
- DCHECK(audio_renderer_thread_checker_.CalledOnValidThread());
{
base::AutoLock auto_lock(lock_);
+#if DCHECK_IS_ON()
+ DCHECK(renderer_->CurrentThreadIsRenderingThread());
+ if (!audio_renderer_thread_checker_.CalledOnValidThread()) {
+ for (const auto& sink : playout_sinks_)
+ sink->OnRenderThreadChanged();
+ }
+#endif
if (!playing_) {
// Force silence to AudioBus after stopping playout in case
// there is lingering audio data in AudioBus.
diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.h b/chromium/content/renderer/media/webrtc_audio_device_impl.h
index 6af4a869356..1e3f05f1a64 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_impl.h
+++ b/chromium/content/renderer/media/webrtc_audio_device_impl.h
@@ -219,7 +219,7 @@ class WebRtcPlayoutDataSource {
class Sink {
public:
// Callback to get the playout data.
- // Called on the render audio thread.
+ // Called on the audio render thread.
virtual void OnPlayoutData(media::AudioBus* audio_bus,
int sample_rate,
int audio_delay_milliseconds) = 0;
@@ -228,6 +228,11 @@ class WebRtcPlayoutDataSource {
// Called on the main render thread.
virtual void OnPlayoutDataSourceChanged() = 0;
+ // Called to notify that the audio render thread has changed, and
+ // OnPlayoutData() will from now on be called on the new thread.
+ // Called on the new audio render thread.
+ virtual void OnRenderThreadChanged() = 0;
+
protected:
virtual ~Sink() {}
};
diff --git a/chromium/content/renderer/media/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc_audio_renderer.cc
index 604ed959a0d..da693872812 100644
--- a/chromium/content/renderer/media/webrtc_audio_renderer.cc
+++ b/chromium/content/renderer/media/webrtc_audio_renderer.cc
@@ -20,10 +20,10 @@
#include "content/renderer/media/webrtc_logging.h"
#include "media/audio/sample_rates.h"
#include "media/base/audio_capturer_source.h"
+#include "media/base/audio_latency.h"
#include "media/base/audio_parameters.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/webrtc/api/mediastreaminterface.h"
-#include "third_party/webrtc/media/base/audiorenderer.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
@@ -153,39 +153,6 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer {
} // namespace
-int WebRtcAudioRenderer::GetOptimalBufferSize(int sample_rate,
- int hardware_buffer_size) {
- // Use native hardware buffer size as default. On Windows, we strive to open
- // up using this native hardware buffer size to achieve best
- // possible performance and to ensure that no FIFO is needed on the browser
- // side to match the client request. That is why there is no #if case for
- // Windows below.
- int frames_per_buffer = hardware_buffer_size;
-
-#if defined(OS_LINUX) || defined(OS_MACOSX)
- // On Linux and MacOS, the low level IO implementations on the browser side
- // supports all buffer size the clients want. We use the native peer
- // connection buffer size (10ms) to achieve best possible performance.
- frames_per_buffer = sample_rate / 100;
-#elif defined(OS_ANDROID)
- // TODO(henrika): Keep tuning this scheme and espcicially for low-latency
- // cases. Might not be possible to come up with the perfect solution using
- // the render side only.
- int frames_per_10ms = sample_rate / 100;
- if (frames_per_buffer < 2 * frames_per_10ms) {
- // Examples of low-latency frame sizes and the resulting |buffer_size|:
- // Nexus 7 : 240 audio frames => 2*480 = 960
- // Nexus 10 : 256 => 2*441 = 882
- // Galaxy Nexus: 144 => 2*441 = 882
- frames_per_buffer = 2 * frames_per_10ms;
- DVLOG(1) << "Low-latency output detected on Android";
- }
-#endif
-
- DVLOG(1) << "Using sink output buffer size: " << frames_per_buffer;
- return frames_per_buffer;
-}
-
WebRtcAudioRenderer::WebRtcAudioRenderer(
const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread,
const blink::WebMediaStream& media_stream,
@@ -209,7 +176,6 @@ WebRtcAudioRenderer::WebRtcAudioRenderer(
WebRtcLogMessage(base::StringPrintf(
"WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i",
source_render_frame_id, session_id, sink_params_.effects()));
- audio_renderer_thread_checker_.DetachFromThread();
}
WebRtcAudioRenderer::~WebRtcAudioRenderer() {
@@ -241,7 +207,7 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
PrepareSink();
{
// No need to reassert the preconditions because the other thread accessing
- // the fields (checked by |audio_renderer_thread_checker_|) only reads them.
+ // the fields only reads them.
base::AutoLock auto_lock(lock_);
source_ = source;
@@ -267,6 +233,10 @@ bool WebRtcAudioRenderer::IsStarted() const {
return start_ref_count_ != 0;
}
+bool WebRtcAudioRenderer::CurrentThreadIsRenderingThread() {
+ return sink_->CurrentThreadIsRenderingThread();
+}
+
void WebRtcAudioRenderer::Start() {
DVLOG(1) << "WebRtcAudioRenderer::Start()";
DCHECK(thread_checker_.CalledOnValidThread());
@@ -407,7 +377,6 @@ void WebRtcAudioRenderer::SwitchOutputDevice(
// callback may currently be executing and trying to grab the lock while we're
// stopping the thread on which it runs.
sink_->Stop();
- audio_renderer_thread_checker_.DetachFromThread();
sink_ = new_sink;
output_device_id_ = device_id;
security_origin_ = security_origin;
@@ -424,7 +393,7 @@ void WebRtcAudioRenderer::SwitchOutputDevice(
int WebRtcAudioRenderer::Render(media::AudioBus* audio_bus,
uint32_t frames_delayed,
uint32_t frames_skipped) {
- DCHECK(audio_renderer_thread_checker_.CalledOnValidThread());
+ DCHECK(sink_->CurrentThreadIsRenderingThread());
base::AutoLock auto_lock(lock_);
if (!source_)
return 0;
@@ -481,7 +450,7 @@ void WebRtcAudioRenderer::OnRenderError() {
// Called by AudioPullFifo when more data is necessary.
void WebRtcAudioRenderer::SourceCallback(
int fifo_frame_delay, media::AudioBus* audio_bus) {
- DCHECK(audio_renderer_thread_checker_.CalledOnValidThread());
+ DCHECK(sink_->CurrentThreadIsRenderingThread());
base::TimeTicks start_time = base::TimeTicks::Now();
DVLOG(2) << "WebRtcAudioRenderer::SourceCallback("
<< fifo_frame_delay << ", "
@@ -654,7 +623,7 @@ void WebRtcAudioRenderer::PrepareSink() {
DVLOG(1) << "Using WebRTC output buffer size: " << source_frames_per_buffer;
// Setup sink parameters.
- const int sink_frames_per_buffer = GetOptimalBufferSize(
+ const int sink_frames_per_buffer = media::AudioLatency::GetRtcBufferSize(
sample_rate, device_info.output_params().frames_per_buffer());
new_sink_params.set_sample_rate(sample_rate);
new_sink_params.set_frames_per_buffer(sink_frames_per_buffer);
diff --git a/chromium/content/renderer/media/webrtc_audio_renderer.h b/chromium/content/renderer/media/webrtc_audio_renderer.h
index f13ac8d5bef..f4f677ee58f 100644
--- a/chromium/content/renderer/media/webrtc_audio_renderer.h
+++ b/chromium/content/renderer/media/webrtc_audio_renderer.h
@@ -73,10 +73,6 @@ class CONTENT_EXPORT WebRtcAudioRenderer
float volume_;
};
-
- // Returns platform specific optimal buffer size for rendering audio.
- static int GetOptimalBufferSize(int sample_rate, int hardware_buffer_size);
-
WebRtcAudioRenderer(
const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread,
const blink::WebMediaStream& media_stream,
@@ -109,6 +105,9 @@ class CONTENT_EXPORT WebRtcAudioRenderer
int sample_rate() const { return sink_params_.sample_rate(); }
int frames_per_buffer() const { return sink_params_.frames_per_buffer(); }
+ // Returns true if called on rendering thread, otherwise false.
+ bool CurrentThreadIsRenderingThread();
+
private:
// MediaStreamAudioRenderer implementation. This is private since we want
// callers to use proxy objects.
@@ -155,7 +154,6 @@ class CONTENT_EXPORT WebRtcAudioRenderer
// Used to DCHECK that we are called on the correct thread.
base::ThreadChecker thread_checker_;
- base::ThreadChecker audio_renderer_thread_checker_;
// Flag to keep track the state of the renderer.
State state_;
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
index d77df9ac552..af465017c68 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
@@ -130,8 +130,8 @@ void WebRtcLocalAudioSourceProvider::provideInput(
audio_converter_->Convert(output_wrapper_.get());
}
-double WebRtcLocalAudioSourceProvider::ProvideInput(
- media::AudioBus* audio_bus, base::TimeDelta buffer_delay) {
+double WebRtcLocalAudioSourceProvider::ProvideInput(media::AudioBus* audio_bus,
+ uint32_t frames_delayed) {
if (fifo_->frames() >= audio_bus->frames()) {
fifo_->Consume(audio_bus, 0, audio_bus->frames());
} else {
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider.h b/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
index f5a867fc949..cbf8d7980ad 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
@@ -75,7 +75,7 @@ class CONTENT_EXPORT WebRtcLocalAudioSourceProvider
// This function is triggered by provideInput()on the WebAudio audio thread,
// so it has been under the protection of |lock_|.
double ProvideInput(media::AudioBus* audio_bus,
- base::TimeDelta buffer_delay) override;
+ uint32_t frames_delayed) override;
// Method to allow the unittests to inject its own sink parameters to avoid
// query the hardware.
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
index 6eda8f178ec..b4013097e2d 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
@@ -33,7 +33,7 @@ class WebRtcLocalAudioSourceProviderTest : public testing::Test {
false /* remote */);
blink_track_.initialize(blink::WebString::fromUTF8("audio_track"),
audio_source);
- blink_track_.setExtraData(new MediaStreamAudioTrack(true));
+ blink_track_.setTrackData(new MediaStreamAudioTrack(true));
source_provider_.reset(new WebRtcLocalAudioSourceProvider(blink_track_));
source_provider_->SetSinkParamsForTesting(sink_params_);
source_provider_->OnSetFormat(source_params_);
diff --git a/chromium/content/renderer/mojo/blink_service_registry_impl.cc b/chromium/content/renderer/mojo/blink_service_registry_impl.cc
index 6a2fdf09a6a..408f6de8064 100644
--- a/chromium/content/renderer/mojo/blink_service_registry_impl.cc
+++ b/chromium/content/renderer/mojo/blink_service_registry_impl.cc
@@ -6,23 +6,36 @@
#include <utility>
-#include "content/common/mojo/service_registry_impl.h"
+#include "base/bind.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "services/shell/public/cpp/interface_provider.h"
namespace content {
BlinkServiceRegistryImpl::BlinkServiceRegistryImpl(
- base::WeakPtr<content::ServiceRegistry> service_registry)
- : service_registry_(service_registry) {}
+ base::WeakPtr<shell::InterfaceProvider> remote_interfaces)
+ : remote_interfaces_(remote_interfaces),
+ main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ weak_ptr_factory_(this) {}
BlinkServiceRegistryImpl::~BlinkServiceRegistryImpl() = default;
void BlinkServiceRegistryImpl::connectToRemoteService(
const char* name,
mojo::ScopedMessagePipeHandle handle) {
- if (!service_registry_)
+ if (!main_thread_task_runner_->BelongsToCurrentThread()) {
+ main_thread_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&BlinkServiceRegistryImpl::connectToRemoteService,
+ weak_ptr_factory_.GetWeakPtr(), name,
+ base::Passed(&handle)));
return;
+ }
- service_registry_->ConnectToRemoteService(name, std::move(handle));
+ if (!remote_interfaces_)
+ return;
+
+ remote_interfaces_->GetInterface(name, std::move(handle));
}
} // namespace content
diff --git a/chromium/content/renderer/mojo/blink_service_registry_impl.h b/chromium/content/renderer/mojo/blink_service_registry_impl.h
index 8bd86321e68..2fc08ae35f3 100644
--- a/chromium/content/renderer/mojo/blink_service_registry_impl.h
+++ b/chromium/content/renderer/mojo/blink_service_registry_impl.h
@@ -6,20 +6,27 @@
#define CONTENT_RENDERER_MOJO_BLINK_SERVICE_REGISTRY_IMPL_H_
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "third_party/WebKit/public/platform/ServiceRegistry.h"
-namespace content {
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace shell {
+class InterfaceProvider;
+}
-class ServiceRegistry;
+namespace content {
// An implementation of blink::ServiceRegistry that forwards to a
-// content::ServiceRegistry.
+// shell::InterfaceProvider.
class BlinkServiceRegistryImpl : public blink::ServiceRegistry {
public:
explicit BlinkServiceRegistryImpl(
- base::WeakPtr<content::ServiceRegistry> service_registry);
+ base::WeakPtr<shell::InterfaceProvider> remote_interfaces);
~BlinkServiceRegistryImpl();
// blink::ServiceRegistry override.
@@ -27,7 +34,11 @@ class BlinkServiceRegistryImpl : public blink::ServiceRegistry {
mojo::ScopedMessagePipeHandle handle) override;
private:
- const base::WeakPtr<content::ServiceRegistry> service_registry_;
+ const base::WeakPtr<shell::InterfaceProvider> remote_interfaces_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+
+ base::WeakPtrFactory<BlinkServiceRegistryImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BlinkServiceRegistryImpl);
};
diff --git a/chromium/content/renderer/mojo/interface_provider_js_wrapper.cc b/chromium/content/renderer/mojo/interface_provider_js_wrapper.cc
new file mode 100644
index 00000000000..174455d525a
--- /dev/null
+++ b/chromium/content/renderer/mojo/interface_provider_js_wrapper.cc
@@ -0,0 +1,112 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/mojo/interface_provider_js_wrapper.h"
+
+#include <memory>
+#include <utility>
+
+#include "mojo/edk/js/handle.h"
+#include "services/shell/public/cpp/interface_provider.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+
+namespace content {
+
+gin::WrapperInfo InterfaceProviderJsWrapper::kWrapperInfo = {
+ gin::kEmbedderNativeGin};
+const char InterfaceProviderJsWrapper::kPerFrameModuleName[] =
+ "content/public/renderer/frame_service_registry";
+const char InterfaceProviderJsWrapper::kPerProcessModuleName[] =
+ "content/public/renderer/service_registry";
+
+InterfaceProviderJsWrapper::~InterfaceProviderJsWrapper() {
+}
+
+// static
+gin::Handle<InterfaceProviderJsWrapper>
+InterfaceProviderJsWrapper::Create(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Context> context,
+ shell::InterfaceProvider* remote_interfaces) {
+ return gin::CreateHandle(
+ isolate,
+ new InterfaceProviderJsWrapper(
+ isolate, context,
+ remote_interfaces->GetWeakPtr()));
+}
+
+gin::ObjectTemplateBuilder
+InterfaceProviderJsWrapper::GetObjectTemplateBuilder(v8::Isolate* isolate) {
+ return Wrappable<InterfaceProviderJsWrapper>::GetObjectTemplateBuilder(
+ isolate)
+ .SetMethod("connectToService",
+ &InterfaceProviderJsWrapper::GetInterface)
+ .SetMethod("addServiceOverrideForTesting",
+ &InterfaceProviderJsWrapper::AddOverrideForTesting)
+ .SetMethod("clearServiceOverridesForTesting",
+ &InterfaceProviderJsWrapper::ClearOverridesForTesting);
+}
+
+mojo::Handle InterfaceProviderJsWrapper::GetInterface(
+ const std::string& interface_name) {
+ mojo::MessagePipe pipe;
+ if (remote_interfaces_) {
+ remote_interfaces_->GetInterface(
+ interface_name, std::move(pipe.handle0));
+ }
+ return pipe.handle1.release();
+}
+
+void InterfaceProviderJsWrapper::AddOverrideForTesting(
+ const std::string& interface_name,
+ v8::Local<v8::Function> service_factory) {
+ ScopedJsFactory factory(v8::Isolate::GetCurrent(), service_factory);
+ shell::InterfaceProvider::TestApi test_api(remote_interfaces_.get());
+ test_api.SetBinderForName(
+ interface_name,
+ base::Bind(&InterfaceProviderJsWrapper::CallJsFactory,
+ weak_factory_.GetWeakPtr(), factory));
+}
+
+void InterfaceProviderJsWrapper::ClearOverridesForTesting() {
+ shell::InterfaceProvider::TestApi test_api(remote_interfaces_.get());
+ test_api.ClearBinders();
+}
+
+InterfaceProviderJsWrapper::InterfaceProviderJsWrapper(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Context> context,
+ base::WeakPtr<shell::InterfaceProvider> remote_interfaces)
+ : isolate_(isolate),
+ context_(isolate, context),
+ remote_interfaces_(remote_interfaces),
+ weak_factory_(this) {
+ context_.SetWeak(this, &InterfaceProviderJsWrapper::ClearContext,
+ v8::WeakCallbackType::kParameter);
+}
+
+void InterfaceProviderJsWrapper::CallJsFactory(
+ const ScopedJsFactory& factory,
+ mojo::ScopedMessagePipeHandle pipe) {
+ if (context_.IsEmpty())
+ return;
+
+ v8::HandleScope handle_scope(isolate_);
+ v8::Handle<v8::Context> context = context_.Get(isolate_);
+ v8::Context::Scope context_scope(context);
+ v8::Local<v8::Value> argv[] = {
+ gin::ConvertToV8(isolate_, mojo::Handle(pipe.release().value()))};
+ blink::WebLocalFrame::frameForContext(context)
+ ->callFunctionEvenIfScriptDisabled(factory.Get(isolate_),
+ v8::Undefined(isolate_), 1, argv);
+}
+
+// static
+void InterfaceProviderJsWrapper::ClearContext(
+ const v8::WeakCallbackInfo<InterfaceProviderJsWrapper>& data) {
+ InterfaceProviderJsWrapper* registry = data.GetParameter();
+ registry->context_.Reset();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/mojo/interface_provider_js_wrapper.h b/chromium/content/renderer/mojo/interface_provider_js_wrapper.h
new file mode 100644
index 00000000000..0c5c6eb9bac
--- /dev/null
+++ b/chromium/content/renderer/mojo/interface_provider_js_wrapper.h
@@ -0,0 +1,75 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MOJO_INTERFACE_PROVIDER_JS_WRAPPER_H_
+#define CONTENT_RENDERER_MOJO_INTERFACE_PROVIDER_JS_WRAPPER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "gin/wrappable.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "v8/include/v8.h"
+
+namespace shell {
+class InterfaceProvider;
+}
+
+namespace content {
+
+// A JS wrapper around shell::InterfaceProvider that allows connecting to
+// remote services.
+class CONTENT_EXPORT InterfaceProviderJsWrapper
+ : public gin::Wrappable<InterfaceProviderJsWrapper> {
+ public:
+ ~InterfaceProviderJsWrapper() override;
+ static gin::Handle<InterfaceProviderJsWrapper> Create(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Context> context,
+ shell::InterfaceProvider* remote_interfaces);
+
+ // gin::Wrappable<InterfaceProviderJsWrapper> overrides.
+ gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) override;
+
+ // JS interface implementation.
+ void AddOverrideForTesting(const std::string& interface_name,
+ v8::Local<v8::Function> interface_factory);
+ void ClearOverridesForTesting();
+ mojo::Handle GetInterface(const std::string& interface_name);
+
+ static gin::WrapperInfo kWrapperInfo;
+ static const char kPerFrameModuleName[];
+ static const char kPerProcessModuleName[];
+
+ private:
+ using ScopedJsFactory =
+ v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>>;
+
+ InterfaceProviderJsWrapper(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Context> context,
+ base::WeakPtr<shell::InterfaceProvider> remote_interfaces);
+
+ void CallJsFactory(const ScopedJsFactory& factory,
+ mojo::ScopedMessagePipeHandle pipe);
+
+ static void ClearContext(
+ const v8::WeakCallbackInfo<InterfaceProviderJsWrapper>& data);
+
+ v8::Isolate* isolate_;
+ v8::Global<v8::Context> context_;
+ base::WeakPtr<shell::InterfaceProvider> remote_interfaces_;
+
+ base::WeakPtrFactory<InterfaceProviderJsWrapper> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(InterfaceProviderJsWrapper);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MOJO_INTERFACE_PROVIDER_JS_WRAPPER_H_
diff --git a/chromium/content/renderer/mojo/service_registry_js_wrapper.cc b/chromium/content/renderer/mojo/service_registry_js_wrapper.cc
deleted file mode 100644
index 8b5793820e3..00000000000
--- a/chromium/content/renderer/mojo/service_registry_js_wrapper.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/mojo/service_registry_js_wrapper.h"
-
-#include <memory>
-#include <utility>
-
-#include "content/common/mojo/service_registry_impl.h"
-#include "content/public/common/service_registry.h"
-#include "mojo/edk/js/handle.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-
-namespace content {
-
-gin::WrapperInfo ServiceRegistryJsWrapper::kWrapperInfo = {
- gin::kEmbedderNativeGin};
-const char ServiceRegistryJsWrapper::kPerFrameModuleName[] =
- "content/public/renderer/frame_service_registry";
-const char ServiceRegistryJsWrapper::kPerProcessModuleName[] =
- "content/public/renderer/service_registry";
-
-ServiceRegistryJsWrapper::~ServiceRegistryJsWrapper() {
-}
-
-// static
-gin::Handle<ServiceRegistryJsWrapper> ServiceRegistryJsWrapper::Create(
- v8::Isolate* isolate,
- v8::Handle<v8::Context> context,
- ServiceRegistry* service_registry) {
- return gin::CreateHandle(
- isolate,
- new ServiceRegistryJsWrapper(
- isolate, context,
- static_cast<ServiceRegistryImpl*>(service_registry)->GetWeakPtr()));
-}
-
-gin::ObjectTemplateBuilder ServiceRegistryJsWrapper::GetObjectTemplateBuilder(
- v8::Isolate* isolate) {
- return Wrappable<ServiceRegistryJsWrapper>::GetObjectTemplateBuilder(isolate)
- .SetMethod("connectToService",
- &ServiceRegistryJsWrapper::ConnectToService)
- .SetMethod("addServiceOverrideForTesting",
- &ServiceRegistryJsWrapper::AddServiceOverrideForTesting)
- .SetMethod("clearServiceOverridesForTesting",
- &ServiceRegistryJsWrapper::ClearServiceOverridesForTesting);
-}
-
-mojo::Handle ServiceRegistryJsWrapper::ConnectToService(
- const std::string& service_name) {
- mojo::MessagePipe pipe;
- if (service_registry_)
- service_registry_->ConnectToRemoteService(service_name,
- std::move(pipe.handle0));
- return pipe.handle1.release();
-}
-
-void ServiceRegistryJsWrapper::AddServiceOverrideForTesting(
- const std::string& service_name,
- v8::Local<v8::Function> service_factory) {
- ServiceRegistry* registry = service_registry_.get();
- if (!registry)
- return;
- ScopedJsFactory factory(v8::Isolate::GetCurrent(), service_factory);
- registry->AddServiceOverrideForTesting(
- service_name, base::Bind(&ServiceRegistryJsWrapper::CallJsFactory,
- weak_factory_.GetWeakPtr(), factory));
-}
-
-void ServiceRegistryJsWrapper::ClearServiceOverridesForTesting() {
- ServiceRegistryImpl* registry =
- static_cast<ServiceRegistryImpl*>(service_registry_.get());
- if (!registry)
- return;
-
- registry->ClearServiceOverridesForTesting();
-}
-
-ServiceRegistryJsWrapper::ServiceRegistryJsWrapper(
- v8::Isolate* isolate,
- v8::Handle<v8::Context> context,
- base::WeakPtr<ServiceRegistry> service_registry)
- : isolate_(isolate),
- context_(isolate, context),
- service_registry_(service_registry),
- weak_factory_(this) {
- context_.SetWeak(this, &ServiceRegistryJsWrapper::ClearContext,
- v8::WeakCallbackType::kParameter);
-}
-
-void ServiceRegistryJsWrapper::CallJsFactory(
- const ScopedJsFactory& factory,
- mojo::ScopedMessagePipeHandle pipe) {
- if (context_.IsEmpty())
- return;
-
- v8::HandleScope handle_scope(isolate_);
- v8::Handle<v8::Context> context = context_.Get(isolate_);
- v8::Context::Scope context_scope(context);
- v8::Local<v8::Value> argv[] = {
- gin::ConvertToV8(isolate_, mojo::Handle(pipe.release().value()))};
- blink::WebLocalFrame::frameForContext(context)
- ->callFunctionEvenIfScriptDisabled(factory.Get(isolate_),
- v8::Undefined(isolate_), 1, argv);
-}
-
-// static
-void ServiceRegistryJsWrapper::ClearContext(
- const v8::WeakCallbackInfo<ServiceRegistryJsWrapper>& data) {
- ServiceRegistryJsWrapper* service_registry = data.GetParameter();
- service_registry->context_.Reset();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/mojo/service_registry_js_wrapper.h b/chromium/content/renderer/mojo/service_registry_js_wrapper.h
deleted file mode 100644
index 5fc2f63729b..00000000000
--- a/chromium/content/renderer/mojo/service_registry_js_wrapper.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MOJO_SERVICE_REGISTRY_JS_WRAPPER_H_
-#define CONTENT_RENDERER_MOJO_SERVICE_REGISTRY_JS_WRAPPER_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "gin/handle.h"
-#include "gin/object_template_builder.h"
-#include "gin/wrappable.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-#include "v8/include/v8.h"
-
-namespace content {
-
-class ServiceRegistry;
-
-// A JS wrapper around ServiceRegistry that allows connecting to remote
-// services.
-class CONTENT_EXPORT ServiceRegistryJsWrapper
- : public gin::Wrappable<ServiceRegistryJsWrapper> {
- public:
- ~ServiceRegistryJsWrapper() override;
- static gin::Handle<ServiceRegistryJsWrapper> Create(
- v8::Isolate* isolate,
- v8::Handle<v8::Context> context,
- ServiceRegistry* service_registry);
-
- // gin::Wrappable<ServiceRegistryJsWrapper> overrides.
- gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
- v8::Isolate* isolate) override;
-
- // JS interface implementation.
- void AddServiceOverrideForTesting(const std::string& service_name,
- v8::Local<v8::Function> service_factory);
- void ClearServiceOverridesForTesting();
- mojo::Handle ConnectToService(const std::string& service_name);
-
- static gin::WrapperInfo kWrapperInfo;
- static const char kPerFrameModuleName[];
- static const char kPerProcessModuleName[];
-
- private:
- using ScopedJsFactory =
- v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>>;
-
- ServiceRegistryJsWrapper(v8::Isolate* isolate,
- v8::Handle<v8::Context> context,
- base::WeakPtr<ServiceRegistry> service_registry);
-
- void CallJsFactory(const ScopedJsFactory& factory,
- mojo::ScopedMessagePipeHandle pipe);
-
- static void ClearContext(
- const v8::WeakCallbackInfo<ServiceRegistryJsWrapper>& data);
-
- v8::Isolate* isolate_;
- v8::Global<v8::Context> context_;
- base::WeakPtr<ServiceRegistry> service_registry_;
-
- base::WeakPtrFactory<ServiceRegistryJsWrapper> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceRegistryJsWrapper);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MOJO_SERVICE_REGISTRY_JS_WRAPPER_H_
diff --git a/chromium/content/renderer/mojo_bindings_controller.cc b/chromium/content/renderer/mojo_bindings_controller.cc
index 135c5adf0ef..56cf602c0c3 100644
--- a/chromium/content/renderer/mojo_bindings_controller.cc
+++ b/chromium/content/renderer/mojo_bindings_controller.cc
@@ -98,4 +98,8 @@ void MojoBindingsController::DidClearWindowObject() {
DestroyContextState(render_frame()->GetWebFrame()->mainWorldScriptContext());
}
+void MojoBindingsController::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/mojo_bindings_controller.h b/chromium/content/renderer/mojo_bindings_controller.h
index d26f17a85cf..b0a3fb6f8e8 100644
--- a/chromium/content/renderer/mojo_bindings_controller.h
+++ b/chromium/content/renderer/mojo_bindings_controller.h
@@ -43,6 +43,7 @@ class MojoBindingsController
void WillReleaseScriptContext(v8::Local<v8::Context> context,
int world_id) override;
void DidClearWindowObject() override;
+ void OnDestruct() override;
const bool for_layout_tests_;
diff --git a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc
index 2a0fd6b4778..685da6d7b57 100644
--- a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc
+++ b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc
@@ -30,7 +30,7 @@ class MouseLockDispatcherTest : public RenderViewTest {
public:
void SetUp() override {
RenderViewTest::SetUp();
- route_id_ = view()->GetRoutingID();
+ route_id_ = view()->GetWidget()->routing_id();
target_ = new MockLockTarget();
alternate_target_ = new MockLockTarget();
}
@@ -43,6 +43,7 @@ class MouseLockDispatcherTest : public RenderViewTest {
protected:
RenderViewImpl* view() { return static_cast<RenderViewImpl*>(view_); }
+ RenderWidget* widget() { return view()->GetWidget(); }
MouseLockDispatcher* dispatcher() { return view()->mouse_lock_dispatcher(); }
int route_id_;
MockLockTarget* target_;
@@ -54,22 +55,22 @@ class MouseLockDispatcherTest : public RenderViewTest {
// Test simple use of RenderViewImpl interface to WebKit for pointer lock.
TEST_F(MouseLockDispatcherTest, BasicWebWidget) {
// Start unlocked.
- EXPECT_FALSE(view()->isPointerLocked());
+ EXPECT_FALSE(widget()->isPointerLocked());
// Lock.
- EXPECT_TRUE(view()->requestPointerLock());
- view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
- EXPECT_TRUE(view()->isPointerLocked());
+ EXPECT_TRUE(widget()->requestPointerLock());
+ widget()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
+ EXPECT_TRUE(widget()->isPointerLocked());
// Unlock.
- view()->requestPointerUnlock();
- view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
- EXPECT_FALSE(view()->isPointerLocked());
+ widget()->requestPointerUnlock();
+ widget()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
+ EXPECT_FALSE(widget()->isPointerLocked());
// Attempt a lock, and have it fail.
- EXPECT_TRUE(view()->requestPointerLock());
- view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, false));
- EXPECT_FALSE(view()->isPointerLocked());
+ EXPECT_TRUE(widget()->requestPointerLock());
+ widget()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, false));
+ EXPECT_FALSE(widget()->isPointerLocked());
}
// Test simple use of MouseLockDispatcher with a mock LockTarget.
@@ -86,7 +87,7 @@ TEST_F(MouseLockDispatcherTest, BasicMockLockTarget) {
// Lock.
EXPECT_TRUE(dispatcher()->LockMouse(target_));
- view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
+ widget()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
// Receive mouse event.
@@ -94,12 +95,12 @@ TEST_F(MouseLockDispatcherTest, BasicMockLockTarget) {
// Unlock.
dispatcher()->UnlockMouse(target_);
- view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
+ widget()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
// Attempt a lock, and have it fail.
EXPECT_TRUE(dispatcher()->LockMouse(target_));
- view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, false));
+ widget()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, false));
EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
}
@@ -112,7 +113,7 @@ TEST_F(MouseLockDispatcherTest, DeleteAndUnlock) {
// Lock.
EXPECT_TRUE(dispatcher()->LockMouse(target_));
- view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
+ widget()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
// Unlock, with a deleted target.
@@ -121,7 +122,7 @@ TEST_F(MouseLockDispatcherTest, DeleteAndUnlock) {
delete target_;
target_ = NULL;
dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
- view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
+ widget()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
}
@@ -140,7 +141,7 @@ TEST_F(MouseLockDispatcherTest, DeleteWithPendingLockSuccess) {
target_ = NULL;
// Lock response.
- view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
+ widget()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
}
// Test deleting a target that is pending a lock request failure response.
@@ -158,7 +159,7 @@ TEST_F(MouseLockDispatcherTest, DeleteWithPendingLockFail) {
target_ = NULL;
// Lock response.
- view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, false));
+ widget()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, false));
}
// Test not receiving mouse events when a target is not locked.
@@ -175,7 +176,7 @@ TEST_F(MouseLockDispatcherTest, MouseEventsNotReceived) {
// Lock.
EXPECT_TRUE(dispatcher()->LockMouse(target_));
- view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
+ widget()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
// Receive mouse event.
@@ -183,7 +184,7 @@ TEST_F(MouseLockDispatcherTest, MouseEventsNotReceived) {
// Unlock.
dispatcher()->UnlockMouse(target_);
- view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
+ widget()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
// (Don't) receive mouse event.
@@ -208,7 +209,7 @@ TEST_F(MouseLockDispatcherTest, MultipleTargets) {
EXPECT_FALSE(dispatcher()->LockMouse(alternate_target_));
// Lock completion for target.
- view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
+ widget()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
// Fail attempt to lock alternate.
@@ -226,7 +227,7 @@ TEST_F(MouseLockDispatcherTest, MultipleTargets) {
// Though the call to UnlockMouse should not unlock any target, we will
// cause an unlock (as if e.g. user escaped mouse lock) and verify the
// correct target is unlocked.
- view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
+ widget()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
}
diff --git a/chromium/content/renderer/mus/BUILD.gn b/chromium/content/renderer/mus/BUILD.gn
index c2d3f93d317..12500af1f8b 100644
--- a/chromium/content/renderer/mus/BUILD.gn
+++ b/chromium/content/renderer/mus/BUILD.gn
@@ -26,12 +26,10 @@ source_set("mus") {
"//content/public/common:common_sources",
"//mojo/common",
"//mojo/converters/blink",
- "//mojo/converters/geometry",
- "//mojo/converters/input_events",
- "//mojo/converters/surfaces",
"//services/shell/public/cpp",
"//third_party/WebKit/public:blink",
"//ui/events:events",
"//ui/events:events_base",
+ "//ui/gfx/geometry/mojo",
]
}
diff --git a/chromium/content/renderer/mus/compositor_mus_connection.cc b/chromium/content/renderer/mus/compositor_mus_connection.cc
index fe2445fc600..322fa11becb 100644
--- a/chromium/content/renderer/mus/compositor_mus_connection.cc
+++ b/chromium/content/renderer/mus/compositor_mus_connection.cc
@@ -9,8 +9,8 @@
#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/mus/render_widget_mus_connection.h"
#include "mojo/converters/blink/blink_input_events_type_converters.h"
-#include "mojo/converters/input_events/input_events_type_converters.h"
#include "ui/events/latency_info.h"
+#include "ui/events/mojo/event.mojom.h"
using mus::mojom::EventResult;
@@ -36,7 +36,7 @@ CompositorMusConnection::CompositorMusConnection(
DCHECK(main_task_runner_->BelongsToCurrentThread());
compositor_task_runner_->PostTask(
FROM_HERE, base::Bind(&CompositorMusConnection::
- CreateWindowTreeConnectionOnCompositorThread,
+ CreateWindowTreeClientOnCompositorThread,
this, base::Passed(std::move(request))));
}
@@ -61,12 +61,10 @@ void CompositorMusConnection::AttachSurfaceOnCompositorThread(
}
}
-void CompositorMusConnection::CreateWindowTreeConnectionOnCompositorThread(
+void CompositorMusConnection::CreateWindowTreeClientOnCompositorThread(
mojo::InterfaceRequest<mus::mojom::WindowTreeClient> request) {
DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- mus::WindowTreeConnection::Create(
- this, std::move(request),
- mus::WindowTreeConnection::CreateType::DONT_WAIT_FOR_EMBED);
+ new mus::WindowTreeClient(this, nullptr, std::move(request));
}
void CompositorMusConnection::OnConnectionLostOnMainThread() {
@@ -98,8 +96,8 @@ void CompositorMusConnection::OnWindowInputEventAckOnMainThread(
compositor_task_runner_->PostTask(FROM_HERE, base::Bind(ack, result));
}
-void CompositorMusConnection::OnConnectionLost(
- mus::WindowTreeConnection* connection) {
+void CompositorMusConnection::OnWindowTreeClientDestroyed(
+ mus::WindowTreeClient* client) {
DCHECK(compositor_task_runner_->BelongsToCurrentThread());
main_task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/content/renderer/mus/compositor_mus_connection.h b/chromium/content/renderer/mus/compositor_mus_connection.h
index d8a75a67df5..a49b3a7bc2f 100644
--- a/chromium/content/renderer/mus/compositor_mus_connection.h
+++ b/chromium/content/renderer/mus/compositor_mus_connection.h
@@ -10,8 +10,8 @@
#include "base/macros.h"
#include "components/mus/public/cpp/input_event_handler.h"
#include "components/mus/public/cpp/window.h"
-#include "components/mus/public/cpp/window_tree_connection.h"
-#include "components/mus/public/cpp/window_tree_delegate.h"
+#include "components/mus/public/cpp/window_tree_client.h"
+#include "components/mus/public/cpp/window_tree_client_delegate.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -26,7 +26,7 @@ class InputHandlerManager;
// default all other methods are assumed to run on the compositor thread unless
// explicited suffixed with OnMainThread.
class CONTENT_EXPORT CompositorMusConnection
- : NON_EXPORTED_BASE(public mus::WindowTreeDelegate),
+ : NON_EXPORTED_BASE(public mus::WindowTreeClientDelegate),
NON_EXPORTED_BASE(public mus::InputEventHandler),
public base::RefCountedThreadSafe<CompositorMusConnection> {
public:
@@ -52,8 +52,8 @@ class CONTENT_EXPORT CompositorMusConnection
void AttachSurfaceOnCompositorThread(
std::unique_ptr<mus::WindowSurfaceBinding> surface_binding);
- void CreateWindowTreeConnectionOnCompositorThread(
- mojo::InterfaceRequest<mus::mojom::WindowTreeClient> request);
+ void CreateWindowTreeClientOnCompositorThread(
+ mus::mojom::WindowTreeClientRequest request);
void OnConnectionLostOnMainThread();
@@ -65,8 +65,8 @@ class CONTENT_EXPORT CompositorMusConnection
const base::Callback<void(mus::mojom::EventResult)>& ack,
mus::mojom::EventResult result);
- // WindowTreeDelegate implementation:
- void OnConnectionLost(mus::WindowTreeConnection* connection) override;
+ // WindowTreeClientDelegate implementation:
+ void OnWindowTreeClientDestroyed(mus::WindowTreeClient* client) override;
void OnEmbed(mus::Window* root) override;
void OnEventObserved(const ui::Event& event, mus::Window* target) override;
diff --git a/chromium/content/renderer/mus/compositor_mus_connection_unittest.cc b/chromium/content/renderer/mus/compositor_mus_connection_unittest.cc
index 45f621bd771..441674ce4b6 100644
--- a/chromium/content/renderer/mus/compositor_mus_connection_unittest.cc
+++ b/chromium/content/renderer/mus/compositor_mus_connection_unittest.cc
@@ -11,9 +11,6 @@
#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
#include "components/mus/public/cpp/tests/test_window.h"
-#include "components/mus/public/interfaces/input_event_constants.mojom.h"
-#include "components/mus/public/interfaces/input_events.mojom.h"
-#include "components/mus/public/interfaces/input_key_codes.mojom.h"
#include "content/common/input/did_overscroll_params.h"
#include "content/common/input/input_event_ack.h"
#include "content/common/input/input_event_ack_state.h"
@@ -28,6 +25,9 @@
#include "mojo/public/cpp/bindings/interface_request.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event_utils.h"
+#include "ui/events/mojo/event.mojom.h"
+#include "ui/events/mojo/event_constants.mojom.h"
+#include "ui/events/mojo/keyboard_codes.mojom.h"
using mus::mojom::EventResult;
@@ -442,9 +442,10 @@ TEST_F(CompositorMusConnectionTest, InputHandlerConsumes) {
// CompositorMusConnection does not consume the ack, nor calls it.
TEST_F(CompositorMusConnectionTest, RendererWillNotSendAck) {
mus::TestWindow test_window;
- ui::PointerEvent event(ui::ET_POINTER_DOWN,
- ui::EventPointerType::POINTER_TYPE_MOUSE, gfx::Point(),
- gfx::Point(), ui::EF_NONE, 0, ui::EventTimeForNow());
+ ui::PointerEvent event(
+ ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_NONE, 0,
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE),
+ ui::EventTimeForNow());
scoped_refptr<TestCallback> test_callback(new TestCallback);
std::unique_ptr<base::Callback<void(EventResult)>> ack_callback(
@@ -466,9 +467,10 @@ TEST_F(CompositorMusConnectionTest, TouchEventConsumed) {
input_handler->set_state(InputEventAckState::INPUT_EVENT_ACK_STATE_CONSUMED);
mus::TestWindow test_window;
- ui::PointerEvent event(ui::ET_POINTER_DOWN,
- ui::EventPointerType::POINTER_TYPE_TOUCH, gfx::Point(),
- gfx::Point(), ui::EF_NONE, 0, ui::EventTimeForNow());
+ ui::PointerEvent event(
+ ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_NONE, 0,
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH),
+ ui::EventTimeForNow());
scoped_refptr<TestCallback> test_callback(new TestCallback);
std::unique_ptr<base::Callback<void(EventResult)>> ack_callback(
diff --git a/chromium/content/renderer/mus/render_widget_mus_connection.cc b/chromium/content/renderer/mus/render_widget_mus_connection.cc
index 6916b324111..b5890e5ba28 100644
--- a/chromium/content/renderer/mus/render_widget_mus_connection.cc
+++ b/chromium/content/renderer/mus/render_widget_mus_connection.cc
@@ -11,15 +11,12 @@
#include "components/mus/public/cpp/context_provider.h"
#include "components/mus/public/cpp/output_surface.h"
#include "components/mus/public/interfaces/command_buffer.mojom.h"
-#include "components/mus/public/interfaces/compositor_frame.mojom.h"
-#include "components/mus/public/interfaces/gpu.mojom.h"
+#include "components/mus/public/interfaces/surface.mojom.h"
#include "components/mus/public/interfaces/window_tree.mojom.h"
#include "content/public/common/mojo_shell_connection.h"
#include "content/renderer/mus/compositor_mus_connection.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
-#include "mojo/converters/geometry/geometry_type_converters.h"
-#include "mojo/converters/surfaces/surfaces_utils.h"
#include "services/shell/public/cpp/connector.h"
namespace content {
@@ -49,13 +46,9 @@ std::unique_ptr<cc::OutputSurface>
RenderWidgetMusConnection::CreateOutputSurface() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!window_surface_binding_);
- mus::mojom::GpuPtr gpu_service;
- MojoShellConnection::Get()->GetConnector()->ConnectToInterface("mojo:mus",
- &gpu_service);
- mus::mojom::CommandBufferPtr cb;
- gpu_service->CreateOffscreenGLES2Context(GetProxy(&cb));
- scoped_refptr<cc::ContextProvider> context_provider(
- new mus::ContextProvider(cb.PassInterface().PassHandle()));
+ scoped_refptr<cc::ContextProvider> context_provider(new mus::ContextProvider(
+ MojoShellConnection::GetForProcess()->GetConnector()));
+
std::unique_ptr<cc::OutputSurface> surface(new mus::OutputSurface(
context_provider, mus::WindowSurface::Create(&window_surface_binding_)));
if (compositor_mus_connection_) {
@@ -100,13 +93,6 @@ bool RenderWidgetMusConnection::HasTouchEventHandlersAt(
return true;
}
-void RenderWidgetMusConnection::ObserveWheelEventAndResult(
- const blink::WebMouseWheelEvent& wheel_event,
- const gfx::Vector2dF& wheel_unused_delta,
- bool event_processed) {
- NOTIMPLEMENTED();
-}
-
void RenderWidgetMusConnection::ObserveGestureEventAndResult(
const blink::WebGestureEvent& gesture_event,
const gfx::Vector2dF& wheel_unused_delta,
diff --git a/chromium/content/renderer/mus/render_widget_mus_connection.h b/chromium/content/renderer/mus/render_widget_mus_connection.h
index 4e61189fb06..bb0abe34a34 100644
--- a/chromium/content/renderer/mus/render_widget_mus_connection.h
+++ b/chromium/content/renderer/mus/render_widget_mus_connection.h
@@ -43,9 +43,6 @@ class CONTENT_EXPORT RenderWidgetMusConnection
// RenderWidgetInputHandlerDelegate implementation:
void FocusChangeComplete() override;
bool HasTouchEventHandlersAt(const gfx::Point& point) const override;
- void ObserveWheelEventAndResult(const blink::WebMouseWheelEvent& wheel_event,
- const gfx::Vector2dF& wheel_unused_delta,
- bool event_processed) override;
void ObserveGestureEventAndResult(const blink::WebGestureEvent& gesture_event,
const gfx::Vector2dF& gesture_unused_delta,
bool event_processed) override;
diff --git a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc b/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
index 83ca42443de..dd862b0e8f0 100644
--- a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
+++ b/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
@@ -16,6 +16,7 @@
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/shell/public/cpp/connection.h"
#include "services/shell/public/cpp/interface_factory.h"
+#include "services/shell/public/cpp/shell_client.h"
#include "url/gurl.h"
namespace content {
@@ -23,21 +24,21 @@ namespace content {
namespace {
// This object's lifetime is managed by MojoShellConnection because it's a
-// MojoShellConnection::Listener.
+// registered with it.
class RenderWidgetWindowTreeClientFactoryImpl
- : public MojoShellConnection::Listener,
+ : public shell::ShellClient,
public shell::InterfaceFactory<
mojom::RenderWidgetWindowTreeClientFactory>,
public mojom::RenderWidgetWindowTreeClientFactory {
public:
RenderWidgetWindowTreeClientFactoryImpl() {
- DCHECK(MojoShellConnection::Get());
+ DCHECK(MojoShellConnection::GetForProcess());
}
~RenderWidgetWindowTreeClientFactoryImpl() override {}
private:
- // MojoShellConnection::Listener implementation:
+ // shell::ShellClient implementation:
bool AcceptConnection(shell::Connection* connection) override {
connection->AddInterface<mojom::RenderWidgetWindowTreeClientFactory>(this);
return true;
@@ -67,8 +68,8 @@ class RenderWidgetWindowTreeClientFactoryImpl
} // namespace
void CreateRenderWidgetWindowTreeClientFactory() {
- MojoShellConnection::Get()->AddListener(
- base::WrapUnique(new RenderWidgetWindowTreeClientFactoryImpl()));
+ MojoShellConnection::GetForProcess()->AddEmbeddedShellClient(
+ base::WrapUnique(new RenderWidgetWindowTreeClientFactoryImpl));
}
} // namespace content
diff --git a/chromium/content/renderer/notification_permission_dispatcher.cc b/chromium/content/renderer/notification_permission_dispatcher.cc
index f038b5c2dfb..0e7e402a791 100644
--- a/chromium/content/renderer/notification_permission_dispatcher.cc
+++ b/chromium/content/renderer/notification_permission_dispatcher.cc
@@ -7,12 +7,13 @@
#include <utility>
#include "base/bind.h"
-#include "content/public/common/service_registry.h"
#include "content/public/renderer/render_frame.h"
+#include "services/shell/public/cpp/interface_provider.h"
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom-blink.h"
#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/modules/notifications/WebNotificationPermissionCallback.h"
using blink::WebNotificationPermissionCallback;
@@ -29,8 +30,7 @@ void NotificationPermissionDispatcher::RequestPermission(
const blink::WebSecurityOrigin& origin,
WebNotificationPermissionCallback* callback) {
if (!permission_service_.get()) {
- render_frame()->GetServiceRegistry()->ConnectToRemoteService(
- mojo::GetProxy(&permission_service_));
+ render_frame()->GetRemoteInterfaces()->GetInterface(&permission_service_);
}
std::unique_ptr<WebNotificationPermissionCallback> owned_callback(callback);
@@ -39,6 +39,7 @@ void NotificationPermissionDispatcher::RequestPermission(
// callbacks, will be deleted before the "this" instance is deleted.
permission_service_->RequestPermission(
blink::mojom::PermissionName::NOTIFICATIONS, origin.toString().utf8(),
+ blink::WebUserGestureIndicator::isProcessingUserGesture(),
base::Bind(&NotificationPermissionDispatcher::OnPermissionRequestComplete,
base::Unretained(this),
base::Passed(std::move(owned_callback))));
@@ -55,4 +56,8 @@ void NotificationPermissionDispatcher::OnPermissionRequestComplete(
callback->permissionRequestComplete(blink_status);
}
+void NotificationPermissionDispatcher::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/notification_permission_dispatcher.h b/chromium/content/renderer/notification_permission_dispatcher.h
index 77fbb63c2a0..8b1eb58adfa 100644
--- a/chromium/content/renderer/notification_permission_dispatcher.h
+++ b/chromium/content/renderer/notification_permission_dispatcher.h
@@ -33,6 +33,9 @@ class NotificationPermissionDispatcher : public RenderFrameObserver {
blink::WebNotificationPermissionCallback* callback);
private:
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
void OnPermissionRequestComplete(
std::unique_ptr<blink::WebNotificationPermissionCallback> callback,
blink::mojom::PermissionStatus status);
diff --git a/chromium/content/renderer/p2p/filtering_network_manager.cc b/chromium/content/renderer/p2p/filtering_network_manager.cc
index dba704a571a..4112d56f513 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager.cc
+++ b/chromium/content/renderer/p2p/filtering_network_manager.cc
@@ -27,29 +27,13 @@ FilteringNetworkManager::FilteringNetworkManager(
// If the feature is not enabled, just return ALLOWED as it's requested.
if (!media_permission_) {
- initialized_ = true;
+ started_permission_check_ = true;
set_enumeration_permission(ENUMERATION_ALLOWED);
VLOG(3) << "media_permission is not passed, granting permission";
return;
}
}
-void FilteringNetworkManager::Initialize() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!initialized_);
-
- initialized_ = true;
- pending_permission_checks_ = 2;
-
- // Request for media permission asynchronously.
- media_permission_->HasPermission(
- media::MediaPermission::AUDIO_CAPTURE, requesting_origin_,
- base::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
- media_permission_->HasPermission(
- media::MediaPermission::VIDEO_CAPTURE, requesting_origin_,
- base::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
-}
-
FilteringNetworkManager::~FilteringNetworkManager() {
DCHECK(thread_checker_.CalledOnValidThread());
// This helps to catch the case if permission never comes back.
@@ -61,9 +45,15 @@ base::WeakPtr<FilteringNetworkManager> FilteringNetworkManager::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
+void FilteringNetworkManager::Initialize() {
+ rtc::NetworkManagerBase::Initialize();
+ if (media_permission_)
+ CheckPermission();
+}
+
void FilteringNetworkManager::StartUpdating() {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(initialized_);
+ DCHECK(started_permission_check_);
if (start_updating_time_.is_null()) {
start_updating_time_ = base::TimeTicks::Now();
@@ -101,6 +91,22 @@ bool FilteringNetworkManager::GetDefaultLocalAddress(
return network_manager_->GetDefaultLocalAddress(family, ipaddress);
}
+void FilteringNetworkManager::CheckPermission() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!started_permission_check_);
+
+ started_permission_check_ = true;
+ pending_permission_checks_ = 2;
+
+ // Request for media permission asynchronously.
+ media_permission_->HasPermission(
+ media::MediaPermission::AUDIO_CAPTURE, requesting_origin_,
+ base::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
+ media_permission_->HasPermission(
+ media::MediaPermission::VIDEO_CAPTURE, requesting_origin_,
+ base::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
+}
+
void FilteringNetworkManager::OnPermissionStatus(bool granted) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_GT(pending_permission_checks_, 0);
diff --git a/chromium/content/renderer/p2p/filtering_network_manager.h b/chromium/content/renderer/p2p/filtering_network_manager.h
index 7b0fca26231..01b0ccd2442 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager.h
+++ b/chromium/content/renderer/p2p/filtering_network_manager.h
@@ -46,11 +46,8 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
CONTENT_EXPORT ~FilteringNetworkManager() override;
- // Check mic/camera permission.
- // This is called by PeerConnectionDependencyFactory.
- CONTENT_EXPORT void Initialize();
-
// rtc::NetworkManager:
+ void Initialize() override;
void StartUpdating() override;
void StopUpdating() override;
void GetNetworks(NetworkList* networks) const override;
@@ -58,6 +55,9 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
rtc::IPAddress* ipaddress) const override;
private:
+ // Check mic/camera permission.
+ void CheckPermission();
+
// Receive callback from MediaPermission when the permission status is
// available.
void OnPermissionStatus(bool granted);
@@ -110,8 +110,8 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
// StartUpdating.
int start_count_ = 0;
- // Track whether Initialize has been called before StartUpdating.
- bool initialized_ = false;
+ // Track whether CheckPermission has been called before StartUpdating.
+ bool started_permission_check_ = false;
// Track how long it takes for client to receive SignalNetworksChanged. This
// helps to identify if the signal is delayed by permission check and increase
diff --git a/chromium/content/renderer/p2p/port_allocator.cc b/chromium/content/renderer/p2p/port_allocator.cc
index c9bc9fadf1d..00ee3beddab 100644
--- a/chromium/content/renderer/p2p/port_allocator.cc
+++ b/chromium/content/renderer/p2p/port_allocator.cc
@@ -21,14 +21,15 @@ P2PPortAllocator::P2PPortAllocator(
std::unique_ptr<rtc::NetworkManager> network_manager,
rtc::PacketSocketFactory* socket_factory,
const Config& config,
- const GURL& origin,
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ const GURL& origin)
: cricket::BasicPortAllocator(network_manager.get(), socket_factory),
network_manager_(std::move(network_manager)),
socket_dispatcher_(socket_dispatcher),
config_(config),
- origin_(origin),
- network_manager_task_runner_(task_runner) {
+ origin_(origin) {
+ DCHECK(socket_dispatcher);
+ DCHECK(network_manager_);
+ DCHECK(socket_factory);
uint32_t flags = 0;
if (!config_.enable_multiple_routes) {
flags |= cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION;
@@ -51,13 +52,11 @@ P2PPortAllocator::P2PPortAllocator(
}
}
-// TODO(guoweis): P2PPortAllocator is also deleted in the wrong thread
-// here. It's created in signaling thread, and held by webrtc::PeerConnection,
-// only used on worker thread. The destructor is invoked on signaling thread
-// again. crbug.com/535761. DeleteSoon can be removed once the bug is fixed.
-P2PPortAllocator::~P2PPortAllocator() {
- network_manager_task_runner_->DeleteSoon(FROM_HERE,
- network_manager_.release());
+P2PPortAllocator::~P2PPortAllocator() {}
+
+void P2PPortAllocator::Initialize() {
+ BasicPortAllocator::Initialize();
+ network_manager_->Initialize();
}
} // namespace content
diff --git a/chromium/content/renderer/p2p/port_allocator.h b/chromium/content/renderer/p2p/port_allocator.h
index 945b5f87e6e..f686b39643e 100644
--- a/chromium/content/renderer/p2p/port_allocator.h
+++ b/chromium/content/renderer/p2p/port_allocator.h
@@ -38,26 +38,22 @@ class P2PPortAllocator : public cricket::BasicPortAllocator {
bool enable_default_local_candidate = true;
};
- P2PPortAllocator(
- const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
- std::unique_ptr<rtc::NetworkManager> network_manager,
- rtc::PacketSocketFactory* socket_factory,
- const Config& config,
- const GURL& origin,
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ P2PPortAllocator(const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
+ std::unique_ptr<rtc::NetworkManager> network_manager,
+ rtc::PacketSocketFactory* socket_factory,
+ const Config& config,
+ const GURL& origin);
~P2PPortAllocator() override;
+ // Will also initialize the network manager passed into the constructor.
+ void Initialize() override;
+
private:
std::unique_ptr<rtc::NetworkManager> network_manager_;
scoped_refptr<P2PSocketDispatcher> socket_dispatcher_;
Config config_;
GURL origin_;
- // This is the thread |network_manager_| is associated with and must be used
- // to delete |network_manager_|.
- const scoped_refptr<base::SingleThreadTaskRunner>
- network_manager_task_runner_;
-
DISALLOW_COPY_AND_ASSIGN(P2PPortAllocator);
};
diff --git a/chromium/content/renderer/pepper/message_channel.cc b/chromium/content/renderer/pepper/message_channel.cc
index f14f0041969..4566631717e 100644
--- a/chromium/content/renderer/pepper/message_channel.cc
+++ b/chromium/content/renderer/pepper/message_channel.cc
@@ -12,7 +12,6 @@
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "content/renderer/pepper/host_array_buffer_var.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_try_catch.h"
#include "content/renderer/pepper/plugin_module.h"
@@ -27,20 +26,12 @@
#include "ppapi/shared_impl/var.h"
#include "ppapi/shared_impl/var_tracker.h"
#include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebNode.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
#include "v8/include/v8.h"
-using ppapi::ArrayBufferVar;
using ppapi::PpapiGlobals;
using ppapi::ScopedPPVar;
using ppapi::StringVar;
-using blink::WebElement;
-using blink::WebDOMEvent;
using blink::WebDOMMessageEvent;
using blink::WebPluginContainer;
using blink::WebSerializedScriptValue;
diff --git a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc
index 0a4bc6e3a53..6f39f0fb7d9 100644
--- a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc
+++ b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc
@@ -4,6 +4,7 @@
#include "content/renderer/pepper/mock_renderer_ppapi_host.h"
+#include "content/public/renderer/render_view.h"
#include "content/renderer/pepper/fake_pepper_plugin_instance.h"
#include "ui/gfx/geometry/point.h"
@@ -16,7 +17,10 @@ MockRendererPpapiHost::MockRendererPpapiHost(RenderView* render_view,
render_view_(render_view),
pp_instance_(instance),
has_user_gesture_(false),
- plugin_instance_(new FakePepperPluginInstance) {}
+ plugin_instance_(new FakePepperPluginInstance) {
+ if (render_view)
+ render_frame_ = render_view->GetMainRenderFrame();
+}
MockRendererPpapiHost::~MockRendererPpapiHost() {}
@@ -35,6 +39,8 @@ PepperPluginInstance* MockRendererPpapiHost::GetPluginInstance(
RenderFrame* MockRendererPpapiHost::GetRenderFrameForInstance(
PP_Instance instance) const {
+ if (instance == pp_instance_)
+ return render_frame_;
return NULL;
}
diff --git a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h
index 84e6ff4d253..30dd766ed26 100644
--- a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h
+++ b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h
@@ -65,6 +65,7 @@ class MockRendererPpapiHost : public RendererPpapiHost {
ppapi::host::PpapiHost ppapi_host_;
RenderView* render_view_;
+ RenderFrame* render_frame_;
PP_Instance pp_instance_;
bool has_user_gesture_;
diff --git a/chromium/content/renderer/pepper/pepper_audio_controller.cc b/chromium/content/renderer/pepper/pepper_audio_controller.cc
new file mode 100644
index 00000000000..88d80f11bd0
--- /dev/null
+++ b/chromium/content/renderer/pepper/pepper_audio_controller.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 "content/renderer/pepper/pepper_audio_controller.h"
+
+#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/ppb_audio_impl.h"
+#include "content/renderer/render_frame_impl.h"
+
+namespace content {
+
+PepperAudioController::PepperAudioController(
+ PepperPluginInstanceImpl* instance)
+ : instance_(instance) {
+ DCHECK(instance_);
+}
+
+PepperAudioController::~PepperAudioController() {
+ if (instance_)
+ OnPepperInstanceDeleted();
+}
+
+void PepperAudioController::AddInstance(PPB_Audio_Impl* audio) {
+ if (!instance_)
+ return;
+ if (ppb_audios_.count(audio))
+ return;
+
+ if (ppb_audios_.empty()) {
+ RenderFrameImpl* render_frame = instance_->render_frame();
+ if (render_frame)
+ render_frame->PepperStartsPlayback(instance_);
+ }
+
+ ppb_audios_.insert(audio);
+}
+
+void PepperAudioController::RemoveInstance(PPB_Audio_Impl* audio) {
+ if (!instance_)
+ return;
+ if (!ppb_audios_.count(audio))
+ return;
+
+ ppb_audios_.erase(audio);
+
+ if (ppb_audios_.empty())
+ NotifyPlaybackStopsOnEmpty();
+}
+
+void PepperAudioController::SetVolume(double volume) {
+ if (!instance_)
+ return;
+
+ for (auto* ppb_audio : ppb_audios_)
+ ppb_audio->SetVolume(volume);
+}
+
+void PepperAudioController::OnPepperInstanceDeleted() {
+ DCHECK(instance_);
+
+ if (!ppb_audios_.empty())
+ NotifyPlaybackStopsOnEmpty();
+
+ ppb_audios_.clear();
+ instance_ = nullptr;
+}
+
+void PepperAudioController::NotifyPlaybackStopsOnEmpty() {
+ DCHECK(instance_);
+
+ RenderFrameImpl* render_frame = instance_->render_frame();
+ if (render_frame)
+ render_frame->PepperStopsPlayback(instance_);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_audio_controller.h b/chromium/content/renderer/pepper/pepper_audio_controller.h
new file mode 100644
index 00000000000..29241ab8e63
--- /dev/null
+++ b/chromium/content/renderer/pepper/pepper_audio_controller.h
@@ -0,0 +1,57 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_PEPPER_PEPPER_AUDIO_CONTROLLER_H_
+#define CONTENT_RENDERER_PEPPER_PEPPER_AUDIO_CONTROLLER_H_
+
+#include <set>
+
+#include "base/macros.h"
+
+namespace content {
+
+class PepperPluginInstanceImpl;
+class PPB_Audio_Impl;
+
+/**
+ * This class controls all the active audio instances of a Pepper instance.
+ * This class can only be a non-shareable member of PepperPluginInstanceImpl.
+ */
+class PepperAudioController {
+ public:
+ explicit PepperAudioController(PepperPluginInstanceImpl* instance);
+ virtual ~PepperAudioController();
+
+ // Adds an audio instance to the controller.
+ void AddInstance(PPB_Audio_Impl* audio);
+
+ // Removes an audio instance from the controller.
+ void RemoveInstance(PPB_Audio_Impl* audio);
+
+ // Sets the volume of all audio instances.
+ void SetVolume(double volume);
+
+ // The pepper instance has been deleted. This method can only be called
+ // once. The controller will be invalidated after this call, and then all
+ // other methods will be no-op.
+ void OnPepperInstanceDeleted();
+
+ private:
+ // Notifies the RenderFrame that the playback has stopped. This method should
+ // only be called when |ppb_audios_| turns from non-empty to empty.
+ void NotifyPlaybackStopsOnEmpty();
+
+ // All active audio instances.
+ std::set<PPB_Audio_Impl*> ppb_audios_;
+
+ // The Pepper instance which this controller is for. Will be null after
+ // OnPepperInstanceDeleted() is called.
+ PepperPluginInstanceImpl* instance_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperAudioController);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PEPPER_PEPPER_AUDIO_CONTROLLER_H_
diff --git a/chromium/content/renderer/pepper/pepper_browser_connection.cc b/chromium/content/renderer/pepper/pepper_browser_connection.cc
index 43affea1374..19ba1cc7a35 100644
--- a/chromium/content/renderer/pepper/pepper_browser_connection.cc
+++ b/chromium/content/renderer/pepper/pepper_browser_connection.cc
@@ -96,4 +96,8 @@ int32_t PepperBrowserConnection::GetNextSequence() {
return ret;
}
+void PepperBrowserConnection::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_browser_connection.h b/chromium/content/renderer/pepper/pepper_browser_connection.h
index 6e5a3d692cb..07d1501c398 100644
--- a/chromium/content/renderer/pepper/pepper_browser_connection.h
+++ b/chromium/content/renderer/pepper/pepper_browser_connection.h
@@ -60,6 +60,9 @@ class PepperBrowserConnection
void DidDeleteInProcessInstance(PP_Instance instance);
private:
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
// Message handlers.
void OnMsgCreateResourceHostsFromHostReply(
int32_t sequence_number,
diff --git a/chromium/content/renderer/pepper/pepper_compositor_host.cc b/chromium/content/renderer/pepper/pepper_compositor_host.cc
index f16ef70ea4a..c2768361c0e 100644
--- a/chromium/content/renderer/pepper/pepper_compositor_host.cc
+++ b/chromium/content/renderer/pepper/pepper_compositor_host.cc
@@ -65,7 +65,7 @@ int32_t VerifyCommittedLayer(const ppapi::CompositorLayerData* old_layer,
if (new_layer->texture) {
if (old_layer) {
// Make sure the old layer is a texture layer too.
- if (!new_layer->texture)
+ if (!old_layer->texture)
return PP_ERROR_BADARGUMENT;
// The mailbox should be same, if the resource_id is not changed.
if (new_layer->common.resource_id == old_layer->common.resource_id) {
@@ -87,7 +87,7 @@ int32_t VerifyCommittedLayer(const ppapi::CompositorLayerData* old_layer,
if (new_layer->image) {
if (old_layer) {
// Make sure the old layer is an image layer too.
- if (!new_layer->image)
+ if (!old_layer->image)
return PP_ERROR_BADARGUMENT;
// The image data resource should be same, if the resource_id is not
// changed.
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
index b70ab83c3d1..f2f8be3b2e5 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
@@ -154,9 +154,10 @@ int32_t PepperFileChooserHost::OnShow(
params.requestor = renderer_ppapi_host_->GetDocumentURL(pp_instance());
handler_ = new CompletionHandler(AsWeakPtr());
- RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
- renderer_ppapi_host_->GetRenderViewForInstance(pp_instance()));
- if (!render_view || !render_view->runFileChooser(params, handler_)) {
+ RenderFrameImpl* render_frame = static_cast<RenderFrameImpl*>(
+ renderer_ppapi_host_->GetRenderFrameForInstance(pp_instance()));
+
+ if (!render_frame || !render_frame->runFileChooser(params, handler_)) {
delete handler_;
handler_ = NULL;
return PP_ERROR_NOACCESS;
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
index f74c0a181b3..d610636955d 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
@@ -3,10 +3,12 @@
// found in the LICENSE file.
#include <stdint.h>
+#include <tuple>
#include "base/files/file_path.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/file_chooser_file_info.h"
#include "content/public/common/file_chooser_params.h"
@@ -91,11 +93,11 @@ TEST_F(PepperFileChooserHostTest, Show) {
// The render view should have sent a chooser request to the browser
// (caught by the render thread's test message sink).
const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
- ViewHostMsg_RunFileChooser::ID);
+ FrameHostMsg_RunFileChooser::ID);
ASSERT_TRUE(msg);
- ViewHostMsg_RunFileChooser::Schema::Param call_msg_param;
- ASSERT_TRUE(ViewHostMsg_RunFileChooser::Read(msg, &call_msg_param));
- const FileChooserParams& chooser_params = base::get<0>(call_msg_param);
+ FrameHostMsg_RunFileChooser::Schema::Param call_msg_param;
+ ASSERT_TRUE(FrameHostMsg_RunFileChooser::Read(msg, &call_msg_param));
+ const FileChooserParams& chooser_params = std::get<0>(call_msg_param);
// Basic validation of request.
EXPECT_EQ(FileChooserParams::Open, chooser_params.mode);
@@ -109,10 +111,11 @@ TEST_F(PepperFileChooserHostTest, Show) {
selected_info.file_path = base::FilePath(FILE_PATH_LITERAL("myp\\ath/foo"));
std::vector<content::FileChooserFileInfo> selected_info_vector;
selected_info_vector.push_back(selected_info);
- RenderViewImpl* view_impl = static_cast<RenderViewImpl*>(view_);
- ViewMsg_RunFileChooserResponse response(view_impl->GetRoutingID(),
- selected_info_vector);
- EXPECT_TRUE(view_impl->OnMessageReceived(response));
+ RenderFrameImpl* frame_impl =
+ static_cast<RenderFrameImpl*>(view_->GetMainRenderFrame());
+ FrameMsg_RunFileChooserResponse response(frame_impl->GetRoutingID(),
+ selected_info_vector);
+ EXPECT_TRUE(frame_impl->OnMessageReceived(response));
// This should have sent the Pepper reply to our test sink.
ppapi::proxy::ResourceMessageReplyParams reply_params;
@@ -127,7 +130,7 @@ TEST_F(PepperFileChooserHostTest, Show) {
ASSERT_TRUE(
PpapiPluginMsg_FileChooser_ShowReply::Read(&reply_msg, &reply_msg_param));
const std::vector<ppapi::FileRefCreateInfo>& chooser_results =
- base::get<0>(reply_msg_param);
+ std::get<0>(reply_msg_param);
ASSERT_EQ(1u, chooser_results.size());
EXPECT_EQ(FilePathToUTF8(selected_info.display_name),
chooser_results[0].display_name);
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
index 478e90536d7..41c82fca255 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -383,8 +383,6 @@ void PepperGraphics2DHost::ViewInitiatedPaint() {
}
}
-void PepperGraphics2DHost::SetScale(float scale) { scale_ = scale; }
-
float PepperGraphics2DHost::GetScale() const { return scale_; }
bool PepperGraphics2DHost::IsAlwaysOpaque() const { return is_always_opaque_; }
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h
index 6fb01c29e8f..e50b095d8c1 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h
@@ -85,7 +85,6 @@ class CONTENT_EXPORT PepperGraphics2DHost
// These messages are used to send Flush callbacks to the plugin.
void ViewInitiatedPaint();
- void SetScale(float scale);
float GetScale() const;
void SetLayerTransform(float scale, const PP_Point& transform);
bool IsAlwaysOpaque() const;
diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.cc b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
index 1b21f75c920..42abb0802af 100644
--- a/chromium/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
@@ -61,12 +61,9 @@ int PepperMediaDeviceManager::EnumerateDevices(
PepperMediaDeviceManager::FromPepperDeviceType(type),
url::Origin(document_url.GetOrigin()));
#else
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&PepperMediaDeviceManager::OnDevicesEnumerated,
- AsWeakPtr(),
- request_id,
- StreamDeviceInfoArray()));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&PepperMediaDeviceManager::OnDevicesEnumerated,
+ AsWeakPtr(), request_id, StreamDeviceInfoArray()));
#endif
return request_id;
@@ -109,11 +106,9 @@ int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type,
PepperMediaDeviceManager::FromPepperDeviceType(type),
url::Origin(document_url.GetOrigin()));
#else
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&PepperMediaDeviceManager::OnDeviceOpenFailed,
- AsWeakPtr(),
- request_id));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&PepperMediaDeviceManager::OnDeviceOpenFailed,
+ AsWeakPtr(), request_id));
#endif
return request_id;
@@ -255,4 +250,8 @@ MediaStreamDispatcher* PepperMediaDeviceManager::GetMediaStreamDispatcher()
return dispatcher;
}
+void PepperMediaDeviceManager::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.h b/chromium/content/renderer/pepper/pepper_media_device_manager.h
index 90d6dc09dcf..e0343bbd197 100644
--- a/chromium/content/renderer/pepper/pepper_media_device_manager.h
+++ b/chromium/content/renderer/pepper/pepper_media_device_manager.h
@@ -81,6 +81,9 @@ class PepperMediaDeviceManager
private:
explicit PepperMediaDeviceManager(RenderFrame* render_frame);
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
// Called by StopEnumerateDevices() after returing to the event loop, to avoid
// a reentrancy problem.
void StopEnumerateDevicesDelayed(int request_id);
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output.cc b/chromium/content/renderer/pepper/pepper_platform_audio_output.cc
index 1e9c74cc7e5..a8e7c433668 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_output.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_output.cc
@@ -60,6 +60,17 @@ bool PepperPlatformAudioOutput::StopPlayback() {
return false;
}
+bool PepperPlatformAudioOutput::SetVolume(double volume) {
+ if (ipc_) {
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&PepperPlatformAudioOutput::SetVolumeOnIOThread,
+ this, volume));
+ return true;
+ }
+ return false;
+}
+
void PepperPlatformAudioOutput::ShutDown() {
// Called on the main thread to stop all audio callbacks. We must only change
// the client on the main thread, and the delegates from the I/O thread.
@@ -156,6 +167,12 @@ void PepperPlatformAudioOutput::StartPlaybackOnIOThread() {
ipc_->PlayStream();
}
+void PepperPlatformAudioOutput::SetVolumeOnIOThread(double volume) {
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
+ if (ipc_)
+ ipc_->SetVolume(volume);
+}
+
void PepperPlatformAudioOutput::StopPlaybackOnIOThread() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
if (ipc_)
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output.h b/chromium/content/renderer/pepper/pepper_platform_audio_output.h
index ea8771d6f90..439dc2b7dc2 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_output.h
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_output.h
@@ -43,6 +43,10 @@ class PepperPlatformAudioOutput
// is created or after the stream is closed.
bool StopPlayback();
+ // Sets the volume. Returns false on error or if called before the stream
+ // is created or after the stream is closed.
+ bool SetVolume(double volume);
+
// Closes the stream. Make sure to call this before the object is
// destructed.
void ShutDown();
@@ -74,6 +78,7 @@ class PepperPlatformAudioOutput
void InitializeOnIOThread(const media::AudioParameters& params);
void StartPlaybackOnIOThread();
void StopPlaybackOnIOThread();
+ void SetVolumeOnIOThread(double volume);
void ShutDownOnIOThread();
// The client to notify when the stream is created. THIS MUST ONLY BE
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 8810686bb43..2dfd47b0822 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -35,6 +35,7 @@
#include "content/renderer/pepper/host_dispatcher_wrapper.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/message_channel.h"
+#include "content/renderer/pepper/pepper_audio_controller.h"
#include "content/renderer/pepper/pepper_browser_connection.h"
#include "content/renderer/pepper/pepper_compositor_host.h"
#include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
@@ -529,6 +530,7 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
isolate_(v8::Isolate::GetCurrent()),
is_deleted_(false),
initialized_(false),
+ audio_controller_(new PepperAudioController(this)),
view_change_weak_ptr_factory_(this),
weak_factory_(this) {
pp_instance_ = HostGlobals::Get()->AddInstance(this);
@@ -585,6 +587,8 @@ PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
if (TrackedCallback::IsPending(lock_mouse_callback_))
lock_mouse_callback_->Abort();
+ audio_controller_->OnPepperInstanceDeleted();
+
if (render_frame_)
render_frame_->PepperInstanceDeleted(this);
@@ -684,7 +688,7 @@ void PepperPluginInstanceImpl::Delete() {
// Force-unbind any Graphics. In the case of Graphics2D, if the plugin
// leaks the graphics 2D, it may actually get cleaned up after our
- // destruction, so we need its pointers to be up-to-date.
+ // destruction, so we need its pointers to be up to date.
BindGraphics(pp_instance(), 0);
container_ = NULL;
}
@@ -756,22 +760,63 @@ void PepperPluginInstanceImpl::ScrollRect(int dx,
}
}
-void PepperPluginInstanceImpl::CommitBackingTexture() {
+void PepperPluginInstanceImpl::CommitTextureMailbox(
+ const cc::TextureMailbox& texture_mailbox) {
+ if (committed_texture_.IsValid() && !IsTextureInUse(committed_texture_)) {
+ committed_texture_graphics_3d_->ReturnFrontBuffer(
+ committed_texture_.mailbox(), committed_texture_consumed_sync_token_,
+ false);
+ }
+
+ committed_texture_ = texture_mailbox;
+ committed_texture_graphics_3d_ = bound_graphics_3d_;
+ committed_texture_consumed_sync_token_ = gpu::SyncToken();
+
if (!texture_layer_) {
UpdateLayer(true);
return;
}
- gpu::Mailbox mailbox;
- gpu::SyncToken sync_token;
- bound_graphics_3d_->GetBackingMailbox(&mailbox, &sync_token);
- DCHECK(!mailbox.IsZero());
- DCHECK(sync_token.HasData());
- texture_layer_->SetTextureMailboxWithoutReleaseCallback(
- cc::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D));
+ PassCommittedTextureToTextureLayer();
texture_layer_->SetNeedsDisplay();
}
+void PepperPluginInstanceImpl::PassCommittedTextureToTextureLayer() {
+ DCHECK(bound_graphics_3d_);
+
+ if (!committed_texture_.IsValid())
+ return;
+
+ std::unique_ptr<cc::SingleReleaseCallback> callback(
+ cc::SingleReleaseCallback::Create(base::Bind(
+ &PepperPluginInstanceImpl::FinishedConsumingCommittedTexture,
+ weak_factory_.GetWeakPtr(), committed_texture_,
+ committed_texture_graphics_3d_)));
+
+ IncrementTextureReferenceCount(committed_texture_);
+ texture_layer_->SetTextureMailbox(committed_texture_, std::move(callback));
+}
+
+void PepperPluginInstanceImpl::FinishedConsumingCommittedTexture(
+ const cc::TextureMailbox& texture_mailbox,
+ scoped_refptr<PPB_Graphics3D_Impl> graphics_3d,
+ const gpu::SyncToken& sync_token,
+ bool is_lost) {
+ bool removed = DecrementTextureReferenceCount(texture_mailbox);
+ bool is_committed_texture =
+ committed_texture_.mailbox() == texture_mailbox.mailbox();
+
+ if (is_committed_texture && !is_lost) {
+ committed_texture_consumed_sync_token_ = sync_token;
+ return;
+ }
+
+ if (removed && !is_committed_texture) {
+ graphics_3d->ReturnFrontBuffer(texture_mailbox.mailbox(), sync_token,
+ is_lost);
+ }
+}
+
void PepperPluginInstanceImpl::InstanceCrashed() {
// Force free all resources and vars.
HostGlobals::Get()->InstanceCrashed(pp_instance());
@@ -843,6 +888,14 @@ bool PepperPluginInstanceImpl::Initialize(
if (message_channel_)
message_channel_->Start();
}
+
+ if (success &&
+ render_frame_ &&
+ render_frame_->render_accessibility() &&
+ LoadPdfInterface()) {
+ plugin_pdf_interface_->EnableAccessibility(pp_instance());
+ }
+
initialized_ = success;
return success;
}
@@ -1216,8 +1269,7 @@ PP_Var PepperPluginInstanceImpl::GetInstanceObject(v8::Isolate* isolate) {
void PepperPluginInstanceImpl::ViewChanged(
const gfx::Rect& window,
const gfx::Rect& clip,
- const gfx::Rect& unobscured,
- const std::vector<gfx::Rect>& cut_outs_rects) {
+ const gfx::Rect& unobscured) {
// WebKit can give weird (x,y) positions for empty clip rects (since the
// position technically doesn't matter). But we want to make these
// consistent since this is given to the plugin, so force everything to 0
@@ -1228,8 +1280,6 @@ void PepperPluginInstanceImpl::ViewChanged(
unobscured_rect_ = unobscured;
- cut_outs_rects_ = cut_outs_rects;
-
view_data_.rect = PP_FromGfxRect(window);
view_data_.clip_rect = PP_FromGfxRect(clip);
view_data_.device_scale = container_->deviceScaleFactor();
@@ -1251,9 +1301,7 @@ void PepperPluginInstanceImpl::ViewChanged(
scroll_offset.height());
if (desired_fullscreen_state_ || view_data_.is_fullscreen) {
- WebElement element = container_->element();
- WebDocument document = element.document();
- bool is_fullscreen_element = (element == document.fullScreenElement());
+ bool is_fullscreen_element = container_->isFullscreenElement();
if (!view_data_.is_fullscreen && desired_fullscreen_state_ &&
render_frame()->GetRenderWidget()->is_fullscreen_granted() &&
is_fullscreen_element) {
@@ -1424,12 +1472,13 @@ bool PepperPluginInstanceImpl::StartFind(const base::string16& search_text,
PP_FromBool(case_sensitive)));
}
-void PepperPluginInstanceImpl::SelectFindResult(bool forward) {
+void PepperPluginInstanceImpl::SelectFindResult(bool forward, int identifier) {
// Keep a reference on the stack. See NOTE above.
scoped_refptr<PepperPluginInstanceImpl> ref(this);
- if (LoadFindInterface())
- plugin_find_interface_->SelectFindResult(pp_instance(),
- PP_FromBool(forward));
+ if (!LoadFindInterface())
+ return;
+ find_identifier_ = identifier;
+ plugin_find_interface_->SelectFindResult(pp_instance(), PP_FromBool(forward));
}
void PepperPluginInstanceImpl::StopFind() {
@@ -1921,9 +1970,9 @@ bool PepperPluginInstanceImpl::SetFullscreen(bool fullscreen) {
// so we will tweak plugin's attributes to support the expected behavior.
KeepSizeAttributesBeforeFullscreen();
SetSizeAttributesForFullscreen();
- container_->element().requestFullScreen();
+ container_->requestFullscreen();
} else {
- container_->document().cancelFullScreen();
+ container_->cancelFullscreen();
}
return true;
}
@@ -2003,12 +2052,7 @@ void PepperPluginInstanceImpl::UpdateLayer(bool force_creation) {
if (!container_)
return;
- gpu::Mailbox mailbox;
- gpu::SyncToken sync_token;
- if (bound_graphics_3d_.get()) {
- bound_graphics_3d_->GetBackingMailbox(&mailbox, &sync_token);
- }
- bool want_3d_layer = !mailbox.IsZero() && sync_token.HasData();
+ bool want_3d_layer = !!bound_graphics_3d_.get();
bool want_2d_layer = !!bound_graphics_2d_platform_;
bool want_texture_layer = want_3d_layer || want_2d_layer;
bool want_compositor_layer = !!bound_compositor_;
@@ -2047,8 +2091,8 @@ void PepperPluginInstanceImpl::UpdateLayer(bool force_creation) {
DCHECK(bound_graphics_3d_.get());
texture_layer_ = cc::TextureLayer::CreateForMailbox(NULL);
opaque = bound_graphics_3d_->IsOpaque();
- texture_layer_->SetTextureMailboxWithoutReleaseCallback(
- cc::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D));
+
+ PassCommittedTextureToTextureLayer();
} else {
DCHECK(bound_graphics_2d_platform_);
texture_layer_ = cc::TextureLayer::CreateForMailbox(this);
@@ -3340,4 +3384,47 @@ void PepperPluginInstanceImpl::ConvertDIPToViewport(gfx::Rect* rect) const {
rect->set_height(rect->height() / viewport_to_dip_scale_);
}
+void PepperPluginInstanceImpl::IncrementTextureReferenceCount(
+ const cc::TextureMailbox& mailbox) {
+ auto it =
+ std::find_if(texture_ref_counts_.begin(), texture_ref_counts_.end(),
+ [&mailbox](const TextureMailboxRefCount& ref_count) {
+ return ref_count.first.mailbox() == mailbox.mailbox();
+ });
+ if (it == texture_ref_counts_.end()) {
+ texture_ref_counts_.push_back(std::make_pair(mailbox, 1));
+ return;
+ }
+
+ it->second++;
+}
+
+bool PepperPluginInstanceImpl::DecrementTextureReferenceCount(
+ const cc::TextureMailbox& mailbox) {
+ auto it =
+ std::find_if(texture_ref_counts_.begin(), texture_ref_counts_.end(),
+ [&mailbox](const TextureMailboxRefCount& ref_count) {
+ return ref_count.first.mailbox() == mailbox.mailbox();
+ });
+ DCHECK(it != texture_ref_counts_.end());
+
+ if (it->second == 1) {
+ texture_ref_counts_.erase(it);
+ return true;
+ }
+
+ it->second--;
+ return false;
+}
+
+bool PepperPluginInstanceImpl::IsTextureInUse(
+ const cc::TextureMailbox& mailbox) const {
+ auto it =
+ std::find_if(texture_ref_counts_.begin(), texture_ref_counts_.end(),
+ [&mailbox](const TextureMailboxRefCount& ref_count) {
+ return ref_count.first.mailbox() == mailbox.mailbox();
+ });
+ return it != texture_ref_counts_.end();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
index dd53679cc79..f3089f05042 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -24,6 +24,7 @@
#include "cc/layers/content_layer_client.h"
#include "cc/layers/layer.h"
#include "cc/layers/texture_layer_client.h"
+#include "cc/resources/texture_mailbox.h"
#include "content/common/content_export.h"
#include "content/public/renderer/pepper_plugin_instance.h"
#include "content/public/renderer/plugin_instance_throttler.h"
@@ -105,6 +106,7 @@ namespace content {
class ContentDecryptorDelegate;
class FullscreenContainer;
class MessageChannel;
+class PepperAudioController;
class PepperCompositorHost;
class PepperGraphics2DHost;
class PluginInstanceThrottlerImpl;
@@ -197,9 +199,18 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// slow path can also be triggered if there is an overlapping frame.
void ScrollRect(int dx, int dy, const gfx::Rect& rect);
- // Commit the backing texture to the screen once the side effects some
- // rendering up to an offscreen SwapBuffers are visible.
- void CommitBackingTexture();
+ // Commit the texture mailbox to the screen.
+ void CommitTextureMailbox(const cc::TextureMailbox& texture_mailbox);
+
+ // Passes the committed texture to |texture_layer_| and marks it as in use.
+ void PassCommittedTextureToTextureLayer();
+
+ // Callback when the compositor is finished consuming the committed texture.
+ void FinishedConsumingCommittedTexture(
+ const cc::TextureMailbox& texture_mailbox,
+ scoped_refptr<PPB_Graphics3D_Impl> graphics_3d,
+ const gpu::SyncToken& sync_token,
+ bool is_lost);
// Called when the out-of-process plugin implementing this instance crashed.
void InstanceCrashed();
@@ -219,8 +230,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
PP_Var GetInstanceObject(v8::Isolate* isolate);
void ViewChanged(const gfx::Rect& window,
const gfx::Rect& clip,
- const gfx::Rect& unobscured,
- const std::vector<gfx::Rect>& cut_outs_rects);
+ const gfx::Rect& unobscured);
// Handlers for composition events.
bool HandleCompositionStart(const base::string16& text);
@@ -259,7 +269,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
bool StartFind(const base::string16& search_text,
bool case_sensitive,
int identifier);
- void SelectFindResult(bool forward);
+ void SelectFindResult(bool forward, int identifier);
void StopFind();
bool SupportsPrintInterface();
@@ -548,6 +558,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
void OnThrottleStateChange() override;
void OnHiddenForPlaceholder(bool hidden) override;
+ PepperAudioController& audio_controller() {
+ return *audio_controller_;
+ }
+
private:
friend class base::RefCounted<PepperPluginInstanceImpl>;
friend class PpapiPluginInstanceTest;
@@ -702,6 +716,28 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
void ConvertRectToDIP(PP_Rect* rect) const;
void ConvertDIPToViewport(gfx::Rect* rect) const;
+ // Each time CommitTextureMailbox() is called, this instance is given
+ // ownership
+ // of a cc::TextureMailbox. This instance always needs to hold on to the most
+ // recently committed cc::TextureMailbox, since UpdateLayer() might require
+ // it.
+ // Since it is possible for a cc::TextureMailbox to be passed to
+ // texture_layer_ more than once, a reference counting mechanism is necessary
+ // to ensure that a cc::TextureMailbox isn't returned until all copies of it
+ // have been released by texture_layer_.
+ //
+ // This method should be called each time a cc::TextureMailbox is passed to
+ // |texture_layer_|. It increments an internal reference count.
+ void IncrementTextureReferenceCount(const cc::TextureMailbox& mailbox);
+
+ // This method should be called each time |texture_layer_| finishes consuming
+ // a cc::TextureMailbox. It decrements an internal reference count. Returns
+ // whether the last reference was removed.
+ bool DecrementTextureReferenceCount(const cc::TextureMailbox& mailbox);
+
+ // Whether a given cc::TextureMailbox is in use by |texture_layer_|.
+ bool IsTextureInUse(const cc::TextureMailbox& mailbox) const;
+
RenderFrameImpl* render_frame_;
scoped_refptr<PluginModule> module_;
std::unique_ptr<ppapi::PPP_Instance_Combined> instance_interface_;
@@ -831,10 +867,6 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// Set to true if this plugin thinks it will always be on top. This allows us
// to use a more optimized painting path in some cases.
bool always_on_top_;
- // Even if |always_on_top_| is true, the plugin is not fully visible if there
- // are some cut-out areas (occupied by iframes higher in the stacking order).
- // This information is used in the optimized painting path.
- std::vector<gfx::Rect> cut_outs_rects_;
// Implementation of PPB_FlashFullscreen.
@@ -932,8 +964,27 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// The text that is currently selected in the plugin.
base::string16 selected_text_;
+ // The most recently committed texture. This is kept around in case the layer
+ // needs to be regenerated.
+ cc::TextureMailbox committed_texture_;
+
+ // The Graphics3D that produced the most recently committed texture.
+ scoped_refptr<PPB_Graphics3D_Impl> committed_texture_graphics_3d_;
+
+ gpu::SyncToken committed_texture_consumed_sync_token_;
+
+ // Holds the number of references |texture_layer_| has to any given
+ // cc::TextureMailbox.
+ // We expect there to be no more than 10 textures in use at a time. A
+ // std::vector will have better performance than a std::map.
+ using TextureMailboxRefCount = std::pair<cc::TextureMailbox, int>;
+ std::vector<TextureMailboxRefCount> texture_ref_counts_;
+
bool initialized_;
+ // The controller for all active audios of this pepper instance.
+ std::unique_ptr<PepperAudioController> audio_controller_;
+
// We use a weak ptr factory for scheduling DidChangeView events so that we
// can tell whether updates are pending and consolidate them. When there's
// already a weak ptr pending (HasWeakPtrs is true), code should update the
diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.cc b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
index ac34ce9ca66..d8b75dda4aa 100644
--- a/chromium/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
@@ -264,7 +264,9 @@ int32_t PepperURLLoaderHost::InternalOnHostMsgOpen(
// The requests from the plugins with private permission which can bypass same
// origin must skip the ServiceWorker.
web_request.setSkipServiceWorker(
- host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE));
+ host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE)
+ ? blink::WebURLRequest::SkipServiceWorker::All
+ : blink::WebURLRequest::SkipServiceWorker::None);
WebURLLoaderOptions options;
if (has_universal_access_) {
diff --git a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
index 00fbe5d631b..3ca1c3b1b9f 100644
--- a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
@@ -149,7 +149,10 @@ int32_t PepperVideoDecoderHost::OnHostMsgInitialize(
// it is okay to immediately send IPC messages.
if (command_buffer->channel()) {
decoder_.reset(new media::GpuVideoDecodeAcceleratorHost(command_buffer));
- if (decoder_->Initialize(profile_, this)) {
+ media::VideoDecodeAccelerator::Config vda_config(profile_);
+ vda_config.supported_output_formats.assign(
+ {media::PIXEL_FORMAT_XRGB, media::PIXEL_FORMAT_ARGB});
+ if (decoder_->Initialize(vda_config, this)) {
initialized_ = true;
return PP_OK;
}
@@ -351,6 +354,7 @@ int32_t PepperVideoDecoderHost::OnHostMsgReset(
void PepperVideoDecoderHost::ProvidePictureBuffers(
uint32_t requested_num_of_buffers,
+ media::VideoPixelFormat format,
uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) {
diff --git a/chromium/content/renderer/pepper/pepper_video_decoder_host.h b/chromium/content/renderer/pepper/pepper_video_decoder_host.h
index 308ba447598..e0f383a651b 100644
--- a/chromium/content/renderer/pepper/pepper_video_decoder_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_decoder_host.h
@@ -73,6 +73,7 @@ class CONTENT_EXPORT PepperVideoDecoderHost
// media::VideoDecodeAccelerator::Client implementation.
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
+ media::VideoPixelFormat format,
uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) override;
diff --git a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
index 8438c0f51d3..0d0997b5047 100644
--- a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
@@ -441,12 +441,14 @@ void PepperVideoEncoderHost::RequireBitstreamBuffers(
}
void PepperVideoEncoderHost::BitstreamBufferReady(int32_t buffer_id,
- size_t payload_size,
- bool key_frame) {
+ size_t payload_size,
+ bool key_frame,
+ base::TimeDelta /* timestamp */) {
DCHECK(RenderThreadImpl::current());
DCHECK(shm_buffers_[buffer_id]->in_use);
shm_buffers_[buffer_id]->in_use = false;
+ // TODO: Pass timestamp. Tracked in crbug/613984.
host()->SendUnsolicitedReply(
pp_resource(),
PpapiPluginMsg_VideoEncoder_BitstreamBufferReady(
@@ -527,10 +529,10 @@ bool PepperVideoEncoderHost::EnsureGpuChannel() {
return false;
command_buffer_ = gpu::CommandBufferProxyImpl::Create(
- std::move(channel), gpu::kNullSurfaceHandle, gfx::Size(), nullptr,
+ std::move(channel), gpu::kNullSurfaceHandle, nullptr,
gpu::GPU_STREAM_DEFAULT, gpu::GpuStreamPriority::NORMAL,
gpu::gles2::ContextCreationAttribHelper(), GURL::EmptyGURL(),
- gfx::PreferIntegratedGpu, base::ThreadTaskRunnerHandle::Get());
+ base::ThreadTaskRunnerHandle::Get());
if (!command_buffer_) {
Close();
return false;
diff --git a/chromium/content/renderer/pepper/pepper_video_encoder_host.h b/chromium/content/renderer/pepper/pepper_video_encoder_host.h
index 53b95069119..d3f8e2a4eb0 100644
--- a/chromium/content/renderer/pepper/pepper_video_encoder_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_encoder_host.h
@@ -71,7 +71,8 @@ class CONTENT_EXPORT PepperVideoEncoderHost
size_t output_buffer_size) override;
void BitstreamBufferReady(int32_t bitstream_buffer_id,
size_t payload_size,
- bool key_frame) override;
+ bool key_frame,
+ base::TimeDelta timestamp) override;
void NotifyError(media::VideoEncodeAccelerator::Error error) override;
// ResourceHost implementation.
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
index 813820319f5..3949db81188 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -9,7 +9,9 @@
#include <utility>
#include "base/debug/crash_logging.h"
-#include "base/message_loop/message_loop.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/pepper/message_channel.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
@@ -155,7 +157,7 @@ void PepperWebPluginImpl::destroy() {
instance_ = nullptr;
}
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
v8::Local<v8::Object> PepperWebPluginImpl::v8ScriptableObject(
@@ -199,12 +201,8 @@ void PepperWebPluginImpl::updateGeometry(
const WebVector<WebRect>& cut_outs_rects,
bool is_visible) {
plugin_rect_ = window_rect;
- if (instance_ && !instance_->FlashIsFullscreenOrPending()) {
- std::vector<gfx::Rect> cut_outs;
- for (size_t i = 0; i < cut_outs_rects.size(); ++i)
- cut_outs.push_back(cut_outs_rects[i]);
- instance_->ViewChanged(plugin_rect_, clip_rect, unobscured_rect, cut_outs);
- }
+ if (instance_ && !instance_->FlashIsFullscreenOrPending())
+ instance_->ViewChanged(plugin_rect_, clip_rect, unobscured_rect);
}
void PepperWebPluginImpl::updateFocus(bool focused,
@@ -271,8 +269,8 @@ bool PepperWebPluginImpl::startFind(const blink::WebString& search_text,
return instance_->StartFind(search_text, case_sensitive, identifier);
}
-void PepperWebPluginImpl::selectFindResult(bool forward) {
- instance_->SelectFindResult(forward);
+void PepperWebPluginImpl::selectFindResult(bool forward, int identifier) {
+ instance_->SelectFindResult(forward, identifier);
}
void PepperWebPluginImpl::stopFind() { instance_->StopFind(); }
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.h b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
index 49a0832c5ae..3de02b80c1a 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.h
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
@@ -70,7 +70,7 @@ class PepperWebPluginImpl : public blink::WebPlugin {
bool startFind(const blink::WebString& search_text,
bool case_sensitive,
int identifier) override;
- void selectFindResult(bool forward) override;
+ void selectFindResult(bool forward, int identifier) override;
void stopFind() override;
bool supportsPaginatedPrint() override;
bool isPrintScalingDisabled() override;
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.cc b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
index 36d65e3f8fc..1879b7e9fe2 100644
--- a/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
@@ -7,9 +7,11 @@
#include <string>
#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
+#include "base/location.h"
#include "base/metrics/histogram.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "content/common/frame_messages.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_frame.h"
@@ -66,6 +68,10 @@ bool PluginPowerSaverHelper::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+void PluginPowerSaverHelper::OnDestruct() {
+ delete this;
+}
+
void PluginPowerSaverHelper::OnUpdatePluginContentOriginWhitelist(
const std::set<url::Origin>& origin_whitelist) {
origin_whitelist_ = origin_whitelist;
@@ -76,8 +82,8 @@ void PluginPowerSaverHelper::OnUpdatePluginContentOriginWhitelist(
if (origin_whitelist.count(it->content_origin)) {
// Because the unthrottle callback may register another peripheral plugin
// and invalidate our iterator, we cannot run it synchronously.
- base::MessageLoop::current()->PostTask(FROM_HERE,
- it->unthrottle_callback);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ it->unthrottle_callback);
it = peripheral_plugins_.erase(it);
} else {
++it;
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.h b/chromium/content/renderer/pepper/plugin_power_saver_helper.h
index 2f3bb442657..0de22ddf3b9 100644
--- a/chromium/content/renderer/pepper/plugin_power_saver_helper.h
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.h
@@ -57,6 +57,7 @@ class CONTENT_EXPORT PluginPowerSaverHelper : public RenderFrameObserver {
void DidCommitProvisionalLoad(bool is_new_navigation,
bool is_same_page_navigation) override;
bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() override;
void OnUpdatePluginContentOriginWhitelist(
const std::set<url::Origin>& origin_whitelist);
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc b/chromium/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc
index d701c31b251..35b8388f88c 100644
--- a/chromium/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <tuple>
+
#include "base/macros.h"
#include "base/run_loop.h"
#include "content/common/frame_messages.h"
@@ -64,7 +66,7 @@ TEST_F(PluginPowerSaverHelperTest, TemporaryOriginWhitelist) {
FrameHostMsg_PluginContentOriginAllowed::Param params;
FrameHostMsg_PluginContentOriginAllowed::Read(msg, &params);
EXPECT_TRUE(url::Origin(GURL("http://other.com"))
- .IsSameOriginWith(base::get<0>(params)));
+ .IsSameOriginWith(std::get<0>(params)));
}
TEST_F(PluginPowerSaverHelperTest, UnthrottleOnExPostFactoWhitelist) {
diff --git a/chromium/content/renderer/pepper/ppb_audio_impl.cc b/chromium/content/renderer/pepper/ppb_audio_impl.cc
index 98bf7637f4a..43426b5b5fa 100644
--- a/chromium/content/renderer/pepper/ppb_audio_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_audio_impl.cc
@@ -5,11 +5,11 @@
#include "content/renderer/pepper/ppb_audio_impl.h"
#include "base/logging.h"
+#include "content/renderer/pepper/pepper_audio_controller.h"
#include "content/renderer/pepper/pepper_platform_audio_output.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_instance_throttler_impl.h"
#include "content/renderer/render_frame_impl.h"
-#include "content/renderer/render_view_impl.h"
#include "media/audio/audio_output_controller.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/ppb_audio.h"
@@ -44,8 +44,11 @@ PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance)
PPB_Audio_Impl::~PPB_Audio_Impl() {
PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>(
PepperPluginInstance::Get(pp_instance()));
- if (instance && instance->throttler()) {
- instance->throttler()->RemoveObserver(this);
+ if (instance) {
+ if (instance->throttler()) {
+ instance->throttler()->RemoveObserver(this);
+ }
+ instance->audio_controller().RemoveInstance(this);
}
// Calling ShutDown() makes sure StreamCreated cannot be called anymore and
@@ -83,6 +86,9 @@ PP_Bool PPB_Audio_Impl::StartPlayback() {
return PP_TRUE;
}
+ if (instance)
+ instance->audio_controller().AddInstance(this);
+
SetStartPlaybackState();
return PP_FromBool(audio_->StartPlayback());
}
@@ -97,6 +103,11 @@ PP_Bool PPB_Audio_Impl::StopPlayback() {
StartDeferredPlayback();
}
+ PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>(
+ PepperPluginInstance::Get(pp_instance()));
+ if (instance)
+ instance->audio_controller().RemoveInstance(this);
+
if (!playing())
return PP_TRUE;
if (!audio_->StopPlayback())
@@ -173,8 +184,17 @@ void PPB_Audio_Impl::StartDeferredPlayback() {
DCHECK(playback_throttled_);
playback_throttled_ = false;
+ PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>(
+ PepperPluginInstance::Get(pp_instance()));
+ if (instance)
+ instance->audio_controller().AddInstance(this);
+
SetStartPlaybackState();
audio_->StartPlayback();
}
+void PPB_Audio_Impl::SetVolume(double volume) {
+ if (audio_)
+ audio_->SetVolume(volume);
+}
} // namespace content
diff --git a/chromium/content/renderer/pepper/ppb_audio_impl.h b/chromium/content/renderer/pepper/ppb_audio_impl.h
index 311dfb9306c..e0618ffb29d 100644
--- a/chromium/content/renderer/pepper/ppb_audio_impl.h
+++ b/chromium/content/renderer/pepper/ppb_audio_impl.h
@@ -50,6 +50,8 @@ class PPB_Audio_Impl : public ppapi::Resource,
int32_t GetSharedMemory(base::SharedMemory** shm,
uint32_t* shm_size) override;
+ void SetVolume(double volume);
+
private:
~PPB_Audio_Impl() override;
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
index a908b6fbe0f..5e0b5f32641 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -28,6 +28,7 @@
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
+#include "third_party/khronos/GLES2/gl2.h"
using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Graphics3D_API;
@@ -114,6 +115,22 @@ void PPB_Graphics3D_Impl::EnsureWorkVisible() {
command_buffer_->EnsureWorkVisible();
}
+void PPB_Graphics3D_Impl::TakeFrontBuffer() {
+ if (!taken_front_buffer_.IsZero()) {
+ DLOG(ERROR)
+ << "TakeFrontBuffer should only be called once before DoSwapBuffers";
+ return;
+ }
+ taken_front_buffer_ = GenerateMailbox();
+ command_buffer_->TakeFrontBuffer(taken_front_buffer_);
+}
+
+void PPB_Graphics3D_Impl::ReturnFrontBuffer(const gpu::Mailbox& mailbox,
+ const gpu::SyncToken& sync_token,
+ bool is_lost) {
+ command_buffer_->ReturnFrontBuffer(mailbox, sync_token, is_lost);
+}
+
bool PPB_Graphics3D_Impl::BindToInstance(bool bind) {
bound_to_instance_ = bind;
return true;
@@ -143,8 +160,10 @@ gpu::GpuControl* PPB_Graphics3D_Impl::GetGpuControl() {
int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token) {
DCHECK(command_buffer_);
- if (sync_token.HasData())
- sync_token_ = sync_token;
+ if (taken_front_buffer_.IsZero()) {
+ DLOG(ERROR) << "TakeFrontBuffer should be called before DoSwapBuffers";
+ return PP_ERROR_FAILED;
+ }
if (bound_to_instance_) {
// If we are bound to the instance, we need to ask the compositor
@@ -154,14 +173,18 @@ int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token) {
//
// Don't need to check for NULL from GetPluginInstance since when we're
// bound, we know our instance is valid.
- HostGlobals::Get()->GetInstance(pp_instance())->CommitBackingTexture();
+ cc::TextureMailbox texture_mailbox(taken_front_buffer_, sync_token,
+ GL_TEXTURE_2D);
+ taken_front_buffer_.SetZero();
+ HostGlobals::Get()
+ ->GetInstance(pp_instance())
+ ->CommitTextureMailbox(texture_mailbox);
commit_pending_ = true;
} else {
// Wait for the command to complete on the GPU to allow for throttling.
command_buffer_->SignalSyncToken(
- sync_token_,
- base::Bind(&PPB_Graphics3D_Impl::OnSwapBuffers,
- weak_ptr_factory_.GetWeakPtr()));
+ sync_token, base::Bind(&PPB_Graphics3D_Impl::OnSwapBuffers,
+ weak_ptr_factory_.GetWeakPtr()));
}
return PP_OK_COMPLETIONPENDING;
@@ -202,9 +225,9 @@ bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
if (!channel)
return false;
- gfx::Size surface_size;
+ gpu::gles2::ContextCreationAttribHelper attrib_helper;
std::vector<int32_t> attribs;
- gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
+ attrib_helper.gpu_preference = gl::PreferDiscreteGpu;
// TODO(alokp): Change CommandBufferProxyImpl::Create()
// interface to accept width and height in the attrib_list so that
// we do not need to filter for width and height here.
@@ -213,16 +236,16 @@ bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
attr += 2) {
switch (attr[0]) {
case PP_GRAPHICS3DATTRIB_WIDTH:
- surface_size.set_width(attr[1]);
+ attrib_helper.offscreen_framebuffer_size.set_width(attr[1]);
break;
case PP_GRAPHICS3DATTRIB_HEIGHT:
- surface_size.set_height(attr[1]);
+ attrib_helper.offscreen_framebuffer_size.set_height(attr[1]);
break;
case PP_GRAPHICS3DATTRIB_GPU_PREFERENCE:
- gpu_preference =
+ attrib_helper.gpu_preference =
(attr[1] == PP_GRAPHICS3DATTRIB_GPU_PREFERENCE_LOW_POWER)
- ? gfx::PreferIntegratedGpu
- : gfx::PreferDiscreteGpu;
+ ? gl::PreferIntegratedGpu
+ : gl::PreferDiscreteGpu;
break;
case PP_GRAPHICS3DATTRIB_ALPHA_SIZE:
has_alpha_ = attr[1] > 0;
@@ -235,7 +258,6 @@ bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
}
attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
}
- gpu::gles2::ContextCreationAttribHelper attrib_helper;
if (!attrib_helper.Parse(attribs))
return false;
@@ -247,10 +269,9 @@ bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
}
command_buffer_ = gpu::CommandBufferProxyImpl::Create(
- std::move(channel), gpu::kNullSurfaceHandle, surface_size, share_buffer,
- gpu::GPU_STREAM_DEFAULT, gpu::GpuStreamPriority::NORMAL,
- attrib_helper, GURL::EmptyGURL(), gpu_preference,
- base::ThreadTaskRunnerHandle::Get());
+ std::move(channel), gpu::kNullSurfaceHandle, share_buffer,
+ gpu::GPU_STREAM_DEFAULT, gpu::GpuStreamPriority::NORMAL, attrib_helper,
+ GURL::EmptyGURL(), base::ThreadTaskRunnerHandle::Get());
if (!command_buffer_)
return false;
@@ -263,10 +284,6 @@ bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
if (command_buffer_id)
*command_buffer_id = command_buffer_->GetCommandBufferID();
- mailbox_ = gpu::Mailbox::Generate();
- if (!command_buffer_->ProduceFrontBuffer(mailbox_))
- return false;
-
return true;
}
@@ -344,4 +361,14 @@ void PPB_Graphics3D_Impl::SendContextLost() {
ppp_graphics_3d->Graphics3DContextLost(this_pp_instance);
}
+gpu::Mailbox PPB_Graphics3D_Impl::GenerateMailbox() {
+ if (!mailboxes_to_reuse_.empty()) {
+ gpu::Mailbox mailbox = mailboxes_to_reuse_.back();
+ mailboxes_to_reuse_.pop_back();
+ return mailbox;
+ }
+
+ return gpu::Mailbox::Generate();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
index 8216f631b7e..abafd2c4b14 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -47,6 +47,10 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared,
gpu::CommandBuffer::State WaitForGetOffsetInRange(int32_t start,
int32_t end) override;
void EnsureWorkVisible() override;
+ void TakeFrontBuffer() override;
+ void ReturnFrontBuffer(const gpu::Mailbox& mailbox,
+ const gpu::SyncToken& sync_token,
+ bool is_lost);
// Binds/unbinds the graphics of this context with the associated instance.
// Returns true if binding/unbinding is successful.
@@ -59,11 +63,6 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared,
// These messages are used to send Flush callbacks to the plugin.
void ViewInitiatedPaint();
- void GetBackingMailbox(gpu::Mailbox* mailbox, gpu::SyncToken* sync_token) {
- *mailbox = mailbox_;
- *sync_token = sync_token_;
- }
-
gpu::CommandBufferProxyImpl* GetCommandBufferProxy();
protected:
@@ -92,6 +91,16 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared,
// Notifications sent to plugin.
void SendContextLost();
+ // Reuses a mailbox if one is available, otherwise makes a new one.
+ gpu::Mailbox GenerateMailbox();
+
+ // A front buffer that was recently taken from the command buffer. This should
+ // be immediately consumed by DoSwapBuffers().
+ gpu::Mailbox taken_front_buffer_;
+
+ // Mailboxes that are no longer in use.
+ std::vector<gpu::Mailbox> mailboxes_to_reuse_;
+
// True if context is bound to instance.
bool bound_to_instance_;
// True when waiting for compositor to commit our backing texture.
@@ -101,8 +110,6 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared,
bool lost_context_ = false;
#endif
- gpu::Mailbox mailbox_;
- gpu::SyncToken sync_token_;
bool has_alpha_;
std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_;
diff --git a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
index 0f31ea09a21..360f5d4e3e5 100644
--- a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
@@ -239,6 +239,7 @@ void PPB_VideoDecoder_Impl::Destroy() {
void PPB_VideoDecoder_Impl::ProvidePictureBuffers(
uint32_t requested_num_of_buffers,
+ media::VideoPixelFormat format,
uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) {
diff --git a/chromium/content/renderer/pepper/ppb_video_decoder_impl.h b/chromium/content/renderer/pepper/ppb_video_decoder_impl.h
index c0597a23211..635a5ce47e4 100644
--- a/chromium/content/renderer/pepper/ppb_video_decoder_impl.h
+++ b/chromium/content/renderer/pepper/ppb_video_decoder_impl.h
@@ -45,6 +45,7 @@ class PPB_VideoDecoder_Impl : public ppapi::PPB_VideoDecoder_Shared,
// media::VideoDecodeAccelerator::Client implementation.
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
+ media::VideoPixelFormat format,
uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) override;
diff --git a/chromium/content/renderer/pepper/video_encoder_shim.cc b/chromium/content/renderer/pepper/video_encoder_shim.cc
index ab466b395da..0887863363b 100644
--- a/chromium/content/renderer/pepper/video_encoder_shim.cc
+++ b/chromium/content/renderer/pepper/video_encoder_shim.cc
@@ -487,7 +487,8 @@ void VideoEncoderShim::OnBitstreamBufferReady(
bool key_frame) {
DCHECK(RenderThreadImpl::current());
- host_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame);
+ host_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame,
+ frame->timestamp());
}
void VideoEncoderShim::OnNotifyError(
diff --git a/chromium/content/renderer/presentation/presentation_dispatcher.cc b/chromium/content/renderer/presentation/presentation_dispatcher.cc
index bcc2eacc4c4..e9360099ed0 100644
--- a/chromium/content/renderer/presentation/presentation_dispatcher.cc
+++ b/chromium/content/renderer/presentation/presentation_dispatcher.cc
@@ -8,12 +8,13 @@
#include <utility>
#include <vector>
+#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "content/public/common/presentation_constants.h"
-#include "content/public/common/service_registry.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/presentation/presentation_connection_client.h"
+#include "services/shell/public/cpp/interface_provider.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationAvailabilityObserver.h"
@@ -308,6 +309,10 @@ void PresentationDispatcher::DidCommitProvisionalLoad(
std::swap(message_request_queue_, empty);
}
+void PresentationDispatcher::OnDestruct() {
+ delete this;
+}
+
void PresentationDispatcher::OnScreenAvailabilityUpdated(
const mojo::String& url, bool available) {
const std::string& availability_url = url.get();
@@ -450,8 +455,7 @@ void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() {
if (presentation_service_.get())
return;
- render_frame()->GetServiceRegistry()->ConnectToRemoteService(
- mojo::GetProxy(&presentation_service_));
+ render_frame()->GetRemoteInterfaces()->GetInterface(&presentation_service_);
presentation_service_->SetClient(binding_.CreateInterfacePtrAndBind());
}
diff --git a/chromium/content/renderer/presentation/presentation_dispatcher.h b/chromium/content/renderer/presentation/presentation_dispatcher.h
index 2aee2c0d710..e5fb81427c1 100644
--- a/chromium/content/renderer/presentation/presentation_dispatcher.h
+++ b/chromium/content/renderer/presentation/presentation_dispatcher.h
@@ -94,6 +94,7 @@ class CONTENT_EXPORT PresentationDispatcher
void DidCommitProvisionalLoad(
bool is_new_navigation,
bool is_same_page_navigation) override;
+ void OnDestruct() override;
// blink::mojom::PresentationServiceClient
void OnScreenAvailabilityNotSupported(const mojo::String& url) override;
diff --git a/chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc b/chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc
index b865237174a..471024e90a7 100644
--- a/chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc
+++ b/chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc
@@ -39,6 +39,10 @@ bool PushMessagingDispatcher::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+void PushMessagingDispatcher::OnDestruct() {
+ delete this;
+}
+
void PushMessagingDispatcher::subscribe(
blink::WebServiceWorkerRegistration* service_worker_registration,
const blink::WebPushSubscriptionOptions& options,
diff --git a/chromium/content/renderer/push_messaging/push_messaging_dispatcher.h b/chromium/content/renderer/push_messaging/push_messaging_dispatcher.h
index 5dcbf8bf943..5fb894f6b5c 100644
--- a/chromium/content/renderer/push_messaging/push_messaging_dispatcher.h
+++ b/chromium/content/renderer/push_messaging/push_messaging_dispatcher.h
@@ -39,8 +39,9 @@ class PushMessagingDispatcher : public RenderFrameObserver,
~PushMessagingDispatcher() override;
private:
- // RenderFrame::Observer implementation.
+ // RenderFrameObserver implementation.
bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() override;
// WebPushClient implementation.
void subscribe(
diff --git a/chromium/content/renderer/raster_worker_pool_unittest.cc b/chromium/content/renderer/raster_worker_pool_unittest.cc
deleted file mode 100644
index 73f83dcdf6a..00000000000
--- a/chromium/content/renderer/raster_worker_pool_unittest.cc
+++ /dev/null
@@ -1,120 +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 "base/test/sequenced_task_runner_test_template.h"
-#include "base/test/task_runner_test_template.h"
-#include "base/threading/simple_thread.h"
-#include "cc/test/task_graph_runner_test_template.h"
-#include "content/renderer/raster_worker_pool.h"
-
-namespace base {
-namespace {
-
-// Number of threads spawned in tests.
-const int kNumThreads = 4;
-
-class RasterWorkerPoolTestDelegate {
- public:
- RasterWorkerPoolTestDelegate()
- : raster_worker_pool_(new content::RasterWorkerPool()) {}
-
- void StartTaskRunner() {
- raster_worker_pool_->Start(kNumThreads);
- }
-
- scoped_refptr<content::RasterWorkerPool> GetTaskRunner() {
- return raster_worker_pool_;
- }
-
- void StopTaskRunner() { raster_worker_pool_->FlushForTesting(); }
-
- ~RasterWorkerPoolTestDelegate() { raster_worker_pool_->Shutdown(); }
-
- private:
- scoped_refptr<content::RasterWorkerPool> raster_worker_pool_;
-};
-
-INSTANTIATE_TYPED_TEST_CASE_P(RasterWorkerPool,
- TaskRunnerTest,
- RasterWorkerPoolTestDelegate);
-
-class RasterWorkerPoolSequencedTestDelegate {
- public:
- RasterWorkerPoolSequencedTestDelegate()
- : raster_worker_pool_(new content::RasterWorkerPool()) {}
-
- void StartTaskRunner() {
- raster_worker_pool_->Start(kNumThreads);
- }
-
- scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() {
- return raster_worker_pool_->CreateSequencedTaskRunner();
- }
-
- void StopTaskRunner() { raster_worker_pool_->FlushForTesting(); }
-
- ~RasterWorkerPoolSequencedTestDelegate() { raster_worker_pool_->Shutdown(); }
-
- private:
- scoped_refptr<content::RasterWorkerPool> raster_worker_pool_;
-};
-
-INSTANTIATE_TYPED_TEST_CASE_P(RasterWorkerPool,
- SequencedTaskRunnerTest,
- RasterWorkerPoolSequencedTestDelegate);
-
-} // namespace
-} // namespace base
-
-namespace cc {
-namespace {
-
-template <int NumThreads>
-class RasterWorkerPoolTaskGraphRunnerTestDelegate {
- public:
- RasterWorkerPoolTaskGraphRunnerTestDelegate()
- : raster_worker_pool_(new content::RasterWorkerPool()) {}
-
- void StartTaskGraphRunner() {
- raster_worker_pool_->Start(NumThreads);
- }
-
- cc::TaskGraphRunner* GetTaskGraphRunner() {
- return raster_worker_pool_->GetTaskGraphRunner();
- }
-
- void StopTaskGraphRunner() { raster_worker_pool_->FlushForTesting(); }
-
- ~RasterWorkerPoolTaskGraphRunnerTestDelegate() {
- raster_worker_pool_->Shutdown();
- }
-
- private:
- scoped_refptr<content::RasterWorkerPool> raster_worker_pool_;
-};
-
-// Multithreaded tests.
-INSTANTIATE_TYPED_TEST_CASE_P(RasterWorkerPool_1_Threads,
- TaskGraphRunnerTest,
- RasterWorkerPoolTaskGraphRunnerTestDelegate<1>);
-INSTANTIATE_TYPED_TEST_CASE_P(RasterWorkerPool_2_Threads,
- TaskGraphRunnerTest,
- RasterWorkerPoolTaskGraphRunnerTestDelegate<2>);
-INSTANTIATE_TYPED_TEST_CASE_P(RasterWorkerPool_3_Threads,
- TaskGraphRunnerTest,
- RasterWorkerPoolTaskGraphRunnerTestDelegate<3>);
-INSTANTIATE_TYPED_TEST_CASE_P(RasterWorkerPool_4_Threads,
- TaskGraphRunnerTest,
- RasterWorkerPoolTaskGraphRunnerTestDelegate<4>);
-INSTANTIATE_TYPED_TEST_CASE_P(RasterWorkerPool_5_Threads,
- TaskGraphRunnerTest,
- RasterWorkerPoolTaskGraphRunnerTestDelegate<5>);
-
-// Single threaded tests.
-INSTANTIATE_TYPED_TEST_CASE_P(RasterWorkerPool,
- SingleThreadTaskGraphRunnerTest,
- RasterWorkerPoolTaskGraphRunnerTestDelegate<1>);
-
-} // namespace
-} // namespace cc
diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc
index 8d049b23fc0..faa00b78063 100644
--- a/chromium/content/renderer/render_frame_impl.cc
+++ b/chromium/content/renderer/render_frame_impl.cc
@@ -50,6 +50,7 @@
#include "content/child/weburlresponse_extradata_impl.h"
#include "content/common/accessibility_messages.h"
#include "content/common/clipboard_messages.h"
+#include "content/common/content_constants_internal.h"
#include "content/common/content_security_policy_header.h"
#include "content/common/frame_messages.h"
#include "content/common/frame_replication_state.h"
@@ -69,8 +70,10 @@
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
+#include "content/public/common/file_chooser_file_info.h"
+#include "content/public/common/file_chooser_params.h"
#include "content/public/common/isolated_world_ids.h"
-#include "content/public/common/mhtml_generation_params.h"
+#include "content/public/common/mojo_shell_connection.h"
#include "content/public/common/page_state.h"
#include "content/public/common/resource_response.h"
#include "content/public/common/url_constants.h"
@@ -82,7 +85,7 @@
#include "content/public/renderer/navigation_state.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/renderer_ppapi_host.h"
-#include "content/renderer/accessibility/renderer_accessibility.h"
+#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "content/renderer/bluetooth/web_bluetooth_impl.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
@@ -110,10 +113,11 @@
#include "content/renderer/media/user_media_client_impl.h"
#include "content/renderer/media/web_media_element_source_utils.h"
#include "content/renderer/media/webmediaplayer_ms.h"
-#include "content/renderer/mojo/service_registry_js_wrapper.h"
+#include "content/renderer/mojo/interface_provider_js_wrapper.h"
#include "content/renderer/mojo_bindings_controller.h"
#include "content/renderer/navigation_state_impl.h"
#include "content/renderer/notification_permission_dispatcher.h"
+#include "content/renderer/pepper/pepper_audio_controller.h"
#include "content/renderer/pepper/plugin_instance_throttler_impl.h"
#include "content/renderer/presentation/presentation_dispatcher.h"
#include "content/renderer/push_messaging/push_messaging_dispatcher.h"
@@ -145,18 +149,22 @@
#include "media/blink/webencryptedmediaclient_impl.h"
#include "media/blink/webmediaplayer_impl.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
-#include "mojo/common/url_type_converters.h"
#include "mojo/edk/js/core.h"
#include "mojo/edk/js/support.h"
#include "net/base/data_url.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_util.h"
+#include "services/shell/public/cpp/interface_provider.h"
+#include "services/shell/public/cpp/interface_registry.h"
+#include "storage/common/data_element.h"
+#include "third_party/WebKit/public/platform/FilePathConversion.h"
#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebCachePolicy.h"
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebMediaPlayerSource.h"
+#include "third_party/WebKit/public/platform/WebPoint.h"
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -169,6 +177,7 @@
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "third_party/WebKit/public/web/WebFrameSerializer.h"
+#include "third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h"
#include "third_party/WebKit/public/web/WebFrameWidget.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
@@ -231,17 +240,17 @@
#endif
#if defined(ENABLE_MOJO_CDM)
-#include "media/mojo/services/mojo_cdm_factory.h" // nogncheck
+#include "media/mojo/clients/mojo_cdm_factory.h" // nogncheck
#endif
#if defined(ENABLE_MOJO_RENDERER)
-#include "media/mojo/services/mojo_renderer_factory.h" // nogncheck
+#include "media/mojo/clients/mojo_renderer_factory.h" // nogncheck
#else
#include "media/renderers/default_renderer_factory.h"
#endif
#if defined(ENABLE_MOJO_AUDIO_DECODER) || defined(ENABLE_MOJO_VIDEO_DECODER)
-#include "media/mojo/services/mojo_decoder_factory.h" // nogncheck
+#include "media/mojo/clients/mojo_decoder_factory.h" // nogncheck
#endif
using blink::WebCachePolicy;
@@ -273,6 +282,7 @@ using blink::WebNavigationType;
using blink::WebNode;
using blink::WebPluginDocument;
using blink::WebPluginParams;
+using blink::WebPoint;
using blink::WebPopupMenuInfo;
using blink::WebRange;
using blink::WebRect;
@@ -301,6 +311,10 @@ using blink::WebFloatPoint;
using blink::WebFloatRect;
#endif
+#define STATIC_ASSERT_ENUM(a, b) \
+ static_assert(static_cast<int>(a) == static_cast<int>(b), \
+ "mismatching enums: " #a)
+
namespace content {
namespace {
@@ -522,10 +536,11 @@ WebURLRequest CreateURLRequestForNavigation(
}
request.setHTTPMethod(WebString::fromUTF8(common_params.method));
+ request.setLoFiState(
+ static_cast<WebURLRequest::LoFiState>(common_params.lofi_state));
RequestExtraData* extra_data = new RequestExtraData();
extra_data->set_stream_override(std::move(stream_override));
- extra_data->set_lofi_state(common_params.lofi_state);
request.setExtraData(extra_data);
// Set the ui timestamp for this navigation. Currently the timestamp here is
@@ -597,8 +612,9 @@ CommonNavigationParams MakeCommonNavigationParams(
return CommonNavigationParams(
request->url(), referrer, extra_data->transition_type(),
FrameMsg_Navigate_Type::NORMAL, true, should_replace_current_entry,
- ui_timestamp, report_type, GURL(), GURL(), extra_data->lofi_state(),
- base::TimeTicks::Now(), request->httpMethod().latin1());
+ ui_timestamp, report_type, GURL(), GURL(),
+ static_cast<LoFiState>(request->getLoFiState()),base::TimeTicks::Now(),
+ request->httpMethod().latin1(), GetRequestBodyForWebURLRequest(*request));
}
media::Context3D GetSharedMainThreadContext3D(
@@ -648,7 +664,7 @@ RenderFrameImpl::CreateRenderFrameImplFunction g_create_render_frame_impl =
nullptr;
void OnGotInstanceID(shell::mojom::ConnectResult result,
- const std::string& user_id,
+ mojo::String user_id,
uint32_t instance_id) {}
WebString ConvertRelativePathToHtmlAttribute(const base::FilePath& path) {
@@ -739,6 +755,12 @@ class MHTMLPartsGenerationDelegate
return WebString::fromUTF8(content_id);
}
+ blink::WebFrameSerializerCacheControlPolicy cacheControlPolicy() override {
+ return params_.mhtml_cache_control_policy;
+ }
+
+ bool useBinaryEncoding() override { return params_.mhtml_binary_encoding; }
+
private:
const FrameMsg_SerializeAsMHTML_Params& params_;
std::set<std::string>* digests_of_uris_of_serialized_resources_;
@@ -793,6 +815,10 @@ bool IsContentWithCertificateErrorsRelevantToUI(
ssl_status.connection_status);
}
+bool IsHttpPost(const blink::WebURLRequest& request) {
+ return request.httpMethod().utf8() == "POST";
+}
+
#if defined(OS_ANDROID)
// Returns true if WMPI should be used for playback, false otherwise.
//
@@ -840,6 +866,14 @@ bool UseMojoCdm() {
} // namespace
+struct RenderFrameImpl::PendingFileChooser {
+ PendingFileChooser(const FileChooserParams& p,
+ blink::WebFileChooserCompletion* c)
+ : params(p), completion(c) {}
+ FileChooserParams params;
+ blink::WebFileChooserCompletion* completion; // MAY BE NULL to skip callback.
+};
+
// static
RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view,
int32_t routing_id) {
@@ -887,9 +921,6 @@ RenderFrameImpl* RenderFrameImpl::CreateMainFrame(
render_view->webview()->setMainFrame(web_frame);
render_frame->render_widget_ = RenderWidget::CreateForFrame(
widget_routing_id, hidden, screen_info, compositor_deps, web_frame);
- // TODO(kenrb): Observing shouldn't be necessary when we sort out
- // WasShown and WasHidden, separating page-level visibility from
- // frame-level visibility.
// TODO(avi): This DCHECK is to track cleanup for https://crbug.com/545684
DCHECK_EQ(render_view->GetWidget(), render_frame->render_widget_)
<< "Main frame is no longer reusing the RenderView as its widget! "
@@ -952,8 +983,7 @@ void RenderFrameImpl::CreateFrame(
render_frame->InitializeBlameContext(nullptr);
render_frame->proxy_routing_id_ = proxy_routing_id;
web_frame = blink::WebLocalFrame::createProvisional(
- render_frame, proxy->web_frame(), replicated_state.sandbox_flags,
- frame_owner_properties);
+ render_frame, proxy->web_frame(), replicated_state.sandbox_flags);
}
render_frame->BindToWebFrame(web_frame);
CHECK(parent_routing_id != MSG_ROUTING_NONE || !web_frame->parent());
@@ -967,12 +997,8 @@ void RenderFrameImpl::CreateFrame(
// TODO(avi): The main frame re-uses the RenderViewImpl as its widget, so
// avoid double-registering the frame as an observer.
// https://crbug.com/545684
- if (web_frame->parent()) {
- // TODO(kenrb): Observing shouldn't be necessary when we sort out
- // WasShown and WasHidden, separating page-level visibility from
- // frame-level visibility.
+ if (web_frame->parent())
render_frame->render_widget_->RegisterRenderFrame(render_frame);
- }
}
render_frame->Initialize();
@@ -1037,7 +1063,6 @@ RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
in_frame_tree_(false),
render_view_(params.render_view->AsWeakPtr()),
routing_id_(params.routing_id),
- is_detaching_(false),
proxy_routing_id_(MSG_ROUTING_NONE),
#if defined(ENABLE_PLUGINS)
plugin_power_saver_helper_(nullptr),
@@ -1064,11 +1089,10 @@ RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
devtools_agent_(nullptr),
push_messaging_dispatcher_(NULL),
presentation_dispatcher_(NULL),
- blink_service_registry_(service_registry_.GetWeakPtr()),
screen_orientation_dispatcher_(NULL),
manifest_manager_(NULL),
accessibility_mode_(AccessibilityModeOff),
- renderer_accessibility_(NULL),
+ render_accessibility_(NULL),
media_player_delegate_(NULL),
is_using_lofi_(false),
effective_connection_type_(
@@ -1080,7 +1104,19 @@ RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
focused_pepper_plugin_(nullptr),
pepper_last_mouse_event_target_(nullptr),
#endif
+ frame_binding_(this),
weak_factory_(this) {
+ // We don't have a shell::Connection at this point, so use nullptr.
+ // TODO(beng): We should fix this, so we can apply policy about which
+ // interfaces get exposed.
+ interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+ shell::mojom::InterfaceProviderPtr remote_interfaces;
+ pending_remote_interface_provider_request_ = GetProxy(&remote_interfaces);
+ remote_interfaces_.reset(new shell::InterfaceProvider);
+ remote_interfaces_->Bind(std::move(remote_interfaces));
+ blink_service_registry_.reset(new BlinkServiceRegistryImpl(
+ remote_interfaces_->GetWeakPtr()));
+
std::pair<RoutingIDFrameMap::iterator, bool> result =
g_routing_id_frame_map.Get().insert(std::make_pair(routing_id_, this));
CHECK(result.second) << "Inserting a duplicate item.";
@@ -1104,6 +1140,15 @@ RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
}
RenderFrameImpl::~RenderFrameImpl() {
+ // If file chooser is still waiting for answer, dispatch empty answer.
+ while (!file_chooser_completions_.empty()) {
+ if (file_chooser_completions_.front()->completion) {
+ file_chooser_completions_.front()->completion->didChooseFile(
+ WebVector<WebString>());
+ }
+ file_chooser_completions_.pop_front();
+ }
+
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, RenderFrameGone());
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnDestruct());
@@ -1176,7 +1221,7 @@ void RenderFrameImpl::Initialize() {
devtools_agent_ = new DevToolsAgent(this);
}
- RegisterMojoServices();
+ RegisterMojoInterfaces();
// We delay calling this until we have the WebFrame so that any observer or
// embedder can call GetWebFrame on any RenderFrame.
@@ -1194,7 +1239,7 @@ void RenderFrameImpl::Initialize() {
void RenderFrameImpl::InitializeBlameContext(RenderFrameImpl* parent_frame) {
DCHECK(!blame_context_);
- blame_context_ = new FrameBlameContext(this, parent_frame);
+ blame_context_ = base::WrapUnique(new FrameBlameContext(this, parent_frame));
blame_context_->Initialize();
}
@@ -1392,15 +1437,10 @@ MediaStreamDispatcher* RenderFrameImpl::GetMediaStreamDispatcher() {
}
bool RenderFrameImpl::Send(IPC::Message* message) {
- if (is_detaching_) {
- delete message;
- return false;
- }
-
return RenderThread::Get()->Send(message);
}
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
void RenderFrameImpl::DidHideExternalPopupMenu() {
// We need to clear external_popup_menu_ as soon as ExternalPopupMenu::close
// is called. Otherwise, createExternalPopupMenu() for new popup will fail.
@@ -1447,6 +1487,9 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(FrameMsg_ContextMenuClosed, OnContextMenuClosed)
IPC_MESSAGE_HANDLER(FrameMsg_CustomContextMenuAction,
OnCustomContextMenuAction)
+#if defined(ENABLE_PLUGINS)
+ IPC_MESSAGE_HANDLER(FrameMsg_SetPepperVolume, OnSetPepperVolume)
+#endif //defined(ENABLE_PLUGINS)
IPC_MESSAGE_HANDLER(InputMsg_Undo, OnUndo)
IPC_MESSAGE_HANDLER(InputMsg_Redo, OnRedo)
IPC_MESSAGE_HANDLER(InputMsg_Cut, OnCut)
@@ -1463,6 +1506,8 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
OnMoveRangeSelectionExtent)
IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
+ IPC_MESSAGE_HANDLER(FrameMsg_CopyImageAt, OnCopyImageAt)
+ IPC_MESSAGE_HANDLER(FrameMsg_SaveImageAt, OnSaveImageAt)
IPC_MESSAGE_HANDLER(InputMsg_ExtendSelectionAndDelete,
OnExtendSelectionAndDelete)
IPC_MESSAGE_HANDLER(InputMsg_SetCompositionFromExistingText,
@@ -1506,17 +1551,29 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
OnGetSerializedHtmlWithLocalLinks)
IPC_MESSAGE_HANDLER(FrameMsg_SerializeAsMHTML, OnSerializeAsMHTML)
IPC_MESSAGE_HANDLER(FrameMsg_Find, OnFind)
+ IPC_MESSAGE_HANDLER(FrameMsg_ClearActiveFindMatch, OnClearActiveFindMatch)
IPC_MESSAGE_HANDLER(FrameMsg_StopFinding, OnStopFinding)
IPC_MESSAGE_HANDLER(FrameMsg_EnableViewSourceMode, OnEnableViewSourceMode)
IPC_MESSAGE_HANDLER(FrameMsg_SuppressFurtherDialogs,
OnSuppressFurtherDialogs)
+ IPC_MESSAGE_HANDLER(FrameMsg_RunFileChooserResponse, OnFileChooserResponse)
#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult,
+ IPC_MESSAGE_HANDLER(FrameMsg_ActivateNearestFindResult,
OnActivateNearestFindResult)
+ IPC_MESSAGE_HANDLER(FrameMsg_GetNearestFindResult,
+ OnGetNearestFindResult)
IPC_MESSAGE_HANDLER(FrameMsg_FindMatchRects, OnFindMatchRects)
- IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
-#elif defined(OS_MACOSX)
+#endif
+
+#if defined(USE_EXTERNAL_POPUP_MENU)
+#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
+#else
+ IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
+#endif
+#endif
+
+#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
#endif
IPC_END_MESSAGE_MAP()
@@ -1552,11 +1609,12 @@ void RenderFrameImpl::OnNavigate(
std::unique_ptr<StreamOverrideParameters>());
}
-void RenderFrameImpl::BindServiceRegistry(
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services) {
- service_registry_.Bind(std::move(services));
- service_registry_.BindRemoteServiceProvider(std::move(exposed_services));
+void RenderFrameImpl::Bind(mojom::FrameRequest request,
+ mojom::FrameHostPtr host) {
+ frame_binding_.Bind(std::move(request));
+ frame_host_ = std::move(host);
+ frame_host_->GetInterfaceProvider(
+ std::move(pending_remote_interface_provider_request_));
}
ManifestManager* RenderFrameImpl::manifest_manager() {
@@ -1568,7 +1626,7 @@ void RenderFrameImpl::SetPendingNavigationParams(
pending_navigation_params_ = std::move(navigation_params);
}
-void RenderFrameImpl::OnBeforeUnload() {
+void RenderFrameImpl::OnBeforeUnload(bool is_reload) {
TRACE_EVENT1("navigation", "RenderFrameImpl::OnBeforeUnload",
"id", routing_id_);
// TODO(creis): Right now, this is only called on the main frame. Make the
@@ -1577,11 +1635,10 @@ void RenderFrameImpl::OnBeforeUnload() {
CHECK(!frame_->parent());
base::TimeTicks before_unload_start_time = base::TimeTicks::Now();
- bool proceed = frame_->dispatchBeforeUnloadEvent();
+ bool proceed = frame_->dispatchBeforeUnloadEvent(is_reload);
base::TimeTicks before_unload_end_time = base::TimeTicks::Now();
- Send(new FrameHostMsg_BeforeUnload_ACK(routing_id_, proceed,
- before_unload_start_time,
- before_unload_end_time));
+ Send(new FrameHostMsg_BeforeUnload_ACK(
+ routing_id_, proceed, before_unload_start_time, before_unload_end_time));
}
void RenderFrameImpl::OnSwapOut(
@@ -1626,14 +1683,6 @@ void RenderFrameImpl::OnSwapOut(
if (!is_main_frame_)
proxy->web_frame()->initializeFromFrame(frame_);
- // Let WebKit know that this view is hidden so it can drop resources and
- // stop compositing.
- // TODO(creis): Support this for subframes as well.
- if (is_main_frame_) {
- render_view_->webview()->setVisibilityState(
- blink::WebPageVisibilityStateHidden, false);
- }
-
RenderViewImpl* render_view = render_view_.get();
bool is_main_frame = is_main_frame_;
int routing_id = GetRoutingID();
@@ -1851,6 +1900,14 @@ void RenderFrameImpl::OnReplaceMisspelling(const base::string16& text) {
frame_->replaceMisspelledRange(text);
}
+void RenderFrameImpl::OnCopyImageAt(int x, int y) {
+ frame_->copyImageAt(WebPoint(x, y));
+}
+
+void RenderFrameImpl::OnSaveImageAt(int x, int y) {
+ frame_->saveImageAt(WebPoint(x, y));
+}
+
void RenderFrameImpl::OnCSSInsertRequest(const std::string& css) {
frame_->document().insertStyleSheet(WebString::fromUTF8(css));
}
@@ -2031,25 +2088,25 @@ void RenderFrameImpl::OnSetAccessibilityMode(AccessibilityMode new_mode) {
if (accessibility_mode_ == new_mode)
return;
accessibility_mode_ = new_mode;
- if (renderer_accessibility_) {
+ if (render_accessibility_) {
// Note: this isn't called automatically by the destructor because
// there'd be no point in calling it in frame teardown, only if there's
// an accessibility mode change but the frame is persisting.
- renderer_accessibility_->DisableAccessibility();
+ render_accessibility_->DisableAccessibility();
- delete renderer_accessibility_;
- renderer_accessibility_ = NULL;
+ delete render_accessibility_;
+ render_accessibility_ = NULL;
}
if (accessibility_mode_ == AccessibilityModeOff)
return;
if (accessibility_mode_ & AccessibilityModeFlagFullTree)
- renderer_accessibility_ = new RendererAccessibility(this);
+ render_accessibility_ = new RenderAccessibilityImpl(this);
}
void RenderFrameImpl::OnSnapshotAccessibilityTree(int callback_id) {
AXContentTreeUpdate response;
- RendererAccessibility::SnapshotAccessibilityTree(this, &response);
+ RenderAccessibilityImpl::SnapshotAccessibilityTree(this, &response);
Send(new AccessibilityHostMsg_SnapshotResponse(
routing_id_, callback_id, response));
}
@@ -2214,6 +2271,31 @@ bool RenderFrameImpl::RunJavaScriptMessage(JavaScriptMessageType type,
return success;
}
+bool RenderFrameImpl::ScheduleFileChooser(
+ const FileChooserParams& params,
+ blink::WebFileChooserCompletion* completion) {
+ static const size_t kMaximumPendingFileChooseRequests = 4;
+ if (file_chooser_completions_.size() > kMaximumPendingFileChooseRequests) {
+ // This sanity check prevents too many file choose requests from getting
+ // queued which could DoS the user. Getting these is most likely a
+ // programming error (there are many ways to DoS the user so it's not
+ // considered a "real" security check), either in JS requesting many file
+ // choosers to pop up, or in a plugin.
+ //
+ // TODO(brettw): We might possibly want to require a user gesture to open
+ // a file picker, which will address this issue in a better way.
+ return false;
+ }
+
+ file_chooser_completions_.push_back(
+ base::WrapUnique(new PendingFileChooser(params, completion)));
+ if (file_chooser_completions_.size() == 1) {
+ // Actually show the browse dialog when this is the first request.
+ Send(new FrameHostMsg_RunFileChooser(routing_id_, params));
+ }
+ return true;
+}
+
void RenderFrameImpl::LoadNavigationErrorPage(
const WebURLRequest& failed_request,
const WebURLError& error,
@@ -2258,6 +2340,10 @@ RenderView* RenderFrameImpl::GetRenderView() {
return render_view_.get();
}
+RenderAccessibility* RenderFrameImpl::GetRenderAccessibility() {
+ return render_accessibility_;
+}
+
int RenderFrameImpl::GetRoutingID() {
return routing_id_;
}
@@ -2334,8 +2420,12 @@ void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) {
OnJavaScriptExecuteRequest(javascript, 0, false);
}
-ServiceRegistry* RenderFrameImpl::GetServiceRegistry() {
- return &service_registry_;
+shell::InterfaceRegistry* RenderFrameImpl::GetInterfaceRegistry() {
+ return interface_registry_.get();
+}
+
+shell::InterfaceProvider* RenderFrameImpl::GetRemoteInterfaces() {
+ return remote_interfaces_.get();
}
#if defined(ENABLE_PLUGINS)
@@ -2398,13 +2488,14 @@ void RenderFrameImpl::EnsureMojoBuiltinsAreAvailable(
registry->AddBuiltinModule(isolate, mojo::edk::js::Support::kModuleName,
mojo::edk::js::Support::GetModule(isolate));
registry->AddBuiltinModule(
- isolate, ServiceRegistryJsWrapper::kPerFrameModuleName,
- ServiceRegistryJsWrapper::Create(isolate, context, &service_registry_)
+ isolate, InterfaceProviderJsWrapper::kPerFrameModuleName,
+ InterfaceProviderJsWrapper::Create(
+ isolate, context, remote_interfaces_.get())
.ToV8());
registry->AddBuiltinModule(
- isolate, ServiceRegistryJsWrapper::kPerProcessModuleName,
- ServiceRegistryJsWrapper::Create(
- isolate, context, RenderThread::Get()->GetServiceRegistry())
+ isolate, InterfaceProviderJsWrapper::kPerProcessModuleName,
+ InterfaceProviderJsWrapper::Create(
+ isolate, context, RenderThread::Get()->GetRemoteInterfaces())
.ToV8());
}
@@ -2439,6 +2530,13 @@ bool RenderFrameImpl::IsPasting() const {
return is_pasting_;
}
+// mojom::Frame implementation -------------------------------------------------
+
+void RenderFrameImpl::GetInterfaceProvider(
+ shell::mojom::InterfaceProviderRequest request) {
+ interface_registry_->Bind(std::move(request));
+}
+
// blink::WebFrameClient implementation ----------------------------------------
blink::WebPlugin* RenderFrameImpl::createPlugin(
@@ -2520,7 +2618,9 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
&GetSharedMainThreadContext3D,
RenderThreadImpl::current()->SharedMainThreadContextProvider());
- scoped_refptr<media::MediaLog> media_log(new RenderMediaLog());
+ scoped_refptr<media::MediaLog> media_log(new RenderMediaLog(
+ blink::WebStringToGURL(frame_->getSecurityOrigin().toString())));
+
#if defined(OS_ANDROID)
if (UseWebMediaPlayerImpl(url) && !media_surface_manager_)
media_surface_manager_ = new RendererSurfaceViewManager(this);
@@ -2558,8 +2658,7 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
media_renderer_factory.reset(new media::DefaultRendererFactory(
media_log, GetDecoderFactory(),
base::Bind(&RenderThreadImpl::GetGpuFactories,
- base::Unretained(render_thread)),
- *render_thread->GetAudioHardwareConfig()));
+ base::Unretained(render_thread))));
}
#endif // defined(ENABLE_MOJO_RENDERER)
@@ -2607,7 +2706,7 @@ RenderFrameImpl::createWorkerContentSettingsClientProxy() {
WebExternalPopupMenu* RenderFrameImpl::createExternalPopupMenu(
const WebPopupMenuInfo& popup_menu_info,
WebExternalPopupMenuClient* popup_menu_client) {
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
// An IPC message is sent to the browser to build and display the actual
// popup. The user could have time to click a different select by the time
// the popup is shown. In that case external_popup_menu_ is non NULL.
@@ -2635,7 +2734,7 @@ blink::WebCookieJar* RenderFrameImpl::cookieJar() {
blink::BlameContext* RenderFrameImpl::frameBlameContext() {
DCHECK(blame_context_);
- return blame_context_;
+ return blame_context_.get();
}
blink::WebServiceWorkerProvider*
@@ -2658,6 +2757,9 @@ RenderFrameImpl::createServiceWorkerProvider() {
}
void RenderFrameImpl::didAccessInitialDocument() {
+ // NOTE: Do not call back into JavaScript here, since this call is made from a
+ // V8 security check.
+
// If the request hasn't yet committed, notify the browser process that it is
// no longer safe to show the pending URL of the main frame, since a URL spoof
// is now possible. (If the request has committed, the browser already knows.)
@@ -2738,7 +2840,6 @@ void RenderFrameImpl::frameDetached(blink::WebFrame* frame, DetachType type) {
// NOTE: This function is called on the frame that is being detached and not
// the parent frame. This is different from createChildFrame() which is
// called on the parent frame.
- CHECK(!is_detaching_);
DCHECK_EQ(frame_, frame);
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, FrameDetached());
@@ -2750,10 +2851,6 @@ void RenderFrameImpl::frameDetached(blink::WebFrame* frame, DetachType type) {
if (!in_browser_initiated_detach_ && type == DetachType::Remove)
Send(new FrameHostMsg_Detach(routing_id_));
- // The |is_detaching_| flag disables Send(). FrameHostMsg_Detach must be
- // sent before setting |is_detaching_| to true.
- is_detaching_ = true;
-
// Clean up the associated RenderWidget for the frame, if there is one.
if (render_widget_) {
render_widget_->UnregisterRenderFrame(this);
@@ -2818,8 +2915,9 @@ void RenderFrameImpl::didChangeName(const blink::WebString& name,
}
}
-void RenderFrameImpl::didEnforceStrictMixedContentChecking() {
- Send(new FrameHostMsg_EnforceStrictMixedContentChecking(routing_id_));
+void RenderFrameImpl::didEnforceInsecureRequestPolicy(
+ blink::WebInsecureRequestPolicy policy) {
+ Send(new FrameHostMsg_EnforceInsecureRequestPolicy(routing_id_, policy));
}
void RenderFrameImpl::didUpdateToUniqueOrigin(
@@ -2915,13 +3013,13 @@ void RenderFrameImpl::loadURLExternally(const blink::WebURLRequest& request,
bool should_replace_current_entry) {
Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame_, request));
if (policy == blink::WebNavigationPolicyDownload) {
- render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(),
- GetRoutingID(),
- request.url(), referrer,
- suggested_name));
+ Send(new FrameHostMsg_DownloadUrl(render_view_->GetRoutingID(),
+ GetRoutingID(), request.url(), referrer,
+ suggested_name));
} else {
- OpenURL(request.url(), referrer, policy, should_replace_current_entry,
- false);
+ OpenURL(request.url(), IsHttpPost(request),
+ GetRequestBodyForWebURLRequest(request), referrer, policy,
+ should_replace_current_entry, false);
}
}
@@ -3072,9 +3170,8 @@ void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame,
ServiceWorkerNetworkProvider::AttachToDocumentState(
DocumentState::FromDataSource(datasource),
- ServiceWorkerNetworkProvider::CreateForNavigation(
- routing_id_, navigation_state->request_params(), frame,
- content_initiated));
+ ServiceWorkerNetworkProvider::CreateForNavigation(routing_id_, frame,
+ content_initiated));
}
void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame,
@@ -3740,6 +3837,37 @@ bool RenderFrameImpl::runModalBeforeUnloadDialog(bool is_reload) {
return success;
}
+bool RenderFrameImpl::runFileChooser(
+ const blink::WebFileChooserParams& params,
+ blink::WebFileChooserCompletion* chooser_completion) {
+ // Do not open the file dialog in a hidden RenderFrame.
+ if (IsHidden())
+ return false;
+
+ FileChooserParams ipc_params;
+ if (params.directory)
+ ipc_params.mode = FileChooserParams::UploadFolder;
+ else if (params.multiSelect)
+ ipc_params.mode = FileChooserParams::OpenMultiple;
+ else if (params.saveAs)
+ ipc_params.mode = FileChooserParams::Save;
+ else
+ ipc_params.mode = FileChooserParams::Open;
+ ipc_params.title = params.title;
+ ipc_params.default_file_name =
+ blink::WebStringToFilePath(params.initialValue).BaseName();
+ ipc_params.accept_types.reserve(params.acceptTypes.size());
+ for (const auto& type : params.acceptTypes)
+ ipc_params.accept_types.push_back(type);
+ ipc_params.need_local_path = params.needLocalPath;
+#if defined(OS_ANDROID)
+ ipc_params.capture = params.useMediaCapture;
+#endif
+ ipc_params.requestor = params.requestor;
+
+ return ScheduleFileChooser(ipc_params, chooser_completion);
+}
+
void RenderFrameImpl::showContextMenu(const blink::WebContextMenuData& data) {
ContextMenuParams params = ContextMenuParamsBuilder::Build(data);
blink::WebRect position_in_window(params.x, params.y, 0, 0);
@@ -3773,6 +3901,15 @@ void RenderFrameImpl::showContextMenu(const blink::WebContextMenuData& data) {
Send(new FrameHostMsg_ContextMenu(routing_id_, params));
}
+void RenderFrameImpl::saveImageFromDataURL(const blink::WebString& data_url) {
+ // Note: We should basically send GURL but we use size-limited string instead
+ // in order to send a larger data url to save a image for <canvas> or <img>.
+ if (data_url.length() < kMaxLengthOfDataURLString) {
+ Send(new FrameHostMsg_SaveImageFromDataURL(
+ render_view_->GetRoutingID(), routing_id_, data_url.utf8()));
+ }
+}
+
void RenderFrameImpl::willSendRequest(
blink::WebLocalFrame* frame,
unsigned identifier,
@@ -3787,20 +3924,20 @@ void RenderFrameImpl::willSendRequest(
// requests). This value will be updated during redirects, consistent with
// https://tools.ietf.org/html/draft-west-first-party-cookies-04#section-2.1.1
if (request.firstPartyForCookies().isEmpty()) {
- if (request.getFrameType() == blink::WebURLRequest::FrameTypeTopLevel) {
+ if (request.getFrameType() == blink::WebURLRequest::FrameTypeTopLevel)
request.setFirstPartyForCookies(request.url());
- } else {
- // TODO(nasko): When the top-level frame is remote, there is no document.
- // This is broken and should be fixed to propagate the first party.
- WebFrame* top = frame->top();
- if (top->isWebLocalFrame()) {
- request.setFirstPartyForCookies(
- frame->top()->document().firstPartyForCookies());
- }
- }
+ else
+ request.setFirstPartyForCookies(frame->document().firstPartyForCookies());
+ }
- // If we need to set the first party, then we need to set the request's
- // initiator as well; it will not be updated during redirects.
+ // Set the requestor origin to the same origin as the frame's document if it
+ // hasn't yet been set.
+ //
+ // TODO(mkwst): It would be cleaner to adjust blink::ResourceRequest to
+ // initialize itself with a `nullptr` initiator so that this can be a simple
+ // `isNull()` check.
+ if (request.requestorOrigin().isUnique() &&
+ !frame->document().getSecurityOrigin().isUnique()) {
request.setRequestorOrigin(frame->document().getSecurityOrigin());
}
@@ -3894,15 +4031,18 @@ void RenderFrameImpl::willSendRequest(
provider_id = provider->provider_id();
// Explicitly set the SkipServiceWorker flag here if the renderer process
// hasn't received SetControllerServiceWorker message.
- if (!provider->IsControlledByServiceWorker())
- request.setSkipServiceWorker(true);
+ if (!provider->IsControlledByServiceWorker() &&
+ request.skipServiceWorker() !=
+ blink::WebURLRequest::SkipServiceWorker::All)
+ request.setSkipServiceWorker(
+ blink::WebURLRequest::SkipServiceWorker::Controlling);
}
WebFrame* parent = frame->parent();
int parent_routing_id = parent ? GetRoutingIdForFrameOrProxy(parent) : -1;
RequestExtraData* extra_data = new RequestExtraData();
- extra_data->set_visibility_state(render_view_->visibilityState());
+ extra_data->set_visibility_state(visibilityState());
extra_data->set_custom_user_agent(custom_user_agent);
extra_data->set_requested_with(requested_with);
extra_data->set_render_frame_id(routing_id_);
@@ -3921,14 +4061,21 @@ void RenderFrameImpl::willSendRequest(
navigation_state->start_params().transferred_request_request_id);
extra_data->set_service_worker_provider_id(provider_id);
extra_data->set_stream_override(std::move(stream_override));
- if (request.getLoFiState() != WebURLRequest::LoFiUnspecified)
- extra_data->set_lofi_state(static_cast<LoFiState>(request.getLoFiState()));
- else if (is_main_frame_ && !navigation_state->request_committed())
- extra_data->set_lofi_state(navigation_state->common_params().lofi_state);
- else
- extra_data->set_lofi_state(is_using_lofi_ ? LOFI_ON : LOFI_OFF);
+ WebString error;
+ extra_data->set_initiated_in_secure_context(
+ frame->document().isSecureContext(error));
request.setExtraData(extra_data);
+ if (request.getLoFiState() == WebURLRequest::LoFiUnspecified) {
+ if (is_main_frame_ && !navigation_state->request_committed()) {
+ request.setLoFiState(static_cast<WebURLRequest::LoFiState>(
+ navigation_state->common_params().lofi_state));
+ } else {
+ request.setLoFiState(
+ is_using_lofi_ ? WebURLRequest::LoFiOn : WebURLRequest::LoFiOff);
+ }
+ }
+
// TODO(creis): Update prefetching to work with out-of-process iframes.
WebFrame* top_frame = frame->top();
if (top_frame && top_frame->isWebLocalFrame()) {
@@ -4113,20 +4260,19 @@ void RenderFrameImpl::willInsertBody(blink::WebLocalFrame* frame) {
void RenderFrameImpl::reportFindInPageMatchCount(int request_id,
int count,
bool final_update) {
- int active_match_ordinal = -1; // -1 = don't update active match ordinal
- if (!count)
- active_match_ordinal = 0;
+ // -1 here means don't update the active match ordinal.
+ int active_match_ordinal = count ? -1 : 0;
- Send(new FrameHostMsg_Find_Reply(routing_id_, request_id, count, gfx::Rect(),
- active_match_ordinal, final_update));
+ SendFindReply(request_id, count, active_match_ordinal, gfx::Rect(),
+ final_update);
}
void RenderFrameImpl::reportFindInPageSelection(
int request_id,
int active_match_ordinal,
const blink::WebRect& selection_rect) {
- Send(new FrameHostMsg_Find_Reply(routing_id_, request_id, -1, selection_rect,
- active_match_ordinal, false));
+ SendFindReply(request_id, -1 /* match_count */, active_match_ordinal,
+ selection_rect, false /* final_status_update */);
}
void RenderFrameImpl::requestStorageQuota(
@@ -4278,8 +4424,8 @@ void RenderFrameImpl::handleAccessibilityFindInPageResult(
int start_offset,
const blink::WebAXObject& end_object,
int end_offset) {
- if (renderer_accessibility_) {
- renderer_accessibility_->HandleAccessibilityFindInPageResult(
+ if (render_accessibility_) {
+ render_accessibility_->HandleAccessibilityFindInPageResult(
identifier, match_index, start_object, start_offset,
end_object, end_offset);
}
@@ -4300,9 +4446,10 @@ bool RenderFrameImpl::exitFullscreen() {
}
blink::WebPermissionClient* RenderFrameImpl::permissionClient() {
- if (!permission_client_)
- permission_client_.reset(new PermissionDispatcher(GetServiceRegistry()));
-
+ if (!permission_client_) {
+ permission_client_.reset(
+ new PermissionDispatcher(GetRemoteInterfaces()));
+ }
return permission_client_.get();
}
@@ -4338,13 +4485,8 @@ void RenderFrameImpl::unregisterProtocolHandler(const WebString& scheme,
}
blink::WebBluetooth* RenderFrameImpl::bluetooth() {
- // ChildThreadImpl::current() is null in some tests.
- if (!bluetooth_ && ChildThreadImpl::current()) {
- bluetooth_.reset(new WebBluetoothImpl(
- GetServiceRegistry(), ChildThreadImpl::current()->thread_safe_sender(),
- routing_id_));
- }
-
+ if (!bluetooth_.get())
+ bluetooth_.reset(new WebBluetoothImpl(GetRemoteInterfaces()));
return bluetooth_.get();
}
@@ -4381,27 +4523,25 @@ void RenderFrameImpl::WasHidden() {
for (auto* plugin : active_pepper_instances_)
plugin->PageVisibilityChanged(false);
#endif // ENABLE_PLUGINS
+
+ if (GetWebFrame()->frameWidget()) {
+ static_cast<blink::WebFrameWidget*>(GetWebFrame()->frameWidget())
+ ->setVisibilityState(visibilityState());
+ }
}
void RenderFrameImpl::WasShown() {
- // TODO(kenrb): Need to figure out how to do this better. Should
- // VisibilityState remain a page-level concept or move to frames?
- // The semantics of 'Show' might have to change here.
- // TODO(avi): This DCHECK is to track cleanup for https://crbug.com/545684
- DCHECK(!IsMainFrame() || render_widget_.get() == render_view_.get())
- << "The main render frame is no longer reusing the RenderView as its "
- << "RenderWidget!";
- if (render_widget_ && render_widget_->webwidget() &&
- render_view_.get() != render_widget_.get()) {
- static_cast<blink::WebFrameWidget*>(render_widget_->webwidget())->
- setVisibilityState(blink::WebPageVisibilityStateVisible, false);
- }
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, WasShown());
#if defined(ENABLE_PLUGINS)
for (auto* plugin : active_pepper_instances_)
plugin->PageVisibilityChanged(true);
#endif // ENABLE_PLUGINS
+
+ if (GetWebFrame()->frameWidget()) {
+ static_cast<blink::WebFrameWidget*>(GetWebFrame()->frameWidget())
+ ->setVisibilityState(visibilityState());
+ }
}
void RenderFrameImpl::WidgetWillClose() {
@@ -4472,8 +4612,7 @@ void RenderFrameImpl::SendDidCommitProvisionalLoad(
// RenderFrameProxies in other processes.
params.origin = frame->document().getSecurityOrigin();
- params.should_enforce_strict_mixed_content_checking =
- frame->shouldEnforceStrictMixedContentChecking();
+ params.insecure_request_policy = frame->getInsecureRequestPolicy();
params.has_potentially_trustworthy_unique_origin =
frame->document().getSecurityOrigin().isUnique() &&
@@ -4665,8 +4804,8 @@ void RenderFrameImpl::didChangeLoadProgress(double load_progress) {
void RenderFrameImpl::HandleWebAccessibilityEvent(
const blink::WebAXObject& obj, blink::WebAXEvent event) {
- if (renderer_accessibility_)
- renderer_accessibility_->HandleWebAccessibilityEvent(obj, event);
+ if (render_accessibility_)
+ render_accessibility_->HandleWebAccessibilityEvent(obj, event);
}
void RenderFrameImpl::FocusedNodeChanged(const WebNode& node) {
@@ -4674,8 +4813,8 @@ void RenderFrameImpl::FocusedNodeChanged(const WebNode& node) {
}
void RenderFrameImpl::FocusedNodeChangedForAccessibility(const WebNode& node) {
- if (renderer_accessibility())
- renderer_accessibility()->AccessibilityFocusedNodeChanged(node);
+ if (render_accessibility())
+ render_accessibility()->AccessibilityFocusedNodeChanged(node);
}
// PlzNavigate
@@ -4793,8 +4932,9 @@ WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
if (is_content_initiated && IsTopLevelNavigation(frame_) &&
render_view_->renderer_preferences_
.browser_handles_all_top_level_requests) {
- OpenURL(url, referrer, info.defaultPolicy, info.replacesCurrentHistoryItem,
- false);
+ OpenURL(url, IsHttpPost(info.urlRequest),
+ GetRequestBodyForWebURLRequest(info.urlRequest), referrer,
+ info.defaultPolicy, info.replacesCurrentHistoryItem, false);
return blink::WebNavigationPolicyIgnore; // Suppress the load here.
}
@@ -4803,8 +4943,9 @@ WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
// FrameNavigationEntry. If none is found, fall back to the default url.
if (SiteIsolationPolicy::UseSubframeNavigationEntries() &&
info.isHistoryNavigationInNewChildFrame && is_content_initiated) {
- OpenURL(url, referrer, info.defaultPolicy, info.replacesCurrentHistoryItem,
- true);
+ OpenURL(url, IsHttpPost(info.urlRequest),
+ GetRequestBodyForWebURLRequest(info.urlRequest), referrer,
+ info.defaultPolicy, info.replacesCurrentHistoryItem, true);
// Suppress the load in Blink but mark the frame as loading.
return blink::WebNavigationPolicyHandledByClient;
}
@@ -4819,15 +4960,6 @@ WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
// an extension or app origin, leaving a WebUI page, etc). We only care about
// top-level navigations (not iframes). But we sometimes navigate to
// about:blank to clear a tab, and we want to still allow that.
- //
- // Note: this is known to break POST submissions when crossing process
- // boundaries until http://crbug.com/101395 is fixed. This is better for
- // security than loading a WebUI, extension or app page in the wrong process.
- // POST requests don't work because this mechanism does not preserve form
- // POST data. We will need to send the request's httpBody data up to the
- // browser process, and issue a special POST navigation in WebKit (via
- // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
- // for examples of how to send the httpBody data.
if (!frame_->parent() && is_content_initiated &&
!url.SchemeIs(url::kAboutScheme)) {
bool send_referrer = false;
@@ -4867,7 +4999,9 @@ WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
}
if (should_fork) {
- OpenURL(url, send_referrer ? referrer : Referrer(), info.defaultPolicy,
+ OpenURL(url, IsHttpPost(info.urlRequest),
+ GetRequestBodyForWebURLRequest(info.urlRequest),
+ send_referrer ? referrer : Referrer(), info.defaultPolicy,
info.replacesCurrentHistoryItem, false);
return blink::WebNavigationPolicyIgnore; // Suppress the load here.
}
@@ -4907,11 +5041,31 @@ WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
if (is_fork) {
// Open the URL via the browser, not via WebKit.
- OpenURL(url, Referrer(), info.defaultPolicy,
- info.replacesCurrentHistoryItem, false);
+ OpenURL(url, IsHttpPost(info.urlRequest),
+ GetRequestBodyForWebURLRequest(info.urlRequest), Referrer(),
+ info.defaultPolicy, info.replacesCurrentHistoryItem, false);
return blink::WebNavigationPolicyIgnore;
}
+ // Execute the BeforeUnload event. If asked not to proceed or the frame is
+ // destroyed, ignore the navigation. There is no need to execute the
+ // BeforeUnload event during a redirect, since it was already executed at the
+ // start of the navigation.
+ // PlzNavigate: this is not executed when commiting the navigation.
+ if (info.defaultPolicy == blink::WebNavigationPolicyCurrentTab &&
+ !is_redirect && (!IsBrowserSideNavigationEnabled() ||
+ info.urlRequest.checkForBrowserSideNavigation())) {
+ // Keep a WeakPtr to this RenderFrameHost to detect if executing the
+ // BeforeUnload event destriyed this frame.
+ base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr();
+
+ if (!frame_->dispatchBeforeUnloadEvent(info.navigationType ==
+ blink::WebNavigationTypeReload) ||
+ !weak_self) {
+ return blink::WebNavigationPolicyIgnore;
+ }
+ }
+
// PlzNavigate: if the navigation is not synchronous, send it to the browser.
// This includes navigations with no request being sent to the network stack.
if (IsBrowserSideNavigationEnabled() &&
@@ -4965,30 +5119,36 @@ void RenderFrameImpl::OnSerializeAsMHTML(
DCHECK(!mhtml_boundary.isEmpty());
WebData data;
- bool success = true;
std::set<std::string> digests_of_uris_of_serialized_resources;
MHTMLPartsGenerationDelegate delegate(
params, &digests_of_uris_of_serialized_resources);
+ bool success = true;
+
// Generate MHTML header if needed.
if (IsMainFrame()) {
- blink::WebFrameSerializerCacheControlPolicy policy =
- static_cast<blink::WebFrameSerializerCacheControlPolicy>(
- params.mhtml_cache_control_policy);
- success = WebFrameSerializer::generateMHTMLHeader(mhtml_boundary, policy,
- GetWebFrame(), &data);
- if (success && file.WriteAtCurrentPos(data.data(), data.size()) < 0) {
+ // |data| can be empty if the main frame should be skipped. If the main
+ // frame is
+ // skipped, then the whole archive is bad, so bail to the error condition.
+ WebData data = WebFrameSerializer::generateMHTMLHeader(
+ mhtml_boundary, GetWebFrame(), &delegate);
+ if (data.isEmpty() ||
+ file.WriteAtCurrentPos(data.data(), data.size()) < 0) {
success = false;
}
}
- // Generate MHTML parts.
+ // Generate MHTML parts. Note that if this is not the main frame, then even
+ // skipping the whole parts generation step is not an error - it simply
+ // results in an omitted resource in the final file.
if (success) {
- data = WebFrameSerializer::generateMHTMLParts(
- mhtml_boundary, GetWebFrame(), params.mhtml_binary_encoding, &delegate);
+ // |data| can be empty if the frame should be skipped, but this is OK.
+ data = WebFrameSerializer::generateMHTMLParts(mhtml_boundary, GetWebFrame(),
+ &delegate);
// TODO(jcivelli): write the chunks in deferred tasks to give a chance to
// the message loop to process other events.
- if (file.WriteAtCurrentPos(data.data(), data.size()) < 0) {
+ if (!data.isEmpty() &&
+ file.WriteAtCurrentPos(data.data(), data.size()) < 0) {
success = false;
}
}
@@ -5011,13 +5171,6 @@ void RenderFrameImpl::OnSerializeAsMHTML(
void RenderFrameImpl::OnFind(int request_id,
const base::string16& search_text,
const WebFindOptions& options) {
- // This should only be received on the main frame, since find-in-page is
- // currently orchestrated by the main frame.
- if (!is_main_frame_) {
- NOTREACHED();
- return;
- }
-
DCHECK(!search_text.empty());
blink::WebPlugin* plugin = GetWebPluginForFind();
@@ -5025,156 +5178,82 @@ void RenderFrameImpl::OnFind(int request_id,
if (plugin) {
if (options.findNext) {
// Just navigate back/forward.
- plugin->selectFindResult(options.forward);
+ plugin->selectFindResult(options.forward, request_id);
} else {
if (!plugin->startFind(search_text, options.matchCase, request_id)) {
// Send "no results".
- SendFindReply(request_id, 0, 0, gfx::Rect(), true);
+ SendFindReply(request_id, 0 /* match_count */, 0 /* ordinal */,
+ gfx::Rect(), true /* final_status_update */ );
}
}
return;
}
- WebLocalFrame* main_frame = GetWebFrame();
- WebLocalFrame* focused_frame =
- render_view_->webview()->focusedFrame()->toWebLocalFrame();
- // Start searching in the focused frame.
- WebLocalFrame* search_frame = focused_frame;
-
- // Check for multiple searchable frames.
- bool multi_frame = (main_frame->traverseNextLocal(true) != main_frame);
-
- // If we have multiple frames, we don't want to wrap the search within the
- // frame, so we check here if we only have |main_frame| in the chain.
- bool wrap_within_frame = !multi_frame;
+ // Send "no results" if this frame has no visible content.
+ if (!frame_->hasVisibleContent()) {
+ SendFindReply(request_id, 0 /* match_count */, 0 /* ordinal */,
+ gfx::Rect(), true /* final_status_update */ );
+ return;
+ }
WebRect selection_rect;
- bool result = false;
bool active_now = false;
// If something is selected when we start searching it means we cannot just
// increment the current match ordinal; we need to re-generate it.
- WebRange current_selection = focused_frame->selectionRange();
-
- do {
- result =
- search_frame->find(request_id, search_text, options, wrap_within_frame,
- &selection_rect, &active_now);
-
- if (!result) {
- // Don't leave text selected as you move to the next frame.
- search_frame->executeCommand(WebString::fromUTF8("Unselect"));
-
- // Find the next frame, but skip the invisible ones.
- do {
- // What is the next frame to search (we might be going backwards)? Note
- // that we specify wrap=true so that search_frame never becomes NULL.
- search_frame = options.forward
- ? search_frame->traverseNextLocal(true)
- : search_frame->traversePreviousLocal(true);
- } while (!search_frame->hasVisibleContent() &&
- search_frame != focused_frame);
-
- // Make sure selection doesn't affect the search operation in new frame.
- search_frame->executeCommand(WebString::fromUTF8("Unselect"));
-
- // If we have multiple frames and we have wrapped back around to the
- // focused frame, we need to search it once more allowing wrap within
- // the frame, otherwise it will report 'no match' if the focused frame has
- // reported matches, but no frames after the focused_frame contain a
- // match for the search word(s).
- if (multi_frame && search_frame == focused_frame) {
- result = search_frame->find(request_id, search_text, options,
- true, // Force wrapping.
- &selection_rect, &active_now);
- }
- }
+ WebRange current_selection = frame_->selectionRange();
- render_view_->webview()->setFocusedFrame(search_frame);
- } while (!result && search_frame != focused_frame);
+ if (frame_->find(request_id, search_text, options,
+ false /* wrapWithinFrame */, &selection_rect, &active_now)) {
+ // Indicate that at least one match has been found. 1 here means possibly
+ // more matches could be coming. -1 here means that the exact active match
+ // ordinal is not yet known.
+ SendFindReply(request_id, 1 /* match_count */, -1 /* ordinal */,
+ gfx::Rect(), false /* final_status_update */ );
+ }
if (options.findNext && current_selection.isNull() && active_now) {
- // Force the main_frame to report the actual count.
- main_frame->increaseMatchCount(0, request_id);
- } else {
- // If nothing is found, set result to "0 of 0", otherwise, set it to
- // "-1 of 1" to indicate that we found at least one item, but we don't know
- // yet what is active.
- int ordinal = result ? -1 : 0; // -1 here means we might know more later.
- int match_count = result ? 1 : 0; // 1 here means possibly more coming.
-
- // If we find no matches then this will be our last status update.
- // Otherwise the scoping effort will send more results.
- bool final_status_update = !result;
-
- SendFindReply(request_id, match_count, ordinal, selection_rect,
- final_status_update);
-
- // Scoping effort begins, starting with the main frame.
- search_frame = main_frame;
-
- main_frame->resetMatchCount();
-
- do {
- // Cancel all old scoping requests before starting a new one.
- search_frame->cancelPendingScopingEffort();
-
- // We don't start another scoping effort unless at least one match has
- // been found.
- if (result) {
- // Start new scoping request. If the scoping function determines that it
- // needs to scope, it will defer until later.
- search_frame->scopeStringMatches(request_id, search_text, options,
- true); // reset the tickmarks
- }
-
- // Iterate to the next frame. The frame will not necessarily scope, for
- // example if it is not visible.
- search_frame = search_frame->traverseNextLocal(true);
- } while (search_frame != main_frame);
+ // Force report of the actual count.
+ frame_->increaseMatchCount(0, request_id);
+ return;
}
+
+ // Scoping effort begins.
+ frame_->resetMatchCount();
+
+ // Cancel all old scoping requests before starting a new one.
+ frame_->cancelPendingScopingEffort();
+
+ // Start new scoping request. If the scoping function determines that it
+ // needs to scope, it will defer until later.
+ frame_->scopeStringMatches(request_id,
+ search_text,
+ options,
+ true); // reset the tickmarks
}
-void RenderFrameImpl::OnStopFinding(StopFindAction action) {
- // This should only be received on the main frame, since find-in-page is
- // currently orchestrated by the main frame.
- if (!is_main_frame_) {
- NOTREACHED();
- return;
- }
+void RenderFrameImpl::OnClearActiveFindMatch() {
+ frame_->executeCommand(WebString::fromUTF8("Unselect"));
+ frame_->clearActiveFindMatch();
+}
- WebView* view = render_view_->webview();
- if (!view)
- return;
+// Ensure that content::StopFindAction and blink::WebLocalFrame::StopFindAction
+// are kept in sync.
+STATIC_ASSERT_ENUM(STOP_FIND_ACTION_CLEAR_SELECTION,
+ WebLocalFrame::StopFindActionClearSelection);
+STATIC_ASSERT_ENUM(STOP_FIND_ACTION_KEEP_SELECTION,
+ WebLocalFrame::StopFindActionKeepSelection);
+STATIC_ASSERT_ENUM(STOP_FIND_ACTION_ACTIVATE_SELECTION,
+ WebLocalFrame::StopFindActionActivateSelection);
+void RenderFrameImpl::OnStopFinding(StopFindAction action) {
blink::WebPlugin* plugin = GetWebPluginForFind();
if (plugin) {
plugin->stopFind();
return;
}
- bool clear_selection = action == STOP_FIND_ACTION_CLEAR_SELECTION;
- if (clear_selection) {
- view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"));
- }
-
- WebLocalFrame* frame = GetWebFrame();
- while (frame) {
- frame->stopFinding(clear_selection);
- frame = frame->traverseNextLocal(false);
- }
-
- if (action == STOP_FIND_ACTION_ACTIVATE_SELECTION) {
- WebFrame* focused_frame = view->focusedFrame();
- if (focused_frame) {
- WebDocument doc = focused_frame->document();
- if (!doc.isNull()) {
- WebElement element = doc.focusedElement();
- if (!element.isNull())
- element.simulateClick();
- }
- }
- }
+ frame_->stopFinding(static_cast<WebLocalFrame::StopFindAction>(action));
}
void RenderFrameImpl::OnEnableViewSourceMode() {
@@ -5187,6 +5266,43 @@ void RenderFrameImpl::OnSuppressFurtherDialogs() {
suppress_further_dialogs_ = true;
}
+void RenderFrameImpl::OnFileChooserResponse(
+ const std::vector<content::FileChooserFileInfo>& files) {
+ // This could happen if we navigated to a different page before the user
+ // closed the chooser.
+ if (file_chooser_completions_.empty())
+ return;
+
+ // Convert Chrome's SelectedFileInfo list to WebKit's.
+ WebVector<blink::WebFileChooserCompletion::SelectedFileInfo> selected_files(
+ files.size());
+ for (size_t i = 0; i < files.size(); ++i) {
+ blink::WebFileChooserCompletion::SelectedFileInfo selected_file;
+ selected_file.path = files[i].file_path.AsUTF16Unsafe();
+ selected_file.displayName =
+ base::FilePath(files[i].display_name).AsUTF16Unsafe();
+ if (files[i].file_system_url.is_valid()) {
+ selected_file.fileSystemURL = files[i].file_system_url;
+ selected_file.length = files[i].length;
+ selected_file.modificationTime = files[i].modification_time.ToDoubleT();
+ selected_file.isDirectory = files[i].is_directory;
+ }
+ selected_files[i] = selected_file;
+ }
+
+ if (file_chooser_completions_.front()->completion) {
+ file_chooser_completions_.front()->completion->didChooseFile(
+ selected_files);
+ }
+ file_chooser_completions_.pop_front();
+
+ // If there are more pending file chooser requests, schedule one now.
+ if (!file_chooser_completions_.empty()) {
+ Send(new FrameHostMsg_RunFileChooser(
+ routing_id_, file_chooser_completions_.front()->params));
+ }
+}
+
#if defined(OS_ANDROID)
void RenderFrameImpl::OnActivateNearestFindResult(int request_id,
float x,
@@ -5206,6 +5322,14 @@ void RenderFrameImpl::OnActivateNearestFindResult(int request_id,
true /* final_update */);
}
+void RenderFrameImpl::OnGetNearestFindResult(int nfr_request_id,
+ float x,
+ float y) {
+ float distance = frame_->distanceToNearestFindMatch(WebFloatPoint(x, y));
+ Send(new FrameHostMsg_GetNearestFindResult_Reply(
+ routing_id_, nfr_request_id, distance));
+}
+
void RenderFrameImpl::OnFindMatchRects(int current_version) {
std::vector<gfx::RectF> match_rects;
@@ -5222,7 +5346,17 @@ void RenderFrameImpl::OnFindMatchRects(int current_version) {
Send(new FrameHostMsg_FindMatchRects_Reply(routing_id_, rects_version,
match_rects, active_rect));
}
+#endif
+#if defined(USE_EXTERNAL_POPUP_MENU)
+#if defined(OS_MACOSX)
+void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) {
+ if (external_popup_menu_ == NULL)
+ return;
+ external_popup_menu_->DidSelectItem(selected_index);
+ external_popup_menu_.reset();
+}
+#else
void RenderFrameImpl::OnSelectPopupMenuItems(
bool canceled,
const std::vector<int>& selected_indices) {
@@ -5236,22 +5370,21 @@ void RenderFrameImpl::OnSelectPopupMenuItems(
external_popup_menu_->DidSelectItems(canceled, selected_indices);
external_popup_menu_.reset();
}
-#elif defined(OS_MACOSX)
-void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) {
- if (external_popup_menu_ == NULL)
- return;
- external_popup_menu_->DidSelectItem(selected_index);
- external_popup_menu_.reset();
-}
+#endif
#endif
-void RenderFrameImpl::OpenURL(const GURL& url,
- const Referrer& referrer,
- WebNavigationPolicy policy,
- bool should_replace_current_entry,
- bool is_history_navigation_in_new_child) {
+void RenderFrameImpl::OpenURL(
+ const GURL& url,
+ bool uses_post,
+ const scoped_refptr<ResourceRequestBodyImpl>& resource_request_body,
+ const Referrer& referrer,
+ WebNavigationPolicy policy,
+ bool should_replace_current_entry,
+ bool is_history_navigation_in_new_child) {
FrameHostMsg_OpenURL_Params params;
params.url = url;
+ params.uses_post = uses_post;
+ params.resource_request_body = resource_request_body;
params.referrer = referrer;
params.disposition = RenderViewImpl::NavigationPolicyToDisposition(policy);
@@ -5349,6 +5482,12 @@ void RenderFrameImpl::NavigateInternal(
WebURLRequest request =
CreateURLRequestForNavigation(common_params, std::move(stream_params),
frame_->isViewSourceModeEnabled());
+ request.setFrameType(IsTopLevelNavigation(frame_)
+ ? blink::WebURLRequest::FrameTypeTopLevel
+ : blink::WebURLRequest::FrameTypeNested);
+
+ if (IsBrowserSideNavigationEnabled() && common_params.post_data)
+ request.setHTTPBody(GetWebHTTPBodyForRequestBody(common_params.post_data));
// Used to determine whether this frame is actually loading a request as part
// of a history navigation.
@@ -5439,18 +5578,10 @@ void RenderFrameImpl::NavigateInternal(
}
}
- if (common_params.method == "POST" && !browser_side_navigation) {
- // Set post data.
- WebHTTPBody http_body;
- http_body.initialize();
- const char* data = nullptr;
- if (start_params.browser_initiated_post_data.size()) {
- data = reinterpret_cast<const char*>(
- &start_params.browser_initiated_post_data.front());
- }
- http_body.appendData(
- WebData(data, start_params.browser_initiated_post_data.size()));
- request.setHTTPBody(http_body);
+ if (common_params.method == "POST" && !browser_side_navigation &&
+ common_params.post_data) {
+ request.setHTTPBody(
+ GetWebHTTPBodyForRequestBody(common_params.post_data));
}
// A session history navigation should have been accompanied by state.
@@ -5474,12 +5605,11 @@ void RenderFrameImpl::NavigateInternal(
// Perform a navigation to a data url if needed.
// Note: the base URL might be invalid, so also check the data URL string.
- if (!common_params.base_url_for_data_url.is_empty() ||
+ bool should_load_data_url = !common_params.base_url_for_data_url.is_empty();
#if defined(OS_ANDROID)
- !request_params.data_url_as_string.empty() ||
+ should_load_data_url |= !request_params.data_url_as_string.empty();
#endif
- (browser_side_navigation &&
- common_params.url.SchemeIs(url::kDataScheme))) {
+ if (should_load_data_url) {
LoadDataURL(common_params, request_params, frame_, load_type,
item_for_history_navigation, history_load_type,
is_client_redirect);
@@ -5605,11 +5735,12 @@ WebMediaPlayer* RenderFrameImpl::CreateWebMediaPlayerForMediaStream(
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner =
render_thread->compositor_task_runner();
if (!compositor_task_runner.get())
- compositor_task_runner = base::MessageLoop::current()->task_runner();
+ compositor_task_runner = base::ThreadTaskRunnerHandle::Get();
return new WebMediaPlayerMS(
frame_, client, GetWebMediaPlayerDelegate()->AsWeakPtr(),
- new RenderMediaLog(), CreateRendererFactory(), compositor_task_runner,
+ new RenderMediaLog(blink::WebStringToGURL(security_origin.toString())),
+ CreateRendererFactory(), compositor_task_runner,
render_thread->GetMediaThreadTaskRunner(),
render_thread->GetWorkerTaskRunner(), render_thread->GetGpuFactories(),
sink_id, security_origin);
@@ -5660,7 +5791,6 @@ void RenderFrameImpl::BeginNavigation(blink::WebURLRequest* request,
bool is_client_redirect) {
CHECK(IsBrowserSideNavigationEnabled());
DCHECK(request);
- // TODO(clamy): Execute the beforeunload event.
// Note: At this stage, the goal is to apply all the modifications the
// renderer wants to make to the request, and then send it to the browser, so
@@ -5708,9 +5838,9 @@ void RenderFrameImpl::BeginNavigation(blink::WebURLRequest* request,
BeginNavigationParams(GetWebURLRequestHeaders(*request),
GetLoadFlagsForWebURLRequest(*request),
request->hasUserGesture(),
- request->skipServiceWorker(),
- GetRequestContextTypeForWebURLRequest(*request)),
- GetRequestBodyForWebURLRequest(*request)));
+ request->skipServiceWorker() !=
+ blink::WebURLRequest::SkipServiceWorker::None,
+ GetRequestContextTypeForWebURLRequest(*request))));
}
void RenderFrameImpl::LoadDataURL(
@@ -6028,23 +6158,23 @@ media::DecoderFactory* RenderFrameImpl::GetDecoderFactory() {
return decoder_factory_.get();
}
-void RenderFrameImpl::RegisterMojoServices() {
+void RenderFrameImpl::RegisterMojoInterfaces() {
// Only main frame have ImageDownloader service.
if (!frame_->parent()) {
- GetServiceRegistry()->AddService(base::Bind(
+ GetInterfaceRegistry()->AddInterface(base::Bind(
&ImageDownloaderImpl::CreateMojoService, base::Unretained(this)));
}
}
template <typename Interface>
void RenderFrameImpl::GetInterface(mojo::InterfaceRequest<Interface> request) {
- GetServiceRegistry()->ConnectToRemoteService(std::move(request));
+ GetRemoteInterfaces()->GetInterface(std::move(request));
}
shell::mojom::InterfaceProviderPtr RenderFrameImpl::ConnectToApplication(
const GURL& url) {
if (!connector_)
- GetServiceRegistry()->ConnectToRemoteService(mojo::GetProxy(&connector_));
+ GetRemoteInterfaces()->GetInterface(&connector_);
shell::mojom::InterfaceProviderPtr interface_provider;
shell::mojom::IdentityPtr target(shell::mojom::Identity::New());
target->name = url.spec();
@@ -6074,13 +6204,28 @@ void RenderFrameImpl::checkIfAudioSinkExistsAndIsAuthorized(
}
blink::ServiceRegistry* RenderFrameImpl::serviceRegistry() {
- return &blink_service_registry_;
+ return blink_service_registry_.get();
}
-blink::WebPlugin* RenderFrameImpl::GetWebPluginForFind() {
- if (!is_main_frame_)
- return nullptr;
+blink::WebPageVisibilityState RenderFrameImpl::visibilityState() const {
+ RenderFrameImpl* local_root =
+ RenderFrameImpl::FromWebFrame(frame_->localRoot());
+ blink::WebPageVisibilityState current_state =
+ local_root->render_widget_->is_hidden()
+ ? blink::WebPageVisibilityStateHidden
+ : blink::WebPageVisibilityStateVisible;
+ blink::WebPageVisibilityState override_state = current_state;
+ if (GetContentClient()->renderer()->ShouldOverridePageVisibilityState(
+ this, &override_state))
+ return override_state;
+ return current_state;
+}
+blink::WebPageVisibilityState RenderFrameImpl::GetVisibilityState() const {
+ return visibilityState();
+}
+
+blink::WebPlugin* RenderFrameImpl::GetWebPluginForFind() {
if (frame_->document().isPluginDocument())
return frame_->document().to<WebPluginDocument>().plugin();
@@ -6097,8 +6242,15 @@ void RenderFrameImpl::SendFindReply(int request_id,
int ordinal,
const WebRect& selection_rect,
bool final_status_update) {
- Send(new FrameHostMsg_Find_Reply(routing_id_, request_id, match_count,
- selection_rect, ordinal,
+ if (final_status_update && !ordinal)
+ frame_->executeCommand(WebString::fromUTF8("Unselect"));
+ DCHECK(ordinal >= -1);
+
+ Send(new FrameHostMsg_Find_Reply(routing_id_,
+ request_id,
+ match_count,
+ selection_rect,
+ ordinal,
final_status_update));
}
@@ -6137,6 +6289,22 @@ void RenderFrameImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance,
GetRenderWidget()->UpdateSelectionBounds();
}
+void RenderFrameImpl::PepperStartsPlayback(PepperPluginInstanceImpl* instance) {
+ // TODO(zqzhang): send PepperStartsPlayback message to the browser.
+ // See https://crbug.com/619084
+}
+
+void RenderFrameImpl::PepperStopsPlayback(PepperPluginInstanceImpl* instance) {
+ // TODO(zqzhang): send PepperStopsPlayback message to the browser.
+ // See https://crbug.com/619084
+}
+
+void RenderFrameImpl::OnSetPepperVolume(int32_t pp_instance, double volume) {
+ PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>(
+ PepperPluginInstance::Get(pp_instance));
+ if (instance)
+ instance->audio_controller().SetVolume(volume);
+}
#endif // ENABLE_PLUGINS
void RenderFrameImpl::RenderWidgetSetFocus(bool enable) {
diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h
index c424e0a6002..f3d5f6f9efa 100644
--- a/chromium/content/renderer/render_frame_impl.h
+++ b/chromium/content/renderer/render_frame_impl.h
@@ -17,13 +17,14 @@
#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/process/process_handle.h"
#include "build/build_config.h"
#include "content/common/accessibility_mode_enums.h"
+#include "content/common/frame.mojom.h"
#include "content/common/frame_message_enums.h"
-#include "content/common/mojo/service_registry_impl.h"
#include "content/public/common/console_message_level.h"
#include "content/public/common/javascript_message_type.h"
#include "content/public/common/referrer.h"
@@ -36,12 +37,14 @@
#include "ipc/ipc_platform_file.h"
#include "media/blink/webmediaplayer_delegate.h"
#include "media/blink/webmediaplayer_params.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "services/shell/public/interfaces/connector.mojom.h"
#include "services/shell/public/interfaces/interface_provider.mojom.h"
#include "third_party/WebKit/public/platform/WebEffectiveConnectionType.h"
#include "third_party/WebKit/public/platform/WebFocusType.h"
#include "third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
+#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
#include "third_party/WebKit/public/platform/modules/app_banner/WebAppBannerClient.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
@@ -108,8 +111,9 @@ class UrlIndex;
class WebEncryptedMediaClientImpl;
}
-namespace mojo {
-class ServiceProvider;
+namespace shell {
+class InterfaceRegistry;
+class InterfaceProvider;
}
namespace url {
@@ -136,7 +140,7 @@ class PepperPluginInstanceImpl;
class PermissionDispatcher;
class PresentationDispatcher;
class PushMessagingDispatcher;
-class RendererAccessibility;
+class RenderAccessibilityImpl;
class RendererCdmManager;
class RendererMediaPlayerManager;
class RendererMediaSessionManager;
@@ -146,11 +150,14 @@ class RenderFrameObserver;
class RenderViewImpl;
class RenderWidget;
class RenderWidgetFullscreenPepper;
+class ResourceRequestBodyImpl;
class ScreenOrientationDispatcher;
class UserMediaClientImpl;
class WakeLockDispatcher;
struct CommonNavigationParams;
struct CustomContextMenuContext;
+struct FileChooserFileInfo;
+struct FileChooserParams;
struct FrameReplicationState;
struct NavigationParams;
struct RequestNavigationParams;
@@ -160,6 +167,7 @@ struct StreamOverrideParameters;
class CONTENT_EXPORT RenderFrameImpl
: public RenderFrame,
+ NON_EXPORTED_BASE(mojom::Frame),
NON_EXPORTED_BASE(public blink::WebFrameClient),
NON_EXPORTED_BASE(public blink::WebFrameSerializerClient) {
public:
@@ -279,8 +287,8 @@ class CONTENT_EXPORT RenderFrameImpl
return accessibility_mode_;
}
- RendererAccessibility* renderer_accessibility() {
- return renderer_accessibility_;
+ RenderAccessibilityImpl* render_accessibility() {
+ return render_accessibility_;
}
void HandleWebAccessibilityEvent(const blink::WebAXObject& obj,
@@ -291,7 +299,7 @@ class CONTENT_EXPORT RenderFrameImpl
void FocusedNodeChanged(const blink::WebNode& node);
// TODO(dmazzoni): the only reason this is here is to plumb it through to
- // RendererAccessibility. It should use the RenderFrameObserver method, once
+ // RenderAccessibilityImpl. It should use the RenderFrameObserver method, once
// blink has a separate accessibility tree per frame.
void FocusedNodeChangedForAccessibility(const blink::WebNode& node);
@@ -367,7 +375,7 @@ class CONTENT_EXPORT RenderFrameImpl
// NULL.
MediaStreamDispatcher* GetMediaStreamDispatcher();
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
void DidHideExternalPopupMenu();
#endif
@@ -379,6 +387,7 @@ class CONTENT_EXPORT RenderFrameImpl
// RenderFrame implementation:
RenderView* GetRenderView() override;
+ RenderAccessibility* GetRenderAccessibility() override;
int GetRoutingID() override;
blink::WebLocalFrame* GetWebFrame() override;
WebPreferences& GetWebkitPreferences() override;
@@ -395,7 +404,8 @@ class CONTENT_EXPORT RenderFrameImpl
void ExecuteJavaScript(const base::string16& javascript) override;
bool IsMainFrame() override;
bool IsHidden() override;
- ServiceRegistry* GetServiceRegistry() override;
+ shell::InterfaceRegistry* GetInterfaceRegistry() override;
+ shell::InterfaceProvider* GetRemoteInterfaces() override;
#if defined(ENABLE_PLUGINS)
void RegisterPeripheralPlugin(
const url::Origin& content_origin,
@@ -418,6 +428,11 @@ class CONTENT_EXPORT RenderFrameImpl
const std::string& message) override;
bool IsUsingLoFi() const override;
bool IsPasting() const override;
+ blink::WebPageVisibilityState GetVisibilityState() const override;
+
+ // mojom::Frame implementation:
+ void GetInterfaceProvider(
+ shell::mojom::InterfaceProviderRequest request) override;
// blink::WebFrameClient implementation:
blink::WebPlugin* createPlugin(blink::WebLocalFrame* frame,
@@ -454,7 +469,8 @@ class CONTENT_EXPORT RenderFrameImpl
void willClose(blink::WebFrame* frame) override;
void didChangeName(const blink::WebString& name,
const blink::WebString& unique_name) override;
- void didEnforceStrictMixedContentChecking() override;
+ void didEnforceInsecureRequestPolicy(
+ blink::WebInsecureRequestPolicy policy) override;
void didUpdateToUniqueOrigin(
bool is_potentially_trustworthy_unique_origin) override;
void didChangeSandboxFlags(blink::WebFrame* child_frame,
@@ -539,7 +555,11 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebString& default_value,
blink::WebString* actual_value) override;
bool runModalBeforeUnloadDialog(bool is_reload) override;
+ bool runFileChooser(
+ const blink::WebFileChooserParams& params,
+ blink::WebFileChooserCompletion* chooser_completion) override;
void showContextMenu(const blink::WebContextMenuData& data) override;
+ void saveImageFromDataURL(const blink::WebString& data_url) override;
void willSendRequest(blink::WebLocalFrame* frame,
unsigned identifier,
blink::WebURLRequest& request,
@@ -618,6 +638,7 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebSecurityOrigin& security_origin,
blink::WebSetSinkIdCallbacks* web_callbacks) override;
blink::ServiceRegistry* serviceRegistry() override;
+ blink::WebPageVisibilityState visibilityState() const override;
// WebFrameSerializerClient implementation:
void didSerializeDataForFrame(
@@ -625,9 +646,8 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebFrameSerializerClient::FrameSerializationStatus status)
override;
- // Binds this render frame's service registry.
- void BindServiceRegistry(shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services);
+ // Binds to the FrameHost in the browser.
+ void Bind(mojom::FrameRequest frame, mojom::FrameHostPtr frame_host);
ManifestManager* manifest_manager();
@@ -670,6 +690,10 @@ class CONTENT_EXPORT RenderFrameImpl
// Notification that the given plugin is focused or unfocused.
void PepperFocusChanged(PepperPluginInstanceImpl* instance, bool focused);
+
+ void PepperStartsPlayback(PepperPluginInstanceImpl* instance);
+ void PepperStopsPlayback(PepperPluginInstanceImpl* instance);
+ void OnSetPepperVolume(int32_t pp_instance, double volume);
#endif // ENABLE_PLUGINS
protected:
@@ -678,13 +702,13 @@ class CONTENT_EXPORT RenderFrameImpl
private:
friend class RenderFrameImplTest;
friend class RenderFrameObserver;
- friend class RendererAccessibilityTest;
+ friend class RenderAccessibilityImplTest;
friend class TestRenderFrame;
FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuDisplayNoneTest, SelectItem);
FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuRemoveTest, RemoveOnChange);
FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, NormalCase);
FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, ShowPopupThenNavigate);
- FRIEND_TEST_ALL_PREFIXES(RendererAccessibilityTest,
+ FRIEND_TEST_ALL_PREFIXES(RenderAccessibilityImplTest,
AccessibilityMessagesQueueWhileSwappedOut);
// A wrapper class used as the callback for JavaScript executed
@@ -741,7 +765,7 @@ class CONTENT_EXPORT RenderFrameImpl
void OnNavigate(const CommonNavigationParams& common_params,
const StartNavigationParams& start_params,
const RequestNavigationParams& request_params);
- void OnBeforeUnload();
+ void OnBeforeUnload(bool is_reload);
void OnSwapOut(int proxy_routing_id,
bool is_loading,
const FrameReplicationState& replicated_frame_state);
@@ -765,6 +789,8 @@ class CONTENT_EXPORT RenderFrameImpl
void OnMoveRangeSelectionExtent(const gfx::Point& point);
void OnReplace(const base::string16& text);
void OnReplaceMisspelling(const base::string16& text);
+ void OnCopyImageAt(int x, int y);
+ void OnSaveImageAt(int x, int y);
void OnCSSInsertRequest(const std::string& css);
void OnAddMessageToConsole(ConsoleMessageLevel level,
const std::string& message);
@@ -816,16 +842,28 @@ class CONTENT_EXPORT RenderFrameImpl
void OnFind(int request_id,
const base::string16& search_text,
const blink::WebFindOptions& options);
+ void OnClearActiveFindMatch();
void OnStopFinding(StopFindAction action);
void OnEnableViewSourceMode();
void OnSuppressFurtherDialogs();
+ void OnFileChooserResponse(
+ const std::vector<content::FileChooserFileInfo>& files);
#if defined(OS_ANDROID)
void OnActivateNearestFindResult(int request_id, float x, float y);
+ void OnGetNearestFindResult(int request_id, float x, float y);
void OnFindMatchRects(int current_version);
+#endif
+
+#if defined(USE_EXTERNAL_POPUP_MENU)
+#if defined(OS_MACOSX)
+ void OnSelectPopupMenuItem(int selected_index);
+#else
void OnSelectPopupMenuItems(bool canceled,
const std::vector<int>& selected_indices);
-#elif defined(OS_MACOSX)
- void OnSelectPopupMenuItem(int selected_index);
+#endif
+#endif
+
+#if defined(OS_MACOSX)
void OnCopyToFindPboard();
#endif
@@ -833,11 +871,14 @@ class CONTENT_EXPORT RenderFrameImpl
// |is_history_navigation_in_new_child| is true, the browser process should
// look for a matching FrameNavigationEntry in the last committed entry to use
// instead of |url|.
- void OpenURL(const GURL& url,
- const Referrer& referrer,
- blink::WebNavigationPolicy policy,
- bool should_replace_current_entry,
- bool is_history_navigation_in_new_child);
+ void OpenURL(
+ const GURL& url,
+ bool uses_post,
+ const scoped_refptr<ResourceRequestBodyImpl>& resource_request_body,
+ const Referrer& referrer,
+ blink::WebNavigationPolicy policy,
+ bool should_replace_current_entry,
+ bool is_history_navigation_in_new_child);
// Performs a navigation in the frame. This provides a unified function for
// the current code path and the browser-side navigation path (in
@@ -881,6 +922,15 @@ class CONTENT_EXPORT RenderFrameImpl
const GURL& frame_url,
base::string16* result);
+ // Adds the given file chooser request to the file_chooser_completion_ queue
+ // (see that var for more) and requests the chooser be displayed if there are
+ // no other waiting items in the queue.
+ //
+ // Returns true if the chooser was successfully scheduled. False means we
+ // didn't schedule anything.
+ bool ScheduleFileChooser(const FileChooserParams& params,
+ blink::WebFileChooserCompletion* completion);
+
// Loads the appropriate error page for the specified failure into the frame.
void LoadNavigationErrorPage(const blink::WebURLRequest& failed_request,
const blink::WebURLError& error,
@@ -978,7 +1028,7 @@ class CONTENT_EXPORT RenderFrameImpl
media::CdmFactory* GetCdmFactory();
media::DecoderFactory* GetDecoderFactory();
- void RegisterMojoServices();
+ void RegisterMojoInterfaces();
// Connect to an interface provided by the service registry.
template <typename Interface>
@@ -1038,8 +1088,6 @@ class CONTENT_EXPORT RenderFrameImpl
base::WeakPtr<RenderViewImpl> render_view_;
int routing_id_;
- bool is_detaching_;
-
// If this frame was created to replace a proxy, this will store the routing
// id of the proxy to replace at commit-time, at which time it will be
// cleared.
@@ -1172,8 +1220,11 @@ class CONTENT_EXPORT RenderFrameImpl
// initialized.
PresentationDispatcher* presentation_dispatcher_;
- ServiceRegistryImpl service_registry_;
- BlinkServiceRegistryImpl blink_service_registry_;
+ std::unique_ptr<shell::InterfaceRegistry> interface_registry_;
+ std::unique_ptr<shell::InterfaceProvider> remote_interfaces_;
+ std::unique_ptr<BlinkServiceRegistryImpl> blink_service_registry_;
+ shell::mojom::InterfaceProviderRequest
+ pending_remote_interface_provider_request_;
// The shell proxy used to connect to Mojo applications.
shell::mojom::ConnectorPtr connector_;
@@ -1191,7 +1242,7 @@ class CONTENT_EXPORT RenderFrameImpl
// Only valid if |accessibility_mode_| is anything other than
// AccessibilityModeOff.
- RendererAccessibility* renderer_accessibility_;
+ RenderAccessibilityImpl* render_accessibility_;
std::unique_ptr<PermissionDispatcher> permission_client_;
@@ -1217,12 +1268,19 @@ class CONTENT_EXPORT RenderFrameImpl
// stack that interferes with swapping out.
bool suppress_further_dialogs_;
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ // The current and pending file chooser completion objects. If the queue is
+ // nonempty, the first item represents the currently running file chooser
+ // callback, and the remaining elements are the other file chooser completion
+ // still waiting to be run (in order).
+ struct PendingFileChooser;
+ std::deque<std::unique_ptr<PendingFileChooser>> file_chooser_completions_;
+
+#if defined(USE_EXTERNAL_POPUP_MENU)
// The external popup for the currently showing select popup.
std::unique_ptr<ExternalPopupMenu> external_popup_menu_;
#endif
- FrameBlameContext* blame_context_; // Not owned.
+ std::unique_ptr<FrameBlameContext> blame_context_;
// Plugins -------------------------------------------------------------------
#if defined(ENABLE_PLUGINS)
@@ -1239,6 +1297,9 @@ class CONTENT_EXPORT RenderFrameImpl
PepperPluginInstanceImpl* pepper_last_mouse_event_target_;
#endif
+ mojo::Binding<mojom::Frame> frame_binding_;
+ mojom::FrameHostPtr frame_host_;
+
base::WeakPtrFactory<RenderFrameImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl);
diff --git a/chromium/content/renderer/render_frame_impl_browsertest.cc b/chromium/content/renderer/render_frame_impl_browsertest.cc
index 2a853c16903..61fd6b341e9 100644
--- a/chromium/content/renderer/render_frame_impl_browsertest.cc
+++ b/chromium/content/renderer/render_frame_impl_browsertest.cc
@@ -19,11 +19,14 @@
#include "content/test/fake_compositor_dependencies.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebEffectiveConnectionType.h"
+#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
#include "third_party/WebKit/public/web/WebHistoryItem.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
+using blink::WebString;
+
namespace {
const int32_t kSubframeRouteId = 20;
const int32_t kSubframeWidgetRouteId = 21;
@@ -108,8 +111,10 @@ class RenderFrameTestObserver : public RenderFrameObserver {
~RenderFrameTestObserver() override {}
+ // RenderFrameObserver implementation.
void WasShown() override { visible_ = true; }
void WasHidden() override { visible_ = false; }
+ void OnDestruct() override { delete this; }
bool visible() { return visible_; }
@@ -292,4 +297,50 @@ TEST_F(RenderFrameImplTest, EffectiveConnectionType) {
}
}
+TEST_F(RenderFrameImplTest, SaveImageFromDataURL) {
+ const IPC::Message* msg1 = render_thread_->sink().GetFirstMessageMatching(
+ FrameHostMsg_SaveImageFromDataURL::ID);
+ EXPECT_FALSE(msg1);
+ render_thread_->sink().ClearMessages();
+
+ const std::string image_data_url =
+ "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=";
+
+ frame()->saveImageFromDataURL(WebString::fromUTF8(image_data_url));
+ ProcessPendingMessages();
+ const IPC::Message* msg2 = render_thread_->sink().GetFirstMessageMatching(
+ FrameHostMsg_SaveImageFromDataURL::ID);
+ EXPECT_TRUE(msg2);
+
+ FrameHostMsg_SaveImageFromDataURL::Param param1;
+ FrameHostMsg_SaveImageFromDataURL::Read(msg2, &param1);
+ EXPECT_EQ(std::get<2>(param1), image_data_url);
+
+ ProcessPendingMessages();
+ render_thread_->sink().ClearMessages();
+
+ const std::string large_data_url(1024 * 1024 * 20 - 1, 'd');
+
+ frame()->saveImageFromDataURL(WebString::fromUTF8(large_data_url));
+ ProcessPendingMessages();
+ const IPC::Message* msg3 = render_thread_->sink().GetFirstMessageMatching(
+ FrameHostMsg_SaveImageFromDataURL::ID);
+ EXPECT_TRUE(msg3);
+
+ FrameHostMsg_SaveImageFromDataURL::Param param2;
+ FrameHostMsg_SaveImageFromDataURL::Read(msg3, &param2);
+ EXPECT_EQ(std::get<2>(param2), large_data_url);
+
+ ProcessPendingMessages();
+ render_thread_->sink().ClearMessages();
+
+ const std::string exceeded_data_url(1024 * 1024 * 20 + 1, 'd');
+
+ frame()->saveImageFromDataURL(WebString::fromUTF8(exceeded_data_url));
+ ProcessPendingMessages();
+ const IPC::Message* msg4 = render_thread_->sink().GetFirstMessageMatching(
+ FrameHostMsg_SaveImageFromDataURL::ID);
+ EXPECT_FALSE(msg4);
+}
+
} // namespace
diff --git a/chromium/content/renderer/render_frame_proxy.cc b/chromium/content/renderer/render_frame_proxy.cc
index 868412155c7..74bcd08f83f 100644
--- a/chromium/content/renderer/render_frame_proxy.cc
+++ b/chromium/content/renderer/render_frame_proxy.cc
@@ -10,6 +10,7 @@
#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "content/child/web_url_request_util.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/content_security_policy_header.h"
#include "content/common/frame_messages.h"
@@ -212,8 +213,7 @@ void RenderFrameProxy::SetReplicatedState(const FrameReplicationState& state) {
web_frame_->setReplicatedSandboxFlags(state.sandbox_flags);
web_frame_->setReplicatedName(blink::WebString::fromUTF8(state.name),
blink::WebString::fromUTF8(state.unique_name));
- web_frame_->setReplicatedShouldEnforceStrictMixedContentChecking(
- state.should_enforce_strict_mixed_content_checking);
+ web_frame_->setReplicatedInsecureRequestPolicy(state.insecure_request_policy);
web_frame_->setReplicatedPotentiallyTrustworthyUniqueOrigin(
state.has_potentially_trustworthy_unique_origin);
@@ -267,11 +267,14 @@ bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) {
OnAddContentSecurityPolicy)
IPC_MESSAGE_HANDLER(FrameMsg_ResetContentSecurityPolicy,
OnResetContentSecurityPolicy)
- IPC_MESSAGE_HANDLER(FrameMsg_EnforceStrictMixedContentChecking,
- OnEnforceStrictMixedContentChecking)
+ IPC_MESSAGE_HANDLER(FrameMsg_EnforceInsecureRequestPolicy,
+ OnEnforceInsecureRequestPolicy)
+ IPC_MESSAGE_HANDLER(FrameMsg_SetFrameOwnerProperties,
+ OnSetFrameOwnerProperties)
IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateOrigin, OnDidUpdateOrigin)
IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetPageFocus)
IPC_MESSAGE_HANDLER(FrameMsg_SetFocusedFrame, OnSetFocusedFrame)
+ IPC_MESSAGE_HANDLER(FrameMsg_WillEnterFullscreen, OnWillEnterFullscreen)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -348,10 +351,14 @@ void RenderFrameProxy::OnResetContentSecurityPolicy() {
web_frame_->resetReplicatedContentSecurityPolicy();
}
-void RenderFrameProxy::OnEnforceStrictMixedContentChecking(
- bool should_enforce) {
- web_frame_->setReplicatedShouldEnforceStrictMixedContentChecking(
- should_enforce);
+void RenderFrameProxy::OnEnforceInsecureRequestPolicy(
+ blink::WebInsecureRequestPolicy policy) {
+ web_frame_->setReplicatedInsecureRequestPolicy(policy);
+}
+
+void RenderFrameProxy::OnSetFrameOwnerProperties(
+ const blink::WebFrameOwnerProperties& properties) {
+ web_frame_->setFrameOwnerProperties(properties);
}
void RenderFrameProxy::OnDidUpdateOrigin(
@@ -372,6 +379,10 @@ void RenderFrameProxy::OnSetFocusedFrame() {
render_view_->webview()->focusDocumentView(web_frame_);
}
+void RenderFrameProxy::OnWillEnterFullscreen() {
+ web_frame_->willEnterFullScreen();
+}
+
void RenderFrameProxy::frameDetached(DetachType type) {
if (type == DetachType::Remove && web_frame_->parent()) {
web_frame_->parent()->removeChild(web_frame_);
@@ -436,6 +447,8 @@ void RenderFrameProxy::navigate(const blink::WebURLRequest& request,
bool should_replace_current_entry) {
FrameHostMsg_OpenURL_Params params;
params.url = request.url();
+ params.uses_post = request.httpMethod().utf8() == "POST";
+ params.resource_request_body = GetRequestBodyForWebURLRequest(request);
params.referrer = Referrer(
blink::WebStringToGURL(
request.httpHeaderField(blink::WebString::fromUTF8("Referer"))),
diff --git a/chromium/content/renderer/render_frame_proxy.h b/chromium/content/renderer/render_frame_proxy.h
index 638037b69d4..950e25dacd5 100644
--- a/chromium/content/renderer/render_frame_proxy.h
+++ b/chromium/content/renderer/render_frame_proxy.h
@@ -11,6 +11,7 @@
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "third_party/WebKit/public/platform/WebFocusType.h"
+#include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
#include "third_party/WebKit/public/web/WebRemoteFrame.h"
#include "third_party/WebKit/public/web/WebRemoteFrameClient.h"
#include "url/origin.h"
@@ -24,7 +25,7 @@ struct WebRect;
}
namespace cc {
-struct SurfaceId;
+class SurfaceId;
struct SurfaceSequence;
}
@@ -168,11 +169,14 @@ class CONTENT_EXPORT RenderFrameProxy
void OnDidUpdateName(const std::string& name, const std::string& unique_name);
void OnAddContentSecurityPolicy(const ContentSecurityPolicyHeader& header);
void OnResetContentSecurityPolicy();
- void OnEnforceStrictMixedContentChecking(bool should_enforce);
+ void OnEnforceInsecureRequestPolicy(blink::WebInsecureRequestPolicy policy);
+ void OnSetFrameOwnerProperties(
+ const blink::WebFrameOwnerProperties& properties);
void OnDidUpdateOrigin(const url::Origin& origin,
bool is_potentially_trustworthy_unique_origin);
void OnSetPageFocus(bool is_focused);
void OnSetFocusedFrame();
+ void OnWillEnterFullscreen();
// The routing ID by which this RenderFrameProxy is known.
const int routing_id_;
diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc
index b729a8ca44e..a43b39dd21d 100644
--- a/chromium/content/renderer/render_thread_impl.cc
+++ b/chromium/content/renderer/render_thread_impl.cc
@@ -41,6 +41,8 @@
#include "cc/base/switches.h"
#include "cc/blink/web_external_bitmap_impl.h"
#include "cc/blink/web_layer_impl.h"
+#include "cc/output/output_surface.h"
+#include "cc/output/vulkan_in_process_context_provider.h"
#include "cc/raster/task_graph_runner.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_settings.h"
@@ -65,15 +67,14 @@
#include "content/child/runtime_features.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/web_database_observer_impl.h"
+#include "content/child/websocket_message_filter.h"
#include "content/child/worker_thread_registry.h"
#include "content/common/child_process_messages.h"
#include "content/common/content_constants_internal.h"
-#include "content/common/database_messages.h"
#include "content/common/dom_storage/dom_storage_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu_process_launch_causes.h"
-#include "content/common/render_frame_setup.mojom.h"
#include "content/common/render_process_messages.h"
#include "content/common/resource_messages.h"
#include "content/common/service_worker/embedded_worker_setup.mojom.h"
@@ -87,10 +88,10 @@
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_thread_observer.h"
#include "content/public/renderer/render_view_visitor.h"
-#include "content/renderer/bluetooth/bluetooth_message_filter.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/cache_storage/cache_storage_dispatcher.h"
#include "content/renderer/cache_storage/cache_storage_message_filter.h"
+#include "content/renderer/categorized_worker_pool.h"
#include "content/renderer/devtools/devtools_agent_filter.h"
#include "content/renderer/devtools/v8_sampling_profiler.h"
#include "content/renderer/dom_storage/dom_storage_dispatcher.h"
@@ -99,6 +100,7 @@
#include "content/renderer/gpu/compositor_external_begin_frame_source.h"
#include "content/renderer/gpu/compositor_forwarding_message_filter.h"
#include "content/renderer/gpu/compositor_output_surface.h"
+#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "content/renderer/input/input_event_filter.h"
#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/input/main_thread_input_event_filter.h"
@@ -114,7 +116,6 @@
#include "content/renderer/media/video_capture_message_filter.h"
#include "content/renderer/net_info_helper.h"
#include "content/renderer/p2p/socket_dispatcher.h"
-#include "content/renderer/raster_worker_pool.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process_impl.h"
#include "content/renderer/render_view_impl.h"
@@ -130,8 +131,8 @@
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_channel_mojo.h"
#include "ipc/ipc_platform_file.h"
-#include "ipc/mojo/ipc_channel_mojo.h"
#include "media/base/audio_hardware_config.h"
#include "media/base/media.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
@@ -151,7 +152,7 @@
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebKit.h"
-#include "third_party/WebKit/public/web/WebMemoryPressureListener.h"
+#include "third_party/WebKit/public/web/WebMemoryCoordinator.h"
#include "third_party/WebKit/public/web/WebNetworkStateNotifier.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebScriptController.h"
@@ -164,8 +165,8 @@
#if defined(OS_ANDROID)
#include <cpu-features.h>
-#include "content/renderer/android/synchronous_compositor_external_begin_frame_source.h"
#include "content/renderer/android/synchronous_compositor_filter.h"
+#include "content/renderer/android/synchronous_compositor_output_surface.h"
#include "content/renderer/media/android/renderer_demuxer_android.h"
#include "content/renderer/media/android/stream_texture_factory.h"
#include "media/base/android/media_codec_util.h"
@@ -197,11 +198,17 @@
#include "v8/src/third_party/vtune/v8-vtune.h"
#endif
-#if defined(MOJO_SHELL_CLIENT)
+#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
+#include "components/mus/common/gpu_service.h"
#include "content/public/common/mojo_shell_connection.h"
+#include "content/renderer/mus/render_widget_mus_connection.h"
#include "content/renderer/mus/render_widget_window_tree_client_factory.h"
#endif
+#if defined(ENABLE_IPC_FUZZER)
+#include "content/common/external_ipc_dumper.h"
+#endif
+
using base::ThreadRestrictions;
using blink::WebDocument;
using blink::WebFrame;
@@ -236,6 +243,9 @@ const double kThrottledResourceRequestFlushPeriodS = 1. / 60.;
// allocation that exceeds this limit.
const size_t kImageCacheSingleAllocationByteLimit = 64 * 1024 * 1024;
+// Unique identifier for each output surface created.
+uint32_t g_next_output_surface_id = 1;
+
// Keep the global RenderThreadImpl in a TLS slot so it is impossible to access
// incorrectly from the wrong thread.
base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> >
@@ -252,6 +262,20 @@ static_assert(static_cast<v8::MemoryPressureLevel>(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) ==
v8::MemoryPressureLevel::kCritical, "critical level not align");
+// WebMemoryPressureLevel should correspond to base::MemoryPressureListener.
+static_assert(static_cast<blink::WebMemoryPressureLevel>(
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) ==
+ blink::WebMemoryPressureLevelNone,
+ "blink::WebMemoryPressureLevelNone not align");
+static_assert(static_cast<blink::WebMemoryPressureLevel>(
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE) ==
+ blink::WebMemoryPressureLevelModerate,
+ "blink::WebMemoryPressureLevelModerate not align");
+static_assert(static_cast<blink::WebMemoryPressureLevel>(
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) ==
+ blink::WebMemoryPressureLevelCritical,
+ "blink::WebMemoryPressureLevelCritical not align");
+
class WebThreadForCompositor : public WebThreadImplForWorkerScheduler {
public:
explicit WebThreadForCompositor(base::Thread::Options options)
@@ -313,16 +337,16 @@ void NotifyTimezoneChangeOnThisThread() {
v8::Date::DateTimeConfigurationChangeNotification(isolate);
}
-class RenderFrameSetupImpl : public mojom::RenderFrameSetup {
+class FrameFactoryImpl : public mojom::FrameFactory {
public:
- explicit RenderFrameSetupImpl(
- mojo::InterfaceRequest<mojom::RenderFrameSetup> request)
+ explicit FrameFactoryImpl(mojom::FrameFactoryRequest request)
: routing_id_highmark_(-1), binding_(this, std::move(request)) {}
- void ExchangeInterfaceProviders(
- int32_t frame_routing_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services) override {
+ private:
+ // mojom::FrameFactory:
+ void CreateFrame(int32_t frame_routing_id,
+ mojom::FrameRequest frame_request,
+ mojom::FrameHostPtr frame_host) override {
// TODO(morrita): This is for investigating http://crbug.com/415059 and
// should be removed once it is fixed.
CHECK_LT(routing_id_highmark_, frame_routing_id);
@@ -333,28 +357,26 @@ class RenderFrameSetupImpl : public mojom::RenderFrameSetup {
// created due to a race between the message and a ViewMsg_New IPC that
// triggers creation of the RenderFrame we want.
if (!frame) {
- RenderThreadImpl::current()->RegisterPendingRenderFrameConnect(
- frame_routing_id, std::move(services), std::move(exposed_services));
+ RenderThreadImpl::current()->RegisterPendingFrameCreate(
+ frame_routing_id, std::move(frame_request), std::move(frame_host));
return;
}
- frame->BindServiceRegistry(std::move(services),
- std::move(exposed_services));
+ frame->Bind(std::move(frame_request), std::move(frame_host));
}
private:
int32_t routing_id_highmark_;
- mojo::StrongBinding<mojom::RenderFrameSetup> binding_;
+ mojo::StrongBinding<mojom::FrameFactory> binding_;
};
-void CreateRenderFrameSetup(
- mojo::InterfaceRequest<mojom::RenderFrameSetup> request) {
- new RenderFrameSetupImpl(std::move(request));
+void CreateFrameFactory(mojom::FrameFactoryRequest request) {
+ new FrameFactoryImpl(std::move(request));
}
void SetupEmbeddedWorkerOnWorkerThread(
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtrInfo exposed_services) {
+ shell::mojom::InterfaceProviderRequest request,
+ shell::mojom::InterfaceProviderPtrInfo remote_interfaces) {
ServiceWorkerContextClient* client =
ServiceWorkerContextClient::ThreadSpecificInstance();
// It is possible for client to be null if for some reason the worker died
@@ -362,8 +384,8 @@ void SetupEmbeddedWorkerOnWorkerThread(
// nothing and let mojo close the connection.
if (!client)
return;
- client->BindServiceRegistry(std::move(services),
- mojo::MakeProxy(std::move(exposed_services)));
+ client->BindInterfaceProviders(std::move(request),
+ mojo::MakeProxy(std::move(remote_interfaces)));
}
class EmbeddedWorkerSetupImpl : public mojom::EmbeddedWorkerSetup {
@@ -374,12 +396,12 @@ class EmbeddedWorkerSetupImpl : public mojom::EmbeddedWorkerSetup {
void ExchangeInterfaceProviders(
int32_t thread_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services) override {
+ shell::mojom::InterfaceProviderRequest request,
+ shell::mojom::InterfaceProviderPtr remote_interfaces) override {
WorkerThreadRegistry::Instance()->GetTaskRunnerFor(thread_id)->PostTask(
FROM_HERE,
- base::Bind(&SetupEmbeddedWorkerOnWorkerThread, base::Passed(&services),
- base::Passed(exposed_services.PassInterface())));
+ base::Bind(&SetupEmbeddedWorkerOnWorkerThread, base::Passed(&request),
+ base::Passed(remote_interfaces.PassInterface())));
}
private:
@@ -430,8 +452,7 @@ scoped_refptr<ContextProviderCommandBuffer> CreateOffscreenContext(
std::move(gpu_channel_host), stream_id, stream_priority,
gpu::kNullSurfaceHandle,
GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext"),
- gfx::PreferIntegratedGpu, automatic_flushes, support_locking, limits,
- attributes, nullptr, type));
+ automatic_flushes, support_locking, limits, attributes, nullptr, type));
}
} // namespace
@@ -582,9 +603,11 @@ RenderThreadImpl::RenderThreadImpl(
std::unique_ptr<scheduler::RendererScheduler> scheduler,
scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue)
: ChildThreadImpl(Options::Builder()
- .InBrowserProcess(params).UseMojoChannel(true).Build()),
+ .InBrowserProcess(params)
+ .UseMojoChannel(true)
+ .Build()),
renderer_scheduler_(std::move(scheduler)),
- raster_worker_pool_(new RasterWorkerPool()) {
+ categorized_worker_pool_(new CategorizedWorkerPool()) {
Init(resource_task_queue);
}
@@ -596,7 +619,7 @@ RenderThreadImpl::RenderThreadImpl(
: ChildThreadImpl(Options::Builder().UseMojoChannel(true).Build()),
renderer_scheduler_(std::move(scheduler)),
main_message_loop_(std::move(main_message_loop)),
- raster_worker_pool_(new RasterWorkerPool()) {
+ categorized_worker_pool_(new CategorizedWorkerPool()) {
scoped_refptr<base::SingleThreadTaskRunner> test_task_counter;
Init(test_task_counter);
}
@@ -609,7 +632,7 @@ void RenderThreadImpl::Init(
base::PlatformThread::CurrentId(),
kTraceEventRendererMainThreadSortIndex);
-#if defined(OS_MACOSX) || (defined(OS_ANDROID) && !defined(USE_AURA))
+#if defined(USE_EXTERNAL_POPUP_MENU)
// On Mac and Android Java UI, the select popups are rendered by the browser.
blink::WebView::setUseExternalPopupMenus(true);
#endif
@@ -627,7 +650,6 @@ void RenderThreadImpl::Init(
hidden_widget_count_ = 0;
idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs;
idle_notifications_to_skip_ = 0;
- layout_test_mode_ = false;
appcache_dispatcher_.reset(
new AppCacheDispatcher(Get(), new AppCacheFrontendImpl()));
@@ -648,7 +670,7 @@ void RenderThreadImpl::Init(
media_stream_center_ = NULL;
- blob_message_filter_ = new BlobMessageFilter();
+ blob_message_filter_ = new BlobMessageFilter(GetFileThreadMessageLoopProxy());
AddFilter(blob_message_filter_.get());
db_message_filter_ = new DBMessageFilter();
AddFilter(db_message_filter_.get());
@@ -690,9 +712,6 @@ void RenderThreadImpl::Init(
midi_message_filter_ = new MidiMessageFilter(GetIOMessageLoopProxy());
AddFilter(midi_message_filter_.get());
- bluetooth_message_filter_ = new BluetoothMessageFilter(thread_safe_sender());
- AddFilter(bluetooth_message_filter_->GetFilter());
-
AddFilter((new IndexedDBMessageFilter(thread_safe_sender()))->GetFilter());
AddFilter((new CacheStorageMessageFilter(thread_safe_sender()))->GetFilter());
@@ -708,6 +727,16 @@ void RenderThreadImpl::Init(
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
+#if defined(ENABLE_IPC_FUZZER)
+ if (command_line.HasSwitch(switches::kIpcDumpDirectory)) {
+ base::FilePath dump_directory =
+ command_line.GetSwitchValuePath(switches::kIpcDumpDirectory);
+ IPC::ChannelProxy::OutgoingMessageFilter* filter =
+ LoadExternalIPCDumper(dump_directory);
+ GetChannel()->set_outgoing_message_filter(filter);
+ }
+#endif
+
cc::SetClientNameForMetrics("Renderer");
is_threaded_animation_enabled_ =
@@ -800,7 +829,7 @@ void RenderThreadImpl::Init(
// image decode tasks.
are_image_decode_tasks_enabled_ = true;
- raster_worker_pool_->Start(num_raster_threads);
+ categorized_worker_pool_->Start(num_raster_threads);
// TODO(boliu): In single process, browser main loop should set up the
// discardable memory manager, and should skip this if kSingleProcess.
@@ -808,19 +837,22 @@ void RenderThreadImpl::Init(
base::DiscardableMemoryAllocator::SetInstance(
ChildThreadImpl::discardable_shared_memory_manager());
- service_registry()->AddService(base::Bind(CreateRenderFrameSetup));
- service_registry()->AddService(base::Bind(CreateEmbeddedWorkerSetup));
+ GetContentClient()->renderer()->ExposeInterfacesToBrowser(
+ GetInterfaceRegistry());
-#if defined(MOJO_SHELL_CLIENT)
+ GetInterfaceRegistry()->AddInterface(base::Bind(CreateFrameFactory));
+ GetInterfaceRegistry()->AddInterface(base::Bind(CreateEmbeddedWorkerSetup));
+
+#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
// We may not have a MojoShellConnection object in tests that directly
// instantiate a RenderThreadImpl.
- if (MojoShellConnection::Get() &&
+ if (MojoShellConnection::GetForProcess() &&
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMusInRenderer))
CreateRenderWidgetWindowTreeClientFactory();
#endif
- service_registry()->ConnectToRemoteService(
+ GetRemoteInterfaces()->GetInterface(
mojo::GetProxy(&storage_partition_service_));
is_renderer_suspended_ = false;
@@ -896,7 +928,7 @@ void RenderThreadImpl::Shutdown() {
RemoveFilter(audio_message_filter_.get());
audio_message_filter_ = NULL;
- raster_worker_pool_->Shutdown();
+ categorized_worker_pool_->Shutdown();
main_input_callback_.Cancel();
input_handler_manager_.reset();
@@ -930,6 +962,7 @@ void RenderThreadImpl::Shutdown() {
// Shut down the message loop and the renderer scheduler before shutting down
// Blink. This prevents a scenario where a pending task in the message loop
// accesses Blink objects after Blink shuts down.
+ renderer_scheduler_->SetRAILModeObserver(nullptr);
renderer_scheduler_->Shutdown();
if (main_message_loop_)
main_message_loop_->RunUntilIdle();
@@ -1009,24 +1042,17 @@ RenderThreadImpl::GetIOMessageLoopProxy() {
void RenderThreadImpl::AddRoute(int32_t routing_id, IPC::Listener* listener) {
ChildThreadImpl::GetRouter()->AddRoute(routing_id, listener);
- PendingRenderFrameConnectMap::iterator it =
- pending_render_frame_connects_.find(routing_id);
- if (it == pending_render_frame_connects_.end())
+ auto it = pending_frame_creates_.find(routing_id);
+ if (it == pending_frame_creates_.end())
return;
RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(routing_id);
if (!frame)
return;
- scoped_refptr<PendingRenderFrameConnect> connection(it->second);
- shell::mojom::InterfaceProviderRequest services(
- std::move(connection->services()));
- shell::mojom::InterfaceProviderPtr exposed_services(
- std::move(connection->exposed_services()));
- exposed_services.set_connection_error_handler(mojo::Closure());
- pending_render_frame_connects_.erase(it);
-
- frame->BindServiceRegistry(std::move(services), std::move(exposed_services));
+ scoped_refptr<PendingFrameCreate> create(it->second);
+ frame->Bind(it->second->TakeFrameRequest(), it->second->TakeFrameHost());
+ pending_frame_creates_.erase(it);
}
void RenderThreadImpl::RemoveRoute(int32_t routing_id) {
@@ -1050,15 +1076,15 @@ void RenderThreadImpl::RemoveEmbeddedWorkerRoute(int32_t routing_id) {
}
}
-void RenderThreadImpl::RegisterPendingRenderFrameConnect(
+void RenderThreadImpl::RegisterPendingFrameCreate(
int routing_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services) {
- std::pair<PendingRenderFrameConnectMap::iterator, bool> result =
- pending_render_frame_connects_.insert(std::make_pair(
+ mojom::FrameRequest frame_request,
+ mojom::FrameHostPtr frame_host) {
+ std::pair<PendingFrameCreateMap::iterator, bool> result =
+ pending_frame_creates_.insert(std::make_pair(
routing_id,
- make_scoped_refptr(new PendingRenderFrameConnect(
- routing_id, std::move(services), std::move(exposed_services)))));
+ make_scoped_refptr(new PendingFrameCreate(
+ routing_id, std::move(frame_request), std::move(frame_host)))));
CHECK(result.second) << "Inserting a duplicate item.";
}
@@ -1105,7 +1131,6 @@ void RenderThreadImpl::InitializeCompositorThread() {
FROM_HERE,
base::Bind(base::IgnoreResult(&ThreadRestrictions::SetIOAllowed), false));
- InputHandlerManagerClient* input_handler_manager_client = nullptr;
SynchronousInputHandlerProxyClient* synchronous_input_handler_proxy_client =
nullptr;
#if defined(OS_ANDROID)
@@ -1113,22 +1138,17 @@ void RenderThreadImpl::InitializeCompositorThread() {
sync_compositor_message_filter_ =
new SynchronousCompositorFilter(compositor_task_runner_);
AddFilter(sync_compositor_message_filter_.get());
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSyncInputForSyncCompositor)) {
- input_handler_manager_client = sync_compositor_message_filter_.get();
- }
synchronous_input_handler_proxy_client =
sync_compositor_message_filter_.get();
}
#endif
- if (!input_handler_manager_client) {
- scoped_refptr<InputEventFilter> compositor_input_event_filter(
- new InputEventFilter(main_input_callback_.callback(),
- main_thread_compositor_task_runner_,
- compositor_task_runner_));
- input_handler_manager_client = compositor_input_event_filter.get();
- input_event_filter_ = compositor_input_event_filter;
- }
+ scoped_refptr<InputEventFilter> compositor_input_event_filter(
+ new InputEventFilter(main_input_callback_.callback(),
+ main_thread_compositor_task_runner_,
+ compositor_task_runner_));
+ InputHandlerManagerClient* input_handler_manager_client =
+ compositor_input_event_filter.get();
+ input_event_filter_ = compositor_input_event_filter;
input_handler_manager_.reset(new InputHandlerManager(
compositor_task_runner_, input_handler_manager_client,
synchronous_input_handler_proxy_client, renderer_scheduler_.get()));
@@ -1150,12 +1170,13 @@ void RenderThreadImpl::InitializeWebKit(
blink_platform_impl_.reset(new RendererBlinkPlatformImpl(
renderer_scheduler_.get(),
- static_cast<ServiceRegistryImpl*>(service_registry())->GetWeakPtr()));
+ GetRemoteInterfaces()->GetWeakPtr()));
blink::initialize(blink_platform_impl_.get());
v8::Isolate* isolate = blink::mainThreadIsolate();
isolate->SetCreateHistogramFunction(CreateHistogram);
isolate->SetAddHistogramSampleFunction(AddHistogramSample);
+ renderer_scheduler_->SetRAILModeObserver(this);
main_thread_compositor_task_runner_ =
renderer_scheduler_->CompositorTaskRunner();
@@ -1184,6 +1205,9 @@ void RenderThreadImpl::InitializeWebKit(
resource_task_queue2);
resource_dispatcher()->SetMainThreadTaskRunner(resource_task_queue2);
+ websocket_message_filter()->SetLoadingTaskRunner(
+ renderer_scheduler_->LoadingTaskRunner());
+
if (!command_line.HasSwitch(switches::kDisableThreadedCompositing) &&
!command_line.HasSwitch(switches::kUseRemoteCompositing))
InitializeCompositorThread();
@@ -1266,6 +1290,10 @@ void RenderThreadImpl::RegisterSchemes() {
// chrome-devtools:
WebString devtools_scheme(base::ASCIIToUTF16(kChromeDevToolsScheme));
WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(devtools_scheme);
+
+ // view-source:
+ WebString view_source_scheme(base::ASCIIToUTF16(kViewSourceScheme));
+ WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(view_source_scheme);
}
void RenderThreadImpl::NotifyTimezoneChange() {
@@ -1499,7 +1527,7 @@ bool RenderThreadImpl::EnableStreamTextureCopy() {
AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() {
if (!audio_renderer_mixer_manager_) {
- audio_renderer_mixer_manager_.reset(new AudioRendererMixerManager());
+ audio_renderer_mixer_manager_ = AudioRendererMixerManager::Create();
}
return audio_renderer_mixer_manager_.get();
@@ -1531,11 +1559,6 @@ void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font,
#endif // OS_WIN
-ServiceRegistry* RenderThreadImpl::GetServiceRegistry() {
- DCHECK(service_registry());
- return service_registry();
-}
-
bool RenderThreadImpl::IsGpuRasterizationForced() {
return is_gpu_rasterization_forced_;
}
@@ -1600,12 +1623,6 @@ scheduler::RendererScheduler* RenderThreadImpl::GetRendererScheduler() {
std::unique_ptr<cc::BeginFrameSource>
RenderThreadImpl::CreateExternalBeginFrameSource(int routing_id) {
-#if defined(OS_ANDROID)
- if (sync_compositor_message_filter_) {
- return base::WrapUnique(new SynchronousCompositorExternalBeginFrameSource(
- routing_id, sync_compositor_message_filter_.get()));
- }
-#endif
return base::WrapUnique(new CompositorExternalBeginFrameSource(
compositor_message_filter_.get(), sync_message_filter(), routing_id));
}
@@ -1616,7 +1633,7 @@ RenderThreadImpl::GetImageSerializationProcessor() {
}
cc::TaskGraphRunner* RenderThreadImpl::GetTaskGraphRunner() {
- return raster_worker_pool_->GetTaskGraphRunner();
+ return categorized_worker_pool_->GetTaskGraphRunner();
}
bool RenderThreadImpl::AreImageDecodeTasksEnabled() {
@@ -1627,6 +1644,11 @@ bool RenderThreadImpl::IsThreadedAnimationEnabled() {
return is_threaded_animation_enabled_;
}
+void RenderThreadImpl::OnRAILModeChanged(v8::RAILMode rail_mode) {
+ blink::mainThreadIsolate()->SetRAILMode(rail_mode);
+ blink::setRAILModeOnWorkerThreadIsolates(rail_mode);
+}
+
bool RenderThreadImpl::IsMainThread() {
return !!current();
}
@@ -1789,6 +1811,123 @@ scoped_refptr<gpu::GpuChannelHost> RenderThreadImpl::EstablishGpuChannelSync(
return gpu_channel_;
}
+std::unique_ptr<cc::OutputSurface>
+RenderThreadImpl::CreateCompositorOutputSurface(
+ bool use_software,
+ int routing_id,
+ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
+ const GURL& url) {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kDisableGpuCompositing))
+ use_software = true;
+
+#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
+ auto shell_connection = MojoShellConnection::GetForProcess();
+ if (shell_connection && !use_software &&
+ command_line.HasSwitch(switches::kUseMusInRenderer)) {
+ mus::GpuService::Initialize(shell_connection->GetConnector());
+ RenderWidgetMusConnection* connection =
+ RenderWidgetMusConnection::GetOrCreate(routing_id);
+ return connection->CreateOutputSurface();
+ }
+#endif
+
+ uint32_t output_surface_id = g_next_output_surface_id++;
+
+ if (command_line.HasSwitch(switches::kEnableVulkan)) {
+ scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider =
+ cc::VulkanInProcessContextProvider::Create();
+ if (vulkan_context_provider) {
+ DCHECK(!layout_test_mode());
+ return base::WrapUnique(new CompositorOutputSurface(
+ routing_id, output_surface_id, std::move(vulkan_context_provider),
+ std::move(frame_swap_message_queue)));
+ }
+ }
+
+ // Create a gpu process channel and verify we want to use GPU compositing
+ // before creating any context providers.
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host;
+ if (!use_software) {
+ gpu_channel_host = EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_RENDERER_VERIFY_GPU_COMPOSITING);
+ if (!gpu_channel_host) {
+ // Cause the compositor to wait and try again.
+ return nullptr;
+ }
+ // We may get a valid channel, but with a software renderer. In that case,
+ // disable GPU compositing.
+ if (gpu_channel_host->gpu_info().software_rendering)
+ use_software = true;
+ }
+
+ if (use_software) {
+ DCHECK(!layout_test_mode());
+ return base::WrapUnique(new CompositorOutputSurface(
+ routing_id, output_surface_id, nullptr, nullptr,
+ std::move(frame_swap_message_queue)));
+ }
+
+ scoped_refptr<ContextProviderCommandBuffer> worker_context_provider =
+ SharedCompositorWorkerContextProvider();
+ if (!worker_context_provider) {
+ // Cause the compositor to wait and try again.
+ return nullptr;
+ }
+
+ // The renderer compositor context doesn't do a lot of stuff, so we don't
+ // expect it to need a lot of space for commands or transfer. Raster and
+ // uploads happen on the worker context instead.
+ gpu::SharedMemoryLimits limits = gpu::SharedMemoryLimits::ForMailboxContext();
+
+ // This is for an offscreen context for the compositor. So the default
+ // framebuffer doesn't need alpha, depth, stencil, antialiasing.
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = -1;
+ attributes.depth_size = 0;
+ attributes.stencil_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
+ attributes.lose_context_when_out_of_memory = true;
+
+ constexpr bool automatic_flushes = false;
+ constexpr bool support_locking = false;
+
+ // The compositor context shares resources with the worker context unless
+ // the worker is async.
+ ContextProviderCommandBuffer* share_context = worker_context_provider.get();
+ if (IsAsyncWorkerContextEnabled())
+ share_context = nullptr;
+
+ scoped_refptr<ContextProviderCommandBuffer> context_provider(
+ new ContextProviderCommandBuffer(
+ gpu_channel_host, gpu::GPU_STREAM_DEFAULT,
+ gpu::GpuStreamPriority::NORMAL, gpu::kNullSurfaceHandle, url,
+ automatic_flushes, support_locking, limits, attributes, share_context,
+ command_buffer_metrics::RENDER_COMPOSITOR_CONTEXT));
+
+ if (layout_test_deps_) {
+ return layout_test_deps_->CreateOutputSurface(
+ std::move(gpu_channel_host), std::move(context_provider),
+ std::move(worker_context_provider), this);
+ }
+
+#if defined(OS_ANDROID)
+ if (sync_compositor_message_filter_) {
+ return base::WrapUnique(new SynchronousCompositorOutputSurface(
+ std::move(context_provider), std::move(worker_context_provider),
+ routing_id, output_surface_id, sync_compositor_message_filter_.get(),
+ std::move(frame_swap_message_queue)));
+ }
+#endif
+
+ return base::WrapUnique(new CompositorOutputSurface(
+ routing_id, output_surface_id, std::move(context_provider),
+ std::move(worker_context_provider), std::move(frame_swap_message_queue)));
+}
+
blink::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter(
blink::WebMediaStreamCenterClient* client) {
#if defined(ENABLE_WEBRTC)
@@ -1906,7 +2045,7 @@ void RenderThreadImpl::OnMemoryPressure(
// Do not call into blink if it is not initialized.
if (blink_platform_impl_) {
- blink::WebMemoryPressureListener::onMemoryPressure(
+ blink::WebMemoryCoordinator::onMemoryPressure(
static_cast<blink::WebMemoryPressureLevel>(memory_pressure_level));
if (memory_pressure_level ==
@@ -1945,7 +2084,7 @@ RenderThreadImpl::GetMediaThreadTaskRunner() {
}
base::TaskRunner* RenderThreadImpl::GetWorkerTaskRunner() {
- return raster_worker_pool_.get();
+ return categorized_worker_pool_.get();
}
scoped_refptr<ContextProviderCommandBuffer>
@@ -2049,29 +2188,27 @@ void RenderThreadImpl::ReleaseFreeMemory() {
blink::decommitFreeableMemory();
}
-RenderThreadImpl::PendingRenderFrameConnect::PendingRenderFrameConnect(
+RenderThreadImpl::PendingFrameCreate::PendingFrameCreate(
int routing_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services)
+ mojom::FrameRequest frame_request,
+ mojom::FrameHostPtr frame_host)
: routing_id_(routing_id),
- services_(std::move(services)),
- exposed_services_(std::move(exposed_services)) {
- // The RenderFrame may be deleted before the ExchangeInterfaceProviders
- // message is received. In that case, the RenderFrameHost should close the
- // connection, which is detected by setting an error handler on
- // |exposed_services_|.
- exposed_services_.set_connection_error_handler(base::Bind(
- &RenderThreadImpl::PendingRenderFrameConnect::OnConnectionError,
+ frame_request_(std::move(frame_request)),
+ frame_host_(std::move(frame_host)) {
+ // The RenderFrame may be deleted before the CreateFrame message is received.
+ // In that case, the RenderFrameHost should cancel the create, which is
+ // detected by setting an error handler on |frame_host_|.
+ frame_host_.set_connection_error_handler(base::Bind(
+ &RenderThreadImpl::PendingFrameCreate::OnConnectionError,
base::Unretained(this)));
}
-RenderThreadImpl::PendingRenderFrameConnect::~PendingRenderFrameConnect() {
+RenderThreadImpl::PendingFrameCreate::~PendingFrameCreate() {
}
-void RenderThreadImpl::PendingRenderFrameConnect::OnConnectionError() {
+void RenderThreadImpl::PendingFrameCreate::OnConnectionError() {
size_t erased =
- RenderThreadImpl::current()->pending_render_frame_connects_.erase(
- routing_id_);
+ RenderThreadImpl::current()->pending_frame_creates_.erase(routing_id_);
DCHECK_EQ(1u, erased);
}
diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h
index 486efe0dbfe..1f26f30d512 100644
--- a/chromium/content/renderer/render_thread_impl.h
+++ b/chromium/content/renderer/render_thread_impl.h
@@ -22,13 +22,16 @@
#include "base/threading/thread_checker.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
+#include "components/scheduler/renderer/renderer_scheduler.h"
#include "content/child/child_thread_impl.h"
#include "content/common/content_export.h"
+#include "content/common/frame.mojom.h"
#include "content/common/frame_replication_state.h"
#include "content/common/gpu_process_launch_causes.h"
#include "content/common/storage_partition_service.mojom.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/gpu/compositor_dependencies.h"
+#include "content/renderer/layout_test_dependencies.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "net/base/network_change_notifier.h"
#include "third_party/WebKit/public/platform/WebConnectionType.h"
@@ -59,6 +62,7 @@ class Thread;
namespace cc {
class ContextProvider;
class ImageSerializationProcessor;
+class OutputSurface;
class TaskGraphRunner;
}
@@ -76,7 +80,6 @@ class GpuVideoAcceleratorFactories;
}
namespace scheduler {
-class RendererScheduler;
class WebThreadBase;
}
@@ -92,7 +95,6 @@ class AudioInputMessageFilter;
class AudioMessageFilter;
class AudioRendererMixerManager;
class BlobMessageFilter;
-class BluetoothMessageFilter;
class BrowserPluginManager;
class CacheStorageDispatcher;
class CompositorForwardingMessageFilter;
@@ -101,6 +103,7 @@ class DBMessageFilter;
class DevToolsAgentFilter;
class DomStorageDispatcher;
class EmbeddedWorkerDispatcher;
+class FrameSwapMessageQueue;
class IndexedDBDispatcher;
class InputHandlerManager;
class MediaStreamCenter;
@@ -110,7 +113,7 @@ class NetInfoDispatcher;
class P2PSocketDispatcher;
class PeerConnectionDependencyFactory;
class PeerConnectionTracker;
-class RasterWorkerPool;
+class CategorizedWorkerPool;
class RenderThreadObserver;
class RendererBlinkPlatformImpl;
class RendererDemuxerAndroid;
@@ -144,6 +147,7 @@ class CONTENT_EXPORT RenderThreadImpl
: public RenderThread,
public ChildThreadImpl,
public gpu::GpuChannelHostFactory,
+ public scheduler::RendererScheduler::RAILModeObserver,
NON_EXPORTED_BASE(public CompositorDependencies) {
public:
static RenderThreadImpl* Create(const InProcessChildThreadParams& params);
@@ -191,7 +195,6 @@ class CONTENT_EXPORT RenderThreadImpl
int PostTaskToAllWebWorkers(const base::Closure& closure) override;
bool ResolveProxy(const GURL& url, std::string* proxy_list) override;
base::WaitableEvent* GetShutdownEvent() override;
- ServiceRegistry* GetServiceRegistry() override;
// CompositorDependencies implementation.
bool IsGpuRasterizationForced() override;
@@ -218,20 +221,28 @@ class CONTENT_EXPORT RenderThreadImpl
bool AreImageDecodeTasksEnabled() override;
bool IsThreadedAnimationEnabled() override;
+ // scheduler::RendererScheduler::RAILModeObserver implementation.
+ void OnRAILModeChanged(v8::RAILMode rail_mode) override;
+
// Synchronously establish a channel to the GPU plugin if not previously
// established or if it has been lost (for example if the GPU plugin crashed).
// If there is a pending asynchronous request, it will be completed by the
// time this routine returns.
scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSync(CauseForGpuLaunch);
+ std::unique_ptr<cc::OutputSurface> CreateCompositorOutputSurface(
+ bool use_software,
+ int routing_id,
+ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
+ const GURL& url);
+
// True if we are running layout tests. This currently disables forwarding
// various status messages to the console, skips network error pages, and
// short circuits size update and focus events.
- bool layout_test_mode() const {
- return layout_test_mode_;
- }
- void set_layout_test_mode(bool layout_test_mode) {
- layout_test_mode_ = layout_test_mode;
+ bool layout_test_mode() const { return !!layout_test_deps_; }
+ void set_layout_test_dependencies(
+ std::unique_ptr<LayoutTestDependencies> deps) {
+ layout_test_deps_ = std::move(deps);
}
RendererBlinkPlatformImpl* blink_platform_impl() const {
@@ -437,10 +448,9 @@ class CONTENT_EXPORT RenderThreadImpl
void AddEmbeddedWorkerRoute(int32_t routing_id, IPC::Listener* listener);
void RemoveEmbeddedWorkerRoute(int32_t routing_id);
- void RegisterPendingRenderFrameConnect(
- int routing_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services);
+ void RegisterPendingFrameCreate(int routing_id,
+ mojom::FrameRequest frame,
+ mojom::FrameHostPtr host);
mojom::StoragePartitionService* GetStoragePartitionService();
@@ -576,8 +586,8 @@ class CONTENT_EXPORT RenderThreadImpl
bool webkit_shared_timer_suspended_;
- // The following flag is used to control layout test specific behavior.
- bool layout_test_mode_;
+ // Used to control layout test specific behavior.
+ std::unique_ptr<LayoutTestDependencies> layout_test_deps_;
// Timer that periodically calls IdleHandler.
base::RepeatingTimer idle_timer_;
@@ -614,7 +624,7 @@ class CONTENT_EXPORT RenderThreadImpl
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
// Pool of workers used for raster operations (e.g., tile rasterization).
- scoped_refptr<RasterWorkerPool> raster_worker_pool_;
+ scoped_refptr<CategorizedWorkerPool> categorized_worker_pool_;
base::CancelableCallback<void(const IPC::Message&)> main_input_callback_;
scoped_refptr<IPC::MessageFilter> input_event_filter_;
@@ -626,8 +636,6 @@ class CONTENT_EXPORT RenderThreadImpl
scoped_refptr<StreamTextureFactory> stream_texture_factory_;
#endif
- scoped_refptr<BluetoothMessageFilter> bluetooth_message_filter_;
-
scoped_refptr<ContextProviderCommandBuffer> shared_main_thread_contexts_;
base::ObserverList<RenderThreadObserver> observers_;
@@ -666,36 +674,34 @@ class CONTENT_EXPORT RenderThreadImpl
bool are_image_decode_tasks_enabled_;
bool is_threaded_animation_enabled_;
- class PendingRenderFrameConnect
- : public base::RefCounted<PendingRenderFrameConnect> {
+ class PendingFrameCreate : public base::RefCounted<PendingFrameCreate> {
public:
- PendingRenderFrameConnect(
- int routing_id,
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services);
-
- shell::mojom::InterfaceProviderRequest& services() { return services_; }
-
- shell::mojom::InterfaceProviderPtr& exposed_services() {
- return exposed_services_;
+ PendingFrameCreate(int routing_id,
+ mojom::FrameRequest frame_request,
+ mojom::FrameHostPtr frame_host);
+
+ mojom::FrameRequest TakeFrameRequest() { return std::move(frame_request_); }
+ mojom::FrameHostPtr TakeFrameHost() {
+ frame_host_.set_connection_error_handler(base::Closure());
+ return std::move(frame_host_);
}
private:
- friend class base::RefCounted<PendingRenderFrameConnect>;
+ friend class base::RefCounted<PendingFrameCreate>;
- ~PendingRenderFrameConnect();
+ ~PendingFrameCreate();
// Mojo error handler.
void OnConnectionError();
int routing_id_;
- shell::mojom::InterfaceProviderRequest services_;
- shell::mojom::InterfaceProviderPtr exposed_services_;
+ mojom::FrameRequest frame_request_;
+ mojom::FrameHostPtr frame_host_;
};
- typedef std::map<int, scoped_refptr<PendingRenderFrameConnect>>
- PendingRenderFrameConnectMap;
- PendingRenderFrameConnectMap pending_render_frame_connects_;
+ using PendingFrameCreateMap =
+ std::map<int, scoped_refptr<PendingFrameCreate>>;
+ PendingFrameCreateMap pending_frame_creates_;
mojom::StoragePartitionServicePtr storage_partition_service_;
diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc
index 98c0ad33f9c..57747020cd7 100644
--- a/chromium/content/renderer/render_view_browsertest.cc
+++ b/chromium/content/renderer/render_view_browsertest.cc
@@ -4,6 +4,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <tuple>
#include "base/bind.h"
#include "base/callback.h"
@@ -45,7 +46,7 @@
#include "content/public/test/frame_load_waiter.h"
#include "content/public/test/render_view_test.h"
#include "content/public/test/test_utils.h"
-#include "content/renderer/accessibility/renderer_accessibility.h"
+#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "content/renderer/devtools/devtools_agent.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/history_controller.h"
@@ -546,54 +547,6 @@ TEST_F(RenderViewImplTest, RenderFrameClearedAfterClose) {
new_view->Release();
}
-TEST_F(RenderViewImplTest, SaveImageFromDataURL) {
- const IPC::Message* msg1 = render_thread_->sink().GetFirstMessageMatching(
- ViewHostMsg_SaveImageFromDataURL::ID);
- EXPECT_FALSE(msg1);
- render_thread_->sink().ClearMessages();
-
- const std::string image_data_url =
- "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=";
-
- view()->saveImageFromDataURL(WebString::fromUTF8(image_data_url));
- ProcessPendingMessages();
- const IPC::Message* msg2 = render_thread_->sink().GetFirstMessageMatching(
- ViewHostMsg_SaveImageFromDataURL::ID);
- EXPECT_TRUE(msg2);
-
- ViewHostMsg_SaveImageFromDataURL::Param param1;
- ViewHostMsg_SaveImageFromDataURL::Read(msg2, &param1);
- EXPECT_EQ(base::get<2>(param1).length(), image_data_url.length());
- EXPECT_EQ(base::get<2>(param1), image_data_url);
-
- ProcessPendingMessages();
- render_thread_->sink().ClearMessages();
-
- const std::string large_data_url(1024 * 1024 * 20 - 1, 'd');
-
- view()->saveImageFromDataURL(WebString::fromUTF8(large_data_url));
- ProcessPendingMessages();
- const IPC::Message* msg3 = render_thread_->sink().GetFirstMessageMatching(
- ViewHostMsg_SaveImageFromDataURL::ID);
- EXPECT_TRUE(msg3);
-
- ViewHostMsg_SaveImageFromDataURL::Param param2;
- ViewHostMsg_SaveImageFromDataURL::Read(msg3, &param2);
- EXPECT_EQ(base::get<2>(param2).length(), large_data_url.length());
- EXPECT_EQ(base::get<2>(param2), large_data_url);
-
- ProcessPendingMessages();
- render_thread_->sink().ClearMessages();
-
- const std::string exceeded_data_url(1024 * 1024 * 20 + 1, 'd');
-
- view()->saveImageFromDataURL(WebString::fromUTF8(exceeded_data_url));
- ProcessPendingMessages();
- const IPC::Message* msg4 = render_thread_->sink().GetFirstMessageMatching(
- ViewHostMsg_SaveImageFromDataURL::ID);
- EXPECT_FALSE(msg4);
-}
-
// Test that we get form state change notifications when input fields change.
TEST_F(RenderViewImplTest, OnNavStateChanged) {
view()->set_send_content_state_immediately(true);
@@ -633,11 +586,11 @@ TEST_F(RenderViewImplTest, OnNavigationHttpPost) {
request_params.page_id = -1;
// Set up post data.
- const unsigned char* raw_data = reinterpret_cast<const unsigned char*>(
- "post \0\ndata");
- const unsigned int length = 11;
- const std::vector<unsigned char> post_data(raw_data, raw_data + length);
- start_params.browser_initiated_post_data = post_data;
+ const char raw_data[] = "post \0\ndata";
+ const size_t length = arraysize(raw_data);
+ scoped_refptr<ResourceRequestBodyImpl> post_data(new ResourceRequestBodyImpl);
+ post_data->AppendBytes(raw_data, length);
+ common_params.post_data = post_data;
frame()->Navigate(common_params, start_params, request_params);
ProcessPendingMessages();
@@ -650,12 +603,12 @@ TEST_F(RenderViewImplTest, OnNavigationHttpPost) {
FrameHostMsg_DidCommitProvisionalLoad::Param host_nav_params;
FrameHostMsg_DidCommitProvisionalLoad::Read(frame_navigate_msg,
&host_nav_params);
- EXPECT_EQ("POST", base::get<0>(host_nav_params).method);
+ EXPECT_EQ("POST", std::get<0>(host_nav_params).method);
// Check post data sent to browser matches
- EXPECT_TRUE(base::get<0>(host_nav_params).page_state.IsValid());
+ EXPECT_TRUE(std::get<0>(host_nav_params).page_state.IsValid());
std::unique_ptr<HistoryEntry> entry =
- PageStateToHistoryEntry(base::get<0>(host_nav_params).page_state);
+ PageStateToHistoryEntry(std::get<0>(host_nav_params).page_state);
blink::WebHTTPBody body = entry->root().httpBody();
blink::WebHTTPBody::Element element;
bool successful = body.elementAt(0, element);
@@ -697,7 +650,7 @@ TEST_F(RenderViewImplTest, OnBrowserNavigationUpdatePageID) {
FrameHostMsg_DidCommitProvisionalLoad::Param host_nav_params;
FrameHostMsg_DidCommitProvisionalLoad::Read(frame_navigate_msg,
&host_nav_params);
- EXPECT_TRUE(base::get<0>(host_nav_params).page_state.IsValid());
+ EXPECT_TRUE(std::get<0>(host_nav_params).page_state.IsValid());
const IPC::Message* frame_page_id_msg =
render_thread_->sink().GetUniqueMessageMatching(
@@ -707,7 +660,7 @@ TEST_F(RenderViewImplTest, OnBrowserNavigationUpdatePageID) {
FrameHostMsg_DidAssignPageId::Param host_page_id_params;
FrameHostMsg_DidAssignPageId::Read(frame_page_id_msg, &host_page_id_params);
- EXPECT_EQ(base::get<0>(host_page_id_params), view_page_id());
+ EXPECT_EQ(std::get<0>(host_page_id_params), view_page_id());
}
#if defined(OS_ANDROID)
@@ -734,7 +687,7 @@ TEST_F(RenderViewImplTest, OnNavigationLoadDataWithBaseURL) {
// Check post data sent to browser matches.
FrameHostMsg_UpdateTitle::Param title_params;
EXPECT_TRUE(FrameHostMsg_UpdateTitle::Read(frame_title_msg, &title_params));
- EXPECT_EQ(base::ASCIIToUTF16("Data page"), base::get<0>(title_params));
+ EXPECT_EQ(base::ASCIIToUTF16("Data page"), std::get<0>(title_params));
}
#endif
@@ -1044,8 +997,8 @@ TEST_F(RenderViewImplTest, DISABLED_LastCommittedUpdateState) {
ASSERT_TRUE(msg_A);
ViewHostMsg_UpdateState::Param param;
ViewHostMsg_UpdateState::Read(msg_A, &param);
- int page_id_A = base::get<0>(param);
- PageState state_A = base::get<1>(param);
+ int page_id_A = std::get<0>(param);
+ PageState state_A = std::get<1>(param);
EXPECT_EQ(1, page_id_A);
render_thread_->sink().ClearMessages();
@@ -1058,8 +1011,8 @@ TEST_F(RenderViewImplTest, DISABLED_LastCommittedUpdateState) {
ViewHostMsg_UpdateState::ID);
ASSERT_TRUE(msg_B);
ViewHostMsg_UpdateState::Read(msg_B, &param);
- int page_id_B = base::get<0>(param);
- PageState state_B = base::get<1>(param);
+ int page_id_B = std::get<0>(param);
+ PageState state_B = std::get<1>(param);
EXPECT_EQ(2, page_id_B);
EXPECT_NE(state_A, state_B);
render_thread_->sink().ClearMessages();
@@ -1073,8 +1026,8 @@ TEST_F(RenderViewImplTest, DISABLED_LastCommittedUpdateState) {
ViewHostMsg_UpdateState::ID);
ASSERT_TRUE(msg_C);
ViewHostMsg_UpdateState::Read(msg_C, &param);
- int page_id_C = base::get<0>(param);
- PageState state_C = base::get<1>(param);
+ int page_id_C = std::get<0>(param);
+ PageState state_C = std::get<1>(param);
EXPECT_EQ(3, page_id_C);
EXPECT_NE(state_B, state_C);
render_thread_->sink().ClearMessages();
@@ -1128,8 +1081,8 @@ TEST_F(RenderViewImplTest, DISABLED_LastCommittedUpdateState) {
ViewHostMsg_UpdateState::ID);
ASSERT_TRUE(msg);
ViewHostMsg_UpdateState::Read(msg, &param);
- int page_id = base::get<0>(param);
- PageState state = base::get<1>(param);
+ int page_id = std::get<0>(param);
+ PageState state = std::get<1>(param);
EXPECT_EQ(page_id_C, page_id);
EXPECT_NE(state_A, state);
EXPECT_NE(state_B, state);
@@ -1202,7 +1155,7 @@ TEST_F(RenderViewImplTest, OnImeTypeChanged) {
EXPECT_EQ(ViewHostMsg_TextInputStateChanged::ID, msg->type());
ViewHostMsg_TextInputStateChanged::Param params;
ViewHostMsg_TextInputStateChanged::Read(msg, &params);
- TextInputState p = base::get<0>(params);
+ TextInputState p = std::get<0>(params);
ui::TextInputType type = p.type;
ui::TextInputMode input_mode = p.mode;
bool can_compose_inline = p.can_compose_inline;
@@ -1222,7 +1175,7 @@ TEST_F(RenderViewImplTest, OnImeTypeChanged) {
EXPECT_TRUE(msg != NULL);
EXPECT_EQ(ViewHostMsg_TextInputStateChanged::ID, msg->type());
ViewHostMsg_TextInputStateChanged::Read(msg, &params);
- p = base::get<0>(params);
+ p = std::get<0>(params);
type = p.type;
input_mode = p.mode;
EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, type);
@@ -1247,7 +1200,7 @@ TEST_F(RenderViewImplTest, OnImeTypeChanged) {
EXPECT_TRUE(msg != NULL);
EXPECT_EQ(ViewHostMsg_TextInputStateChanged::ID, msg->type());
ViewHostMsg_TextInputStateChanged::Read(msg, &params);
- p = base::get<0>(params);
+ p = std::get<0>(params);
type = p.type;
input_mode = p.mode;
EXPECT_EQ(test_case->expected_mode, input_mode);
@@ -2007,7 +1960,7 @@ TEST_F(RenderViewImplTest, FocusElementCallsFocusedNodeChanged) {
ViewHostMsg_FocusedNodeChanged::Param params;
ViewHostMsg_FocusedNodeChanged::Read(msg1, &params);
- EXPECT_TRUE(base::get<0>(params));
+ EXPECT_TRUE(std::get<0>(params));
render_thread_->sink().ClearMessages();
ExecuteJavaScriptForTests("document.getElementById('test2').focus();");
@@ -2015,7 +1968,7 @@ TEST_F(RenderViewImplTest, FocusElementCallsFocusedNodeChanged) {
ViewHostMsg_FocusedNodeChanged::ID);
EXPECT_TRUE(msg2);
ViewHostMsg_FocusedNodeChanged::Read(msg2, &params);
- EXPECT_TRUE(base::get<0>(params));
+ EXPECT_TRUE(std::get<0>(params));
render_thread_->sink().ClearMessages();
view()->webview()->clearFocusedElement();
@@ -2023,7 +1976,7 @@ TEST_F(RenderViewImplTest, FocusElementCallsFocusedNodeChanged) {
ViewHostMsg_FocusedNodeChanged::ID);
EXPECT_TRUE(msg3);
ViewHostMsg_FocusedNodeChanged::Read(msg3, &params);
- EXPECT_FALSE(base::get<0>(params));
+ EXPECT_FALSE(std::get<0>(params));
render_thread_->sink().ClearMessages();
}
@@ -2071,19 +2024,19 @@ TEST_F(RenderViewImplTest, ServiceWorkerNetworkProviderSetup) {
TEST_F(RenderViewImplTest, OnSetAccessibilityMode) {
ASSERT_EQ(AccessibilityModeOff, frame()->accessibility_mode());
- ASSERT_EQ((RendererAccessibility*) NULL, frame()->renderer_accessibility());
+ ASSERT_FALSE(frame()->render_accessibility());
frame()->SetAccessibilityMode(AccessibilityModeTreeOnly);
ASSERT_EQ(AccessibilityModeTreeOnly, frame()->accessibility_mode());
- ASSERT_NE((RendererAccessibility*) NULL, frame()->renderer_accessibility());
+ ASSERT_TRUE(frame()->render_accessibility());
frame()->SetAccessibilityMode(AccessibilityModeOff);
ASSERT_EQ(AccessibilityModeOff, frame()->accessibility_mode());
- ASSERT_EQ((RendererAccessibility*) NULL, frame()->renderer_accessibility());
+ ASSERT_FALSE(frame()->render_accessibility());
frame()->SetAccessibilityMode(AccessibilityModeComplete);
ASSERT_EQ(AccessibilityModeComplete, frame()->accessibility_mode());
- ASSERT_NE((RendererAccessibility*) NULL, frame()->renderer_accessibility());
+ ASSERT_TRUE(frame()->render_accessibility());
}
// Sanity check for the Navigation Timing API |navigationStart| override. We
@@ -2123,7 +2076,7 @@ TEST_F(RenderViewImplTest, RendererNavigationStartTransmittedToBrowser) {
FrameHostMsg_DidStartProvisionalLoad::Param host_nav_params;
FrameHostMsg_DidStartProvisionalLoad::Read(frame_navigate_msg,
&host_nav_params);
- base::TimeTicks transmitted_start = base::get<1>(host_nav_params);
+ base::TimeTicks transmitted_start = std::get<1>(host_nav_params);
EXPECT_FALSE(transmitted_start.is_null());
EXPECT_LT(lower_bound_navigation_start, transmitted_start);
}
@@ -2147,7 +2100,7 @@ TEST_F(RenderViewImplTest, BrowserNavigationStartNotUsedForReload) {
FrameHostMsg_DidStartProvisionalLoad::Param host_nav_params =
ProcessAndReadIPC<FrameHostMsg_DidStartProvisionalLoad>();
// The true timestamp is later than the browser initiated one.
- EXPECT_PRED2(TimeTicksGT, base::get<1>(host_nav_params),
+ EXPECT_PRED2(TimeTicksGT, std::get<1>(host_nav_params),
common_params.navigation_start);
}
@@ -2169,7 +2122,7 @@ TEST_F(RenderViewImplTest, BrowserNavigationStartNotUsedForHistoryNavigation) {
StartNavigationParams(), RequestNavigationParams());
FrameHostMsg_DidStartProvisionalLoad::Param host_nav_params =
ProcessAndReadIPC<FrameHostMsg_DidStartProvisionalLoad>();
- EXPECT_PRED2(TimeTicksGT, base::get<1>(host_nav_params),
+ EXPECT_PRED2(TimeTicksGT, std::get<1>(host_nav_params),
common_params_back.navigation_start);
render_thread_->sink().ClearMessages();
@@ -2182,7 +2135,7 @@ TEST_F(RenderViewImplTest, BrowserNavigationStartNotUsedForHistoryNavigation) {
StartNavigationParams(), RequestNavigationParams());
FrameHostMsg_DidStartProvisionalLoad::Param host_nav_params2 =
ProcessAndReadIPC<FrameHostMsg_DidStartProvisionalLoad>();
- EXPECT_PRED2(TimeTicksGT, base::get<1>(host_nav_params2),
+ EXPECT_PRED2(TimeTicksGT, std::get<1>(host_nav_params2),
common_params_forward.navigation_start);
}
@@ -2197,7 +2150,7 @@ TEST_F(RenderViewImplTest, BrowserNavigationStartSuccessfullyTransmitted) {
FrameHostMsg_DidStartProvisionalLoad::Param host_nav_params =
ProcessAndReadIPC<FrameHostMsg_DidStartProvisionalLoad>();
- EXPECT_EQ(base::get<1>(host_nav_params), common_params.navigation_start);
+ EXPECT_EQ(std::get<1>(host_nav_params), common_params.navigation_start);
}
TEST_F(RenderViewImplTest, PreferredSizeZoomed) {
diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc
index c6c6a4991ce..be61076b8df 100644
--- a/chromium/content/renderer/render_view_impl.cc
+++ b/chromium/content/renderer/render_view_impl.cc
@@ -19,17 +19,20 @@
#include "base/i18n/rtl.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
+#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/process/kill.h"
#include "base/process/process.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -42,15 +45,12 @@
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/content_constants_internal.h"
#include "content/common/content_switches_internal.h"
-#include "content/common/database_messages.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/common/drag_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/frame_replication_state.h"
-#include "content/common/input/input_event_utils.h"
#include "content/common/input_messages.h"
#include "content/common/page_messages.h"
-#include "content/common/pepper_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
@@ -60,8 +60,6 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/drop_data.h"
#include "content/public/common/favicon_url.h"
-#include "content/public/common/file_chooser_file_info.h"
-#include "content/public/common/file_chooser_params.h"
#include "content/public/common/page_importance_signals.h"
#include "content/public/common/page_state.h"
#include "content/public/common/page_zoom.h"
@@ -92,7 +90,6 @@
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/render_view_mouse_lock_dispatcher.h"
#include "content/renderer/render_widget_fullscreen_pepper.h"
#include "content/renderer/renderer_webapplicationcachehost_impl.h"
#include "content/renderer/resizing_mode_selector.h"
@@ -392,39 +389,55 @@ static void ConvertToFaviconSizes(
///////////////////////////////////////////////////////////////////////////////
-struct RenderViewImpl::PendingFileChooser {
- PendingFileChooser(const FileChooserParams& p, WebFileChooserCompletion* c)
- : params(p),
- completion(c) {
- }
- FileChooserParams params;
- WebFileChooserCompletion* completion; // MAY BE NULL to skip callback.
-};
-
namespace {
-class WebWidgetLockTarget : public MouseLockDispatcher::LockTarget {
- public:
- explicit WebWidgetLockTarget(blink::WebWidget* webwidget)
- : webwidget_(webwidget) {}
-
- void OnLockMouseACK(bool succeeded) override {
- if (succeeded)
- webwidget_->didAcquirePointerLock();
- else
- webwidget_->didNotAcquirePointerLock();
- }
+WebDragData DropMetaDataToWebDragData(
+ const std::vector<DropData::Metadata>& drop_meta_data) {
+ std::vector<WebDragData::Item> item_list;
+ for (const auto& meta_data_item : drop_meta_data) {
+ if (meta_data_item.kind == DropData::Kind::STRING) {
+ WebDragData::Item item;
+ item.storageType = WebDragData::Item::StorageTypeString;
+ item.stringType = meta_data_item.mime_type;
+ // Have to pass a dummy URL here instead of an empty URL because the
+ // DropData received by browser_plugins goes through a round trip:
+ // DropData::MetaData --> WebDragData-->DropData. In the end, DropData
+ // will contain an empty URL (which means no URL is dragged) if the URL in
+ // WebDragData is empty.
+ if (base::EqualsASCII(meta_data_item.mime_type,
+ ui::Clipboard::kMimeTypeURIList)) {
+ item.stringData = WebString::fromUTF8("about:dragdrop-placeholder");
+ }
+ item_list.push_back(item);
+ continue;
+ }
- void OnMouseLockLost() override { webwidget_->didLosePointerLock(); }
+ // TODO(hush): crbug.com/584789. Blink needs to support creating a file with
+ // just the mimetype. This is needed to drag files to WebView on Android
+ // platform.
+ if ((meta_data_item.kind == DropData::Kind::FILENAME) &&
+ !meta_data_item.filename.empty()) {
+ WebDragData::Item item;
+ item.storageType = WebDragData::Item::StorageTypeFilename;
+ item.filenameData = meta_data_item.filename.AsUTF16Unsafe();
+ item_list.push_back(item);
+ continue;
+ }
- bool HandleMouseLockedInputEvent(const blink::WebMouseEvent& event) override {
- // The WebWidget handles mouse lock in WebKit's handleInputEvent().
- return false;
+ if (meta_data_item.kind == DropData::Kind::FILESYSTEMFILE) {
+ WebDragData::Item item;
+ item.storageType = WebDragData::Item::StorageTypeFileSystemFile;
+ item.fileSystemURL = meta_data_item.file_system_url;
+ item_list.push_back(item);
+ continue;
+ }
}
- private:
- blink::WebWidget* webwidget_;
-};
+ WebDragData result;
+ result.initialize();
+ result.setItems(item_list);
+ return result;
+}
WebDragData DropDataToWebDragData(const DropData& drop_data) {
std::vector<WebDragData::Item> item_list;
@@ -442,8 +455,6 @@ WebDragData DropDataToWebDragData(const DropData& drop_data) {
item_list.push_back(item);
}
- // TODO(dcheng): Do we need to distinguish between null and empty URLs? Is it
- // meaningful to write an empty URL to the clipboard?
if (!drop_data.url.is_empty()) {
WebDragData::Item item;
item.storageType = WebDragData::Item::StorageTypeString;
@@ -606,14 +617,19 @@ GetV8CacheStrategiesForCacheStorage() {
*base::CommandLine::ForCurrentProcess();
std::string v8_cache_strategies = command_line.GetSwitchValueASCII(
switches::kV8CacheStrategiesForCacheStorage);
- if (v8_cache_strategies.empty())
+ if (v8_cache_strategies.empty()) {
v8_cache_strategies =
base::FieldTrialList::FindFullName("V8CacheStrategiesForCacheStorage");
- if (v8_cache_strategies == "none") {
+ }
+
+ if (base::StartsWith(v8_cache_strategies, "none",
+ base::CompareCase::SENSITIVE)) {
return WebSettings::V8CacheStrategiesForCacheStorage::None;
- } else if (v8_cache_strategies == "normal") {
+ } else if (base::StartsWith(v8_cache_strategies, "normal",
+ base::CompareCase::SENSITIVE)) {
return WebSettings::V8CacheStrategiesForCacheStorage::Normal;
- } else if (v8_cache_strategies == "aggressive") {
+ } else if (base::StartsWith(v8_cache_strategies, "aggressive",
+ base::CompareCase::SENSITIVE)) {
return WebSettings::V8CacheStrategiesForCacheStorage::Aggressive;
} else {
return WebSettings::V8CacheStrategiesForCacheStorage::Default;
@@ -654,7 +670,6 @@ RenderViewImpl::RenderViewImpl(CompositorDependencies* compositor_deps,
main_render_frame_(nullptr),
frame_widget_(nullptr),
speech_recognition_dispatcher_(NULL),
- mouse_lock_dispatcher_(NULL),
#if defined(OS_ANDROID)
expected_content_intent_id_(0),
#endif
@@ -679,9 +694,10 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
// Ensure we start with a valid next_page_id_ from the browser.
DCHECK_GE(next_page_id_, 0);
- webview_ = WebView::create(this);
- webwidget_ = webview_->widget();
- webwidget_mouse_lock_target_.reset(new WebWidgetLockTarget(webwidget_));
+ webview_ =
+ WebView::create(this, is_hidden() ? blink::WebPageVisibilityStateHidden
+ : blink::WebPageVisibilityStateVisible);
+ RenderWidget::DoInit(MSG_ROUTING_NONE, webview_->widget(), nullptr);
g_view_map.Get().insert(std::make_pair(webview(), this));
g_routing_id_view_map.Get().insert(std::make_pair(GetRoutingID(), this));
@@ -709,6 +725,7 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
command_line.HasSwitch(switches::kRootLayerScrolls));
webview()->setShowFPSCounter(
command_line.HasSwitch(cc::switches::kShowFPSCounter));
+ webview()->setDeviceColorProfile(params.image_decode_color_profile);
ApplyWebPreferencesInternal(webkit_preferences_, webview(), compositor_deps_);
@@ -767,17 +784,6 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
content_detectors_.push_back(base::WrapUnique(new EmailDetector()));
#endif
- RenderThread::Get()->AddRoute(GetRoutingID(), this);
- // Take a reference on behalf of the RenderThread. This will be balanced
- // when we receive ViewMsg_Close in the RenderWidget (which RenderView
- // inherits from).
- AddRef();
- if (RenderThreadImpl::current()) {
- RenderThreadImpl::current()->WidgetCreated();
- if (is_hidden_)
- RenderThreadImpl::current()->WidgetHidden();
- }
-
// If this is a popup, we must wait for the CreatingNew_ACK message before
// completing initialization. Otherwise, we can finish it now.
if (opener_id_ == MSG_ROUTING_NONE)
@@ -809,10 +815,6 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
new TextInputClientObserver(this);
#endif // defined(OS_MACOSX)
- // The next group of objects all implement RenderViewObserver, so are deleted
- // along with the RenderView automatically.
- mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this);
-
// We don't use HistoryController in OOPIF-enabled modes.
if (!SiteIsolationPolicy::UseSubframeNavigationEntries())
history_controller_.reset(new HistoryController(this));
@@ -845,18 +847,9 @@ RenderViewImpl::~RenderViewImpl() {
++it)
delete it->second;
- // If file chooser is still waiting for answer, dispatch empty answer.
- while (!file_chooser_completions_.empty()) {
- if (file_chooser_completions_.front()->completion) {
- file_chooser_completions_.front()->completion->didChooseFile(
- WebVector<WebString>());
- }
- file_chooser_completions_.pop_front();
- }
-
#if defined(OS_ANDROID)
- // The date/time picker client is both a scoped_ptr member of this class and
- // a RenderViewObserver. Reset it to prevent double deletion.
+ // The date/time picker client is both a std::unique_ptr member of this class
+ // and a RenderViewObserver. Reset it to prevent double deletion.
date_time_picker_client_.reset();
#endif
@@ -1123,8 +1116,12 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
prefs.report_screen_size_in_physical_pixels_quirk);
settings->setShouldReuseGlobalForUnownedMainFrame(
prefs.resue_global_for_unowned_main_frame);
+ settings->setProgressBarCompletion(
+ static_cast<WebSettings::ProgressBarCompletion>(
+ prefs.progress_bar_completion));
settings->setPreferHiddenVolumeControls(true);
- settings->setShrinksViewportContentToFit(true);
+ WebRuntimeFeatures::enableAutoplayMutedVideos(
+ prefs.autoplay_muted_videos_enabled);
#endif
settings->setAutoplayExperimentMode(
@@ -1132,6 +1129,8 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->setViewportEnabled(prefs.viewport_enabled);
settings->setViewportMetaEnabled(prefs.viewport_meta_enabled);
+ settings->setShrinksViewportContentToFit(
+ prefs.shrinks_viewport_contents_to_fit);
settings->setViewportStyle(
static_cast<blink::WebViewportStyle>(prefs.viewport_style));
@@ -1144,13 +1143,13 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->setUseSolidColorScrollbars(prefs.use_solid_color_scrollbars);
settings->setShowContextMenuOnMouseUp(prefs.context_menu_on_mouse_up);
+ settings->setAlwaysShowContextMenuOnTouch(
+ prefs.always_show_context_menu_on_touch);
#if defined(OS_MACOSX)
settings->setDoubleTapToZoomEnabled(true);
web_view->setMaximumLegibleScale(prefs.default_maximum_page_scale_factor);
#endif
-
- settings->setWheelGesturesEnabled(UseGestureBasedWheelScrolling());
}
/*static*/
@@ -1288,8 +1287,6 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
OnScrollFocusedEditableNodeIntoRect)
IPC_MESSAGE_HANDLER(InputMsg_SetEditCommandsForNextKeyEvent,
OnSetEditCommandsForNextKeyEvent)
- IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
- IPC_MESSAGE_HANDLER(ViewMsg_SaveImageAt, OnSaveImageAt)
IPC_MESSAGE_HANDLER(ViewMsg_SetPageScale, OnSetPageScale)
IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL,
@@ -1310,7 +1307,6 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
IPC_MESSAGE_HANDLER(ViewMsg_EnumerateDirectoryResponse,
OnEnumerateDirectoryResponse)
- IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
@@ -1339,6 +1335,9 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(PageMsg_UpdateWindowScreenRect,
OnUpdateWindowScreenRect)
IPC_MESSAGE_HANDLER(PageMsg_SetZoomLevel, OnSetZoomLevel)
+ IPC_MESSAGE_HANDLER(PageMsg_WasHidden, OnPageWasHidden)
+ IPC_MESSAGE_HANDLER(PageMsg_WasShown, OnPageWasShown)
+
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState,
OnUpdateTopControlsState)
@@ -1367,14 +1366,6 @@ void RenderViewImpl::OnSelectWordAroundCaret() {
input_handler_->set_handling_input_event(false);
}
-void RenderViewImpl::OnCopyImageAt(int x, int y) {
- webview()->copyImageAt(WebPoint(x, y));
-}
-
-void RenderViewImpl::OnSaveImageAt(int x, int y) {
- webview()->saveImageAt(WebPoint(x, y));
-}
-
void RenderViewImpl::OnUpdateTargetURLAck() {
// Check if there is a targeturl waiting to be sent.
if (target_url_status_ == TARGET_PENDING)
@@ -1409,15 +1400,12 @@ void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
return;
}
- blink::WebElement element = GetFocusedElement();
- bool will_animate = false;
- if (!element.isNull() && element.isEditable()) {
- rect_for_scrolled_focused_editable_node_ = rect;
- has_scrolled_focused_editable_node_into_rect_ = true;
- will_animate = webview()->scrollFocusedNodeIntoRect(rect);
- }
+ if (!webview()->scrollFocusedEditableElementIntoRect(rect))
+ return;
- if (!will_animate)
+ rect_for_scrolled_focused_editable_node_ = rect;
+ has_scrolled_focused_editable_node_into_rect_ = true;
+ if (!compositor()->hasPendingPageScaleAnimation())
GetWidget()->FocusChangeComplete();
}
@@ -1624,14 +1612,6 @@ void RenderViewImpl::printPage(WebLocalFrame* frame) {
PrintPage(frame, input_handler().handling_input_event()));
}
-void RenderViewImpl::saveImageFromDataURL(const blink::WebString& data_url) {
- // Note: We should basically send GURL but we use size-limited string instead
- // in order to send a larger data url to save a image for <canvas> or <img>.
- if (data_url.length() < kMaxLengthOfDataURLString)
- Send(new ViewHostMsg_SaveImageFromDataURL(
- GetRoutingID(), GetMainRenderFrame()->GetRoutingID(), data_url.utf8()));
-}
-
bool RenderViewImpl::enumerateChosenDirectory(
const WebString& path,
WebFileChooserCompletion* chooser_completion) {
@@ -1704,36 +1684,6 @@ bool RenderViewImpl::handleCurrentKeyboardEvent() {
return did_execute_command;
}
-bool RenderViewImpl::runFileChooser(
- const blink::WebFileChooserParams& params,
- WebFileChooserCompletion* chooser_completion) {
- // Do not open the file dialog in a hidden RenderView.
- if (is_hidden())
- return false;
- FileChooserParams ipc_params;
- if (params.directory)
- ipc_params.mode = FileChooserParams::UploadFolder;
- else if (params.multiSelect)
- ipc_params.mode = FileChooserParams::OpenMultiple;
- else if (params.saveAs)
- ipc_params.mode = FileChooserParams::Save;
- else
- ipc_params.mode = FileChooserParams::Open;
- ipc_params.title = params.title;
- ipc_params.default_file_name =
- blink::WebStringToFilePath(params.initialValue).BaseName();
- ipc_params.accept_types.reserve(params.acceptTypes.size());
- for (size_t i = 0; i < params.acceptTypes.size(); ++i)
- ipc_params.accept_types.push_back(params.acceptTypes[i]);
- ipc_params.need_local_path = params.needLocalPath;
-#if defined(OS_ANDROID)
- ipc_params.capture = params.useMediaCapture;
-#endif
- ipc_params.requestor = params.requestor;
-
- return ScheduleFileChooser(ipc_params, chooser_completion);
-}
-
void RenderViewImpl::SetValidationMessageDirection(
base::string16* wrapped_main_text,
blink::WebTextDirection main_text_hint,
@@ -1994,19 +1944,6 @@ void RenderViewImpl::show(WebNavigationPolicy policy) {
SetPendingWindowRect(initial_rect_);
}
-bool RenderViewImpl::requestPointerLock() {
- return mouse_lock_dispatcher_->LockMouse(webwidget_mouse_lock_target_.get());
-}
-
-void RenderViewImpl::requestPointerUnlock() {
- mouse_lock_dispatcher_->UnlockMouse(webwidget_mouse_lock_target_.get());
-}
-
-bool RenderViewImpl::isPointerLocked() {
- return mouse_lock_dispatcher_->IsMouseLockedTo(
- webwidget_mouse_lock_target_.get());
-}
-
void RenderViewImpl::onMouseDown(const WebNode& mouse_down_node) {
FOR_EACH_OBSERVER(
RenderViewObserver, observers_, OnMouseDown(mouse_down_node));
@@ -2062,8 +1999,7 @@ void RenderViewImpl::initializeLayerTreeView() {
if (input_handler_manager) {
input_handler_manager->AddInputHandler(
GetRoutingID(), rwc->GetInputHandler(), AsWeakPtr(),
- webkit_preferences_.enable_scroll_animator,
- UseGestureBasedWheelScrolling());
+ webkit_preferences_.enable_scroll_animator);
has_added_input_handler_ = true;
}
}
@@ -2320,10 +2256,6 @@ bool RenderViewImpl::GetContentStateImmediately() const {
return send_content_state_immediately_;
}
-blink::WebPageVisibilityState RenderViewImpl::GetVisibilityState() const {
- return visibilityState();
-}
-
void RenderViewImpl::DidStartLoading() {
main_render_frame_->didStartLoading(true);
}
@@ -2332,19 +2264,6 @@ void RenderViewImpl::DidStopLoading() {
main_render_frame_->didStopLoading();
}
-blink::WebElement RenderViewImpl::GetFocusedElement() const {
- if (!webview())
- return WebElement();
- WebFrame* focused_frame = webview()->focusedFrame();
- if (focused_frame) {
- WebDocument doc = focused_frame->document();
- if (!doc.isNull())
- return doc.focusedElement();
- }
-
- return WebElement();
-}
-
void RenderViewImpl::OnSetPageScale(float page_scale_factor) {
if (!webview())
return;
@@ -2444,17 +2363,15 @@ void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags) {
main_render_frame_->MaybeEnableMojoBindings();
}
-void RenderViewImpl::OnDragTargetDragEnter(const DropData& drop_data,
- const gfx::Point& client_point,
- const gfx::Point& screen_point,
- WebDragOperationsMask ops,
- int key_modifiers) {
+void RenderViewImpl::OnDragTargetDragEnter(
+ const std::vector<DropData::Metadata>& drop_meta_data,
+ const gfx::Point& client_point,
+ const gfx::Point& screen_point,
+ WebDragOperationsMask ops,
+ int key_modifiers) {
WebDragOperation operation = webview()->dragTargetDragEnter(
- DropDataToWebDragData(drop_data),
- ConvertWindowPointToViewport(client_point),
- screen_point,
- ops,
- key_modifiers);
+ DropMetaDataToWebDragData(drop_meta_data), client_point, screen_point,
+ ops, key_modifiers);
Send(new DragHostMsg_UpdateDragCursor(GetRoutingID(), operation));
}
@@ -2476,11 +2393,12 @@ void RenderViewImpl::OnDragTargetDragLeave() {
webview()->dragTargetDragLeave();
}
-void RenderViewImpl::OnDragTargetDrop(const gfx::Point& client_point,
+void RenderViewImpl::OnDragTargetDrop(const DropData& drop_data,
+ const gfx::Point& client_point,
const gfx::Point& screen_point,
int key_modifiers) {
- webview()->dragTargetDrop(
- ConvertWindowPointToViewport(client_point), screen_point, key_modifiers);
+ webview()->dragTargetDrop(DropDataToWebDragData(drop_data), client_point,
+ screen_point, key_modifiers);
}
void RenderViewImpl::OnDragSourceEnded(const gfx::Point& client_point,
@@ -2513,42 +2431,6 @@ void RenderViewImpl::OnEnumerateDirectoryResponse(
enumeration_completions_.erase(id);
}
-void RenderViewImpl::OnFileChooserResponse(
- const std::vector<content::FileChooserFileInfo>& files) {
- // This could happen if we navigated to a different page before the user
- // closed the chooser.
- if (file_chooser_completions_.empty())
- return;
-
- // Convert Chrome's SelectedFileInfo list to WebKit's.
- WebVector<WebFileChooserCompletion::SelectedFileInfo> selected_files(
- files.size());
- for (size_t i = 0; i < files.size(); ++i) {
- WebFileChooserCompletion::SelectedFileInfo selected_file;
- selected_file.path = files[i].file_path.AsUTF16Unsafe();
- selected_file.displayName =
- base::FilePath(files[i].display_name).AsUTF16Unsafe();
- if (files[i].file_system_url.is_valid()) {
- selected_file.fileSystemURL = files[i].file_system_url;
- selected_file.length = files[i].length;
- selected_file.modificationTime = files[i].modification_time.ToDoubleT();
- selected_file.isDirectory = files[i].is_directory;
- }
- selected_files[i] = selected_file;
- }
-
- if (file_chooser_completions_.front()->completion)
- file_chooser_completions_.front()->completion->didChooseFile(
- selected_files);
- file_chooser_completions_.pop_front();
-
- // If there are more pending file chooser requests, schedule one now.
- if (!file_chooser_completions_.empty()) {
- Send(new ViewHostMsg_RunFileChooser(
- GetRoutingID(), file_chooser_completions_.front()->params));
- }
-}
-
void RenderViewImpl::OnEnableAutoResize(const gfx::Size& min_size,
const gfx::Size& max_size) {
DCHECK(disable_scrollbars_size_limit_.IsEmpty());
@@ -2698,7 +2580,8 @@ void RenderViewImpl::OnResize(const ResizeParams& params) {
TRACE_EVENT0("renderer", "RenderViewImpl::OnResize");
if (webview()) {
webview()->hidePopups();
- if (send_preferred_size_changes_) {
+ if (send_preferred_size_changes_ &&
+ webview()->mainFrame()->isWebLocalFrame()) {
webview()->mainFrame()->setCanHaveScrollbars(
ShouldDisplayScrollbars(params.new_size.width(),
params.new_size.height()));
@@ -2800,9 +2683,7 @@ void RenderViewImpl::Close() {
RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID()));
}
-void RenderViewImpl::OnWasHidden() {
- RenderWidget::OnWasHidden();
-
+void RenderViewImpl::OnPageWasHidden() {
#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
RenderThreadImpl::current()->video_capture_impl_manager()->
SuspendDevices(true);
@@ -2810,21 +2691,30 @@ void RenderViewImpl::OnWasHidden() {
speech_recognition_dispatcher_->AbortAllRecognitions();
#endif
- if (webview())
- webview()->setVisibilityState(visibilityState(), false);
+ if (webview()) {
+ // TODO(lfg): It's not correct to defer the page visibility to the main
+ // frame. Currently, this is done because the main frame may override the
+ // visibility of the page when prerendering. In order to fix this,
+ // prerendering must be made aware of OOPIFs. https://crbug.com/440544
+ blink::WebPageVisibilityState visibilityState =
+ GetMainRenderFrame() ? GetMainRenderFrame()->visibilityState()
+ : blink::WebPageVisibilityStateHidden;
+ webview()->setVisibilityState(visibilityState, false);
+ }
}
-void RenderViewImpl::OnWasShown(bool needs_repainting,
- const ui::LatencyInfo& latency_info) {
- RenderWidget::OnWasShown(needs_repainting, latency_info);
-
+void RenderViewImpl::OnPageWasShown() {
#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
RenderThreadImpl::current()->video_capture_impl_manager()->
SuspendDevices(false);
#endif
- if (webview())
- webview()->setVisibilityState(visibilityState(), false);
+ if (webview()) {
+ blink::WebPageVisibilityState visibilityState =
+ GetMainRenderFrame() ? GetMainRenderFrame()->visibilityState()
+ : blink::WebPageVisibilityStateVisible;
+ webview()->setVisibilityState(visibilityState, false);
+ }
}
GURL RenderViewImpl::GetURLForGraphicsContext3D() {
@@ -3026,31 +2916,6 @@ void RenderViewImpl::SetScreenMetricsEmulationParameters(
}
}
-bool RenderViewImpl::ScheduleFileChooser(
- const FileChooserParams& params,
- WebFileChooserCompletion* completion) {
- static const size_t kMaximumPendingFileChooseRequests = 4;
- if (file_chooser_completions_.size() > kMaximumPendingFileChooseRequests) {
- // This sanity check prevents too many file choose requests from getting
- // queued which could DoS the user. Getting these is most likely a
- // programming error (there are many ways to DoS the user so it's not
- // considered a "real" security check), either in JS requesting many file
- // choosers to pop up, or in a plugin.
- //
- // TODO(brettw) we might possibly want to require a user gesture to open
- // a file picker, which will address this issue in a better way.
- return false;
- }
-
- file_chooser_completions_.push_back(
- base::WrapUnique(new PendingFileChooser(params, completion)));
- if (file_chooser_completions_.size() == 1) {
- // Actually show the browse dialog when this is the first request.
- Send(new ViewHostMsg_RunFileChooser(GetRoutingID(), params));
- }
- return true;
-}
-
blink::WebSpeechRecognizer* RenderViewImpl::speechRecognizer() {
if (!speech_recognition_dispatcher_)
speech_recognition_dispatcher_ = new SpeechRecognitionDispatcher(this);
@@ -3100,19 +2965,6 @@ double RenderViewImpl::zoomFactorToZoomLevel(double factor) const {
return ZoomFactorToZoomLevel(factor);
}
-blink::WebPageVisibilityState RenderViewImpl::visibilityState() const {
- blink::WebPageVisibilityState current_state = is_hidden() ?
- blink::WebPageVisibilityStateHidden :
- blink::WebPageVisibilityStateVisible;
- blink::WebPageVisibilityState override_state = current_state;
- // TODO(jam): move this method to WebFrameClient.
- if (GetContentClient()->renderer()->
- ShouldOverridePageVisibilityState(main_render_frame_,
- &override_state))
- return override_state;
- return current_state;
-}
-
void RenderViewImpl::draggableRegionsChanged() {
FOR_EACH_OBSERVER(
RenderViewObserver,
@@ -3153,7 +3005,7 @@ WebContentDetectionResult RenderViewImpl::detectContentAround(
void RenderViewImpl::scheduleContentIntent(const WebURL& intent,
bool is_main_frame) {
// Introduce a short delay so that the user can notice the content.
- base::MessageLoop::current()->PostDelayedTask(
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::Bind(&RenderViewImpl::LaunchAndroidContentIntent, AsWeakPtr(),
intent, expected_content_intent_id_, is_main_frame),
diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h
index 8d292c2c9d1..1ebdb174b2e 100644
--- a/chromium/content/renderer/render_view_impl.h
+++ b/chromium/content/renderer/render_view_impl.h
@@ -33,19 +33,18 @@
#include "content/common/navigation_gesture.h"
#include "content/common/page_message_enums.h"
#include "content/common/view_message_enums.h"
+#include "content/public/common/drop_data.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/referrer.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/common/top_controls_state.h"
#include "content/public/common/web_preferences.h"
#include "content/public/renderer/render_view.h"
-#include "content/renderer/mouse_lock_dispatcher.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_widget.h"
#include "content/renderer/render_widget_owner_delegate.h"
#include "content/renderer/stats_collection_observer.h"
#include "ipc/ipc_platform_file.h"
-#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
@@ -121,7 +120,6 @@ namespace content {
class HistoryController;
class HistoryEntry;
-class MouseLockDispatcher;
class PageState;
class RenderViewImplTest;
class RenderViewObserver;
@@ -130,7 +128,6 @@ class RendererDateTimePicker;
class RendererWebColorChooserImpl;
class SpeechRecognitionDispatcher;
class WebPluginDelegateProxy;
-struct DropData;
struct FaviconURL;
struct FileChooserParams;
struct FileChooserFileInfo;
@@ -194,10 +191,6 @@ class CONTENT_EXPORT RenderViewImpl
send_content_state_immediately_ = value;
}
- MouseLockDispatcher* mouse_lock_dispatcher() {
- return mouse_lock_dispatcher_;
- }
-
HistoryController* history_controller() {
return history_controller_.get();
}
@@ -293,9 +286,6 @@ class CONTENT_EXPORT RenderViewImpl
// Most methods are handled by RenderWidget.
void didFocus() override;
void show(blink::WebNavigationPolicy policy) override;
- bool requestPointerLock() override;
- void requestPointerUnlock() override;
- bool isPointerLocked() override;
void didHandleGestureEvent(const blink::WebGestureEvent& event,
bool event_cancelled) override;
void onMouseDown(const blink::WebNode& mouse_down_node) override;
@@ -347,12 +337,8 @@ class CONTENT_EXPORT RenderViewImpl
bool enumerateChosenDirectory(
const blink::WebString& path,
blink::WebFileChooserCompletion* chooser_completion) override;
- void saveImageFromDataURL(const blink::WebString& data_url) override;
void didCancelCompositionOnSelectionChange() override;
bool handleCurrentKeyboardEvent() override;
- bool runFileChooser(
- const blink::WebFileChooserParams& params,
- blink::WebFileChooserCompletion* chooser_completion) override;
void SetValidationMessageDirection(base::string16* main_text,
blink::WebTextDirection main_text_hint,
base::string16* sub_text,
@@ -395,7 +381,6 @@ class CONTENT_EXPORT RenderViewImpl
void pageScaleFactorChanged() override;
virtual double zoomLevelToZoomFactor(double zoom_level) const;
virtual double zoomFactorToZoomLevel(double factor) const;
- blink::WebPageVisibilityState visibilityState() const override;
void draggableRegionsChanged() override;
void pageImportanceSignalsChanged() override;
@@ -428,7 +413,6 @@ class CONTENT_EXPORT RenderViewImpl
bool ShouldDisplayScrollbars(int width, int height) const override;
int GetEnabledBindings() const override;
bool GetContentStateImmediately() const override;
- blink::WebPageVisibilityState GetVisibilityState() const override;
void DidStartLoading() override;
void DidStopLoading() override;
void Repaint(const gfx::Size& size) override;
@@ -461,9 +445,6 @@ class CONTENT_EXPORT RenderViewImpl
void Close() override;
void OnResize(const ResizeParams& params) override;
void OnSetFocus(bool enable) override;
- void OnWasHidden() override;
- void OnWasShown(bool needs_repainting,
- const ui::LatencyInfo& latency_info) override;
GURL GetURLForGraphicsContext3D() override;
void OnImeSetComposition(
const base::string16& text,
@@ -620,8 +601,6 @@ class CONTENT_EXPORT RenderViewImpl
void OnShowContextMenu(ui::MenuSourceType source_type,
const gfx::Point& location);
- void OnCopyImageAt(int x, int y);
- void OnSaveImageAt(int x, int y);
void OnDeterminePageLanguage();
void OnDisableScrollbarsForSmallWindows(
const gfx::Size& disable_scrollbars_size_limit);
@@ -629,14 +608,17 @@ class CONTENT_EXPORT RenderViewImpl
const gfx::Point& screen_point,
blink::WebDragOperation drag_operation);
void OnDragSourceSystemDragEnded();
- void OnDragTargetDrop(const gfx::Point& client_pt,
+ void OnDragTargetDrop(const DropData& drop_data,
+ const gfx::Point& client_pt,
const gfx::Point& screen_pt,
int key_modifiers);
- void OnDragTargetDragEnter(const DropData& drop_data,
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- blink::WebDragOperationsMask operations_allowed,
- int key_modifiers);
+ // Real data that is dragged is not included at DragEnter time.
+ void OnDragTargetDragEnter(
+ const std::vector<DropData::Metadata>& drop_meta_data,
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ blink::WebDragOperationsMask operations_allowed,
+ int key_modifiers);
void OnDragTargetDragLeave();
void OnDragTargetDragOver(const gfx::Point& client_pt,
const gfx::Point& screen_pt,
@@ -647,8 +629,6 @@ class CONTENT_EXPORT RenderViewImpl
void OnDisableAutoResize(const gfx::Size& new_size);
void OnEnumerateDirectoryResponse(int id,
const std::vector<base::FilePath>& paths);
- void OnFileChooserResponse(
- const std::vector<content::FileChooserFileInfo>& files);
void OnMediaPlayerActionAt(const gfx::Point& location,
const blink::WebMediaPlayerAction& action);
void OnPluginActionAt(const gfx::Point& location,
@@ -686,6 +666,8 @@ class CONTENT_EXPORT RenderViewImpl
// Page message handlers -----------------------------------------------------
void OnUpdateWindowScreenRect(gfx::Rect window_screen_rect);
void OnSetZoomLevel(PageMsg_SetZoomLevel_Command command, double zoom_level);
+ void OnPageWasHidden();
+ void OnPageWasShown();
// Adding a new message handler? Please add it in alphabetical order above
// and put it in the same position in the .cc file.
@@ -694,9 +676,6 @@ class CONTENT_EXPORT RenderViewImpl
// Check whether the preferred size has changed.
void CheckPreferredSize();
- // Gets the currently focused element, if any.
- blink::WebElement GetFocusedElement() const;
-
#if defined(OS_ANDROID)
// Launch an Android content intent with the given URL.
void LaunchAndroidContentIntent(const GURL& intent_url,
@@ -904,9 +883,6 @@ class CONTENT_EXPORT RenderViewImpl
// initialized.
SpeechRecognitionDispatcher* speech_recognition_dispatcher_;
- // Mouse Lock dispatcher attached to this view.
- MouseLockDispatcher* mouse_lock_dispatcher_;
-
std::unique_ptr<HistoryController> history_controller_;
#if defined(OS_ANDROID)
@@ -926,13 +902,6 @@ class CONTENT_EXPORT RenderViewImpl
// Misc ----------------------------------------------------------------------
- // The current and pending file chooser completion objects. If the queue is
- // nonempty, the first item represents the currently running file chooser
- // callback, and the remaining elements are the other file chooser completion
- // still waiting to be run (in order).
- struct PendingFileChooser;
- std::deque<std::unique_ptr<PendingFileChooser>> file_chooser_completions_;
-
// The current directory enumeration callback
std::map<int, blink::WebFileChooserCompletion*> enumeration_completions_;
int enumeration_completion_id_;
@@ -950,9 +919,6 @@ class CONTENT_EXPORT RenderViewImpl
// is fine.
base::ObserverList<RenderViewObserver> observers_;
- // Wraps the |webwidget_| as a MouseLockDispatcher::LockTarget interface.
- std::unique_ptr<MouseLockDispatcher::LockTarget> webwidget_mouse_lock_target_;
-
// This field stores drag/drop related info for the event that is currently
// being handled. If the current event results in starting a drag/drop
// session, this info is sent to the browser along with other drag/drop info.
diff --git a/chromium/content/renderer/render_view_mouse_lock_dispatcher.h b/chromium/content/renderer/render_view_mouse_lock_dispatcher.h
deleted file mode 100644
index 984a40e0984..00000000000
--- a/chromium/content/renderer/render_view_mouse_lock_dispatcher.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_RENDER_VIEW_MOUSE_LOCK_DISPATCHER_H_
-#define CONTENT_RENDERER_RENDER_VIEW_MOUSE_LOCK_DISPATCHER_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "content/renderer/mouse_lock_dispatcher.h"
-
-namespace content {
-class RenderViewImpl;
-
-// RenderViewMouseLockDispatcher is owned by RenderViewImpl.
-class RenderViewMouseLockDispatcher : public MouseLockDispatcher,
- public RenderViewObserver {
- public:
- explicit RenderViewMouseLockDispatcher(RenderViewImpl* render_view_impl);
- ~RenderViewMouseLockDispatcher() override;
-
- private:
- // MouseLockDispatcher implementation.
- void SendLockMouseRequest(bool unlocked_by_target) override;
- void SendUnlockMouseRequest() override;
-
- // RenderView::Observer implementation.
- bool OnMessageReceived(const IPC::Message& message) override;
-
- void OnLockMouseACK(bool succeeded);
-
- RenderViewImpl* render_view_impl_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderViewMouseLockDispatcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_RENDER_VIEW_MOUSE_LOCK_DISPATCHER_H_
diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc
index 66a8ecc0355..129ed07f6eb 100644
--- a/chromium/content/renderer/render_widget.cc
+++ b/chromium/content/renderer/render_widget.cc
@@ -23,17 +23,11 @@
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_synthetic_delay.h"
#include "build/build_config.h"
-#include "cc/base/switches.h"
-#include "cc/debug/benchmark_instrumentation.h"
#include "cc/output/output_surface.h"
-#include "cc/output/vulkan_in_process_context_provider.h"
#include "cc/scheduler/begin_frame_source.h"
-#include "cc/trees/layer_tree_host.h"
#include "components/scheduler/renderer/render_widget_scheduling_state.h"
#include "components/scheduler/renderer/renderer_scheduler.h"
#include "content/common/content_switches_internal.h"
-#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu_process_launch_causes.h"
#include "content/common/input/synthetic_gesture_packet.h"
#include "content/common/input/web_input_event_traits.h"
#include "content/common/input_messages.h"
@@ -46,10 +40,7 @@
#include "content/renderer/cursor_utils.h"
#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h"
#include "content/renderer/external_popup_menu.h"
-#include "content/renderer/gpu/compositor_output_surface.h"
-#include "content/renderer/gpu/delegated_compositor_output_surface.h"
#include "content/renderer/gpu/frame_swap_message_queue.h"
-#include "content/renderer/gpu/mailbox_output_surface.h"
#include "content/renderer/gpu/queue_message_swap_promise.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/ime_event_guard.h"
@@ -63,7 +54,6 @@
#include "content/renderer/render_widget_owner_delegate.h"
#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/resizing_mode_selector.h"
-#include "gpu/command_buffer/client/shared_memory_limits.h"
#include "ipc/ipc_sync_message.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
@@ -93,8 +83,6 @@
#if defined(OS_ANDROID)
#include <android/keycodes.h>
-#include "content/renderer/android/synchronous_compositor_filter.h"
-#include "content/renderer/android/synchronous_compositor_output_surface.h"
#endif
#if defined(OS_POSIX)
@@ -140,6 +128,29 @@ namespace {
typedef std::map<std::string, ui::TextInputMode> TextInputModeMap;
+class WebWidgetLockTarget : public content::MouseLockDispatcher::LockTarget {
+ public:
+ explicit WebWidgetLockTarget(blink::WebWidget* webwidget)
+ : webwidget_(webwidget) {}
+
+ void OnLockMouseACK(bool succeeded) override {
+ if (succeeded)
+ webwidget_->didAcquirePointerLock();
+ else
+ webwidget_->didNotAcquirePointerLock();
+ }
+
+ void OnMouseLockLost() override { webwidget_->didLosePointerLock(); }
+
+ bool HandleMouseLockedInputEvent(const blink::WebMouseEvent& event) override {
+ // The WebWidget handles mouse lock in Blink's handleInputEvent().
+ return false;
+ }
+
+ private:
+ blink::WebWidget* webwidget_;
+};
+
class TextInputModeMapSingleton {
public:
static TextInputModeMapSingleton* GetInstance() {
@@ -189,7 +200,7 @@ content::RenderWidgetInputHandlerDelegate* GetRenderWidgetInputHandlerDelegate(
content::RenderWidget* widget) {
#if defined(MOJO_SHELL_CLIENT)
const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess();
- if (content::MojoShellConnection::Get() &&
+ if (content::MojoShellConnection::GetForProcess() &&
cmdline.HasSwitch(switches::kUseMusInRenderer)) {
return content::RenderWidgetMusConnection::GetOrCreate(
widget->routing_id());
@@ -239,7 +250,6 @@ RenderWidget::RenderWidget(CompositorDependencies* compositor_deps,
pending_window_rect_count_(0),
screen_info_(screen_info),
device_scale_factor_(screen_info_.deviceScaleFactor),
- next_output_surface_id_(0),
#if defined(OS_ANDROID)
text_field_is_dirty_(false),
#endif
@@ -374,6 +384,8 @@ bool RenderWidget::DoInit(int32_t opener_id,
opener_id_ = opener_id;
webwidget_ = web_widget;
+ webwidget_mouse_lock_target_.reset(new WebWidgetLockTarget(webwidget_));
+ mouse_lock_dispatcher_.reset(new RenderWidgetMouseLockDispatcher(this));
bool result = true;
if (create_widget_message)
@@ -435,7 +447,7 @@ gfx::Rect RenderWidget::AdjustValidationMessageAnchor(const gfx::Rect& anchor) {
return anchor;
}
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
void RenderWidget::SetExternalPopupOriginAdjustmentsForEmulation(
ExternalPopupMenu* popup,
RenderWidgetScreenMetricsEmulator* emulator) {
@@ -450,6 +462,10 @@ void RenderWidget::OnShowHostContextMenu(ContextMenuParams* params) {
}
bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
+ if (mouse_lock_dispatcher_ &&
+ mouse_lock_dispatcher_->OnMessageReceived(message))
+ return true;
+
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidget, message)
IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnHandleInputEvent)
@@ -467,7 +483,6 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
OnEnableDeviceEmulation)
IPC_MESSAGE_HANDLER(ViewMsg_DisableDeviceEmulation,
OnDisableDeviceEmulation)
- IPC_MESSAGE_HANDLER(ViewMsg_ColorProfile, OnColorProfile)
IPC_MESSAGE_HANDLER(ViewMsg_ChangeResizeRect, OnChangeResizeRect)
IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
IPC_MESSAGE_HANDLER(ViewMsg_WasShown, OnWasShown)
@@ -596,10 +611,6 @@ void RenderWidget::OnDisableDeviceEmulation() {
screen_metrics_emulator_.reset();
}
-void RenderWidget::OnColorProfile(const std::vector<char>& color_profile) {
- SetDeviceColorProfile(color_profile);
-}
-
void RenderWidget::OnChangeResizeRect(const gfx::Rect& resizer_rect) {
if (resizer_rect_ == resizer_rect)
return;
@@ -704,119 +715,9 @@ std::unique_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(
// For widgets that are never visible, we don't start the compositor, so we
// never get a request for a cc::OutputSurface.
DCHECK(!compositor_never_visible_);
-
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- bool use_software = fallback;
- if (command_line.HasSwitch(switches::kDisableGpuCompositing))
- use_software = true;
-
-#if defined(MOJO_SHELL_CLIENT)
- if (MojoShellConnection::Get() && !use_software &&
- command_line.HasSwitch(switches::kUseMusInRenderer)) {
- RenderWidgetMusConnection* connection =
- RenderWidgetMusConnection::GetOrCreate(routing_id());
- return connection->CreateOutputSurface();
- }
-#endif
-
- uint32_t output_surface_id = next_output_surface_id_++;
-
- if (command_line.HasSwitch(switches::kEnableVulkan)) {
- scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider =
- cc::VulkanInProcessContextProvider::Create();
- if (vulkan_context_provider) {
- return base::WrapUnique(new DelegatedCompositorOutputSurface(
- routing_id(), output_surface_id, nullptr, nullptr,
- vulkan_context_provider, frame_swap_message_queue_));
- }
- }
-
- // Create a gpu process channel and verify we want to use GPU compositing
- // before creating any context providers.
- scoped_refptr<gpu::GpuChannelHost> gpu_channel_host;
- if (!use_software) {
- gpu_channel_host = RenderThreadImpl::current()->EstablishGpuChannelSync(
- CAUSE_FOR_GPU_LAUNCH_RENDERER_VERIFY_GPU_COMPOSITING);
- if (!gpu_channel_host) {
- // Cause the compositor to wait and try again.
- return nullptr;
- }
- // We may get a valid channel, but with a software renderer. In that case,
- // disable GPU compositing.
- if (gpu_channel_host->gpu_info().software_rendering)
- use_software = true;
- }
-
- if (use_software) {
- return base::WrapUnique(new DelegatedCompositorOutputSurface(
- routing_id(), output_surface_id, nullptr, nullptr, nullptr,
- frame_swap_message_queue_));
- }
-
- scoped_refptr<ContextProviderCommandBuffer> worker_context_provider =
- RenderThreadImpl::current()->SharedCompositorWorkerContextProvider();
- if (!worker_context_provider) {
- // Cause the compositor to wait and try again.
- return nullptr;
- }
-
- // The renderer compositor context doesn't do a lot of stuff, so we don't
- // expect it to need a lot of space for commands or transfer. Raster and
- // uploads happen on the worker context instead.
- gpu::SharedMemoryLimits limits = gpu::SharedMemoryLimits::ForMailboxContext();
-
- // This is for an offscreen context for the compositor. So the default
- // framebuffer doesn't need alpha, depth, stencil, antialiasing.
- gpu::gles2::ContextCreationAttribHelper attributes;
- attributes.alpha_size = -1;
- attributes.depth_size = 0;
- attributes.stencil_size = 0;
- attributes.samples = 0;
- attributes.sample_buffers = 0;
- attributes.bind_generates_resource = false;
- attributes.lose_context_when_out_of_memory = true;
-
- constexpr bool automatic_flushes = false;
- constexpr bool support_locking = false;
-
- // The compositor context shares resources with the worker context unless
- // the worker is async.
- ContextProviderCommandBuffer* share_context = worker_context_provider.get();
- if (compositor_deps_->IsAsyncWorkerContextEnabled())
- share_context = nullptr;
-
- scoped_refptr<ContextProviderCommandBuffer> context_provider(
- new ContextProviderCommandBuffer(
- std::move(gpu_channel_host), gpu::GPU_STREAM_DEFAULT,
- gpu::GpuStreamPriority::NORMAL, gpu::kNullSurfaceHandle,
- GetURLForGraphicsContext3D(), gfx::PreferIntegratedGpu,
- automatic_flushes, support_locking, limits, attributes, share_context,
- command_buffer_metrics::RENDER_COMPOSITOR_CONTEXT));
-
-#if defined(OS_ANDROID)
- if (RenderThreadImpl::current()->sync_compositor_message_filter()) {
- return base::WrapUnique(new SynchronousCompositorOutputSurface(
- context_provider, worker_context_provider, routing_id(),
- output_surface_id,
- RenderThreadImpl::current()->sync_compositor_message_filter(),
- frame_swap_message_queue_));
- }
-#endif
-
- // Composite-to-mailbox is currently used for layout tests in order to cause
- // them to draw inside in the renderer to do the readback there. This should
- // no longer be the case when crbug.com/311404 is fixed.
- if (RenderThreadImpl::current()->layout_test_mode()) {
- return base::WrapUnique(new MailboxOutputSurface(
- routing_id(), output_surface_id, std::move(context_provider),
- std::move(worker_context_provider), frame_swap_message_queue_,
- cc::RGBA_8888));
- }
-
- return base::WrapUnique(new DelegatedCompositorOutputSurface(
- routing_id(), output_surface_id, std::move(context_provider),
- std::move(worker_context_provider), nullptr, frame_swap_message_queue_));
+ return RenderThreadImpl::current()->CreateCompositorOutputSurface(
+ fallback, routing_id_, frame_swap_message_queue_,
+ GetURLForGraphicsContext3D());
}
std::unique_ptr<cc::BeginFrameSource>
@@ -915,13 +816,6 @@ void RenderWidget::WillBeginCompositorFrame() {
WillBeginCompositorFrame());
}
-void RenderWidget::ReportFixedRasterScaleUseCounters(
- bool has_blurry_content,
- bool has_potential_performance_regression) {
- webwidget_->reportFixedRasterScaleUseCounters(
- has_blurry_content, has_potential_performance_regression);
-}
-
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetInputHandlerDelegate
@@ -937,27 +831,6 @@ bool RenderWidget::HasTouchEventHandlersAt(const gfx::Point& point) const {
return true;
}
-void RenderWidget::ObserveWheelEventAndResult(
- const blink::WebMouseWheelEvent& wheel_event,
- const gfx::Vector2dF& wheel_unused_delta,
- bool event_processed) {
- if (!compositor_deps_->IsElasticOverscrollEnabled())
- return;
-
- cc::InputHandlerScrollResult scroll_result;
- scroll_result.did_scroll = event_processed;
- scroll_result.did_overscroll_root = !wheel_unused_delta.IsZero();
- scroll_result.unused_scroll_delta = wheel_unused_delta;
-
- RenderThreadImpl* render_thread = RenderThreadImpl::current();
- InputHandlerManager* input_handler_manager =
- render_thread ? render_thread->input_handler_manager() : NULL;
- if (input_handler_manager) {
- input_handler_manager->ObserveWheelEventAndResultOnMainThread(
- routing_id_, wheel_event, scroll_result);
- }
-}
-
void RenderWidget::ObserveGestureEventAndResult(
const blink::WebGestureEvent& gesture_event,
const gfx::Vector2dF& unused_delta,
@@ -2099,4 +1972,17 @@ float RenderWidget::GetOriginalDeviceScaleFactor() const {
device_scale_factor_;
}
+bool RenderWidget::requestPointerLock() {
+ return mouse_lock_dispatcher_->LockMouse(webwidget_mouse_lock_target_.get());
+}
+
+void RenderWidget::requestPointerUnlock() {
+ mouse_lock_dispatcher_->UnlockMouse(webwidget_mouse_lock_target_.get());
+}
+
+bool RenderWidget::isPointerLocked() {
+ return mouse_lock_dispatcher_->IsMouseLockedTo(
+ webwidget_mouse_lock_target_.get());
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h
index 181222d7c44..8cb0010653d 100644
--- a/chromium/content/renderer/render_widget.h
+++ b/chromium/content/renderer/render_widget.h
@@ -27,6 +27,8 @@
#include "content/renderer/input/render_widget_input_handler.h"
#include "content/renderer/input/render_widget_input_handler_delegate.h"
#include "content/renderer/message_delivery_policy.h"
+#include "content/renderer/mouse_lock_dispatcher.h"
+#include "content/renderer/render_widget_mouse_lock_dispatcher.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "third_party/WebKit/public/platform/WebDisplayMode.h"
@@ -39,7 +41,6 @@
#include "third_party/WebKit/public/web/WebTouchAction.h"
#include "third_party/WebKit/public/web/WebWidget.h"
#include "third_party/WebKit/public/web/WebWidgetClient.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ui_base_types.h"
@@ -202,16 +203,10 @@ class CONTENT_EXPORT RenderWidget
void RequestScheduleAnimation() override;
void UpdateVisualState() override;
void WillBeginCompositorFrame() override;
- void ReportFixedRasterScaleUseCounters(
- bool has_blurry_content,
- bool has_potential_performance_regression) override;
// RenderWidgetInputHandlerDelegate
void FocusChangeComplete() override;
bool HasTouchEventHandlersAt(const gfx::Point& point) const override;
- void ObserveWheelEventAndResult(const blink::WebMouseWheelEvent& wheel_event,
- const gfx::Vector2dF& wheel_unused_delta,
- bool event_processed) override;
void ObserveGestureEventAndResult(const blink::WebGestureEvent& gesture_event,
const gfx::Vector2dF& unused_delta,
bool event_processed) override;
@@ -262,6 +257,9 @@ class CONTENT_EXPORT RenderWidget
void showImeIfNeeded() override;
void convertViewportToWindow(blink::WebRect* rect) override;
void convertWindowToViewport(blink::WebFloatRect* rect) override;
+ bool requestPointerLock() override;
+ void requestPointerUnlock() override;
+ bool isPointerLocked() override;
// Override point to obtain that the current input method state and caret
// position.
@@ -346,9 +344,6 @@ class CONTENT_EXPORT RenderWidget
// the new value will be sent to the browser process.
void UpdateSelectionBounds();
- // Called by the compositor to forward a proto that represents serialized
- // compositor state.
-
virtual void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end);
void OnShowHostContextMenu(ContextMenuParams* params);
@@ -366,6 +361,10 @@ class CONTENT_EXPORT RenderWidget
// Indicates whether this widget has focus.
bool has_focus() const { return has_focus_; }
+ MouseLockDispatcher* mouse_lock_dispatcher() {
+ return mouse_lock_dispatcher_.get();
+ }
+
protected:
// Friend RefCounted so that the dtor can be non-public. Using this class
// without ref-counting is an error.
@@ -424,7 +423,7 @@ class CONTENT_EXPORT RenderWidget
// Used to force the size of a window when running layout tests.
void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(USE_EXTERNAL_POPUP_MENU)
void SetExternalPopupOriginAdjustmentsForEmulation(
ExternalPopupMenu* popup,
RenderWidgetScreenMetricsEmulator* emulator);
@@ -442,7 +441,6 @@ class CONTENT_EXPORT RenderWidget
virtual void OnResize(const ResizeParams& params);
void OnEnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
void OnDisableDeviceEmulation();
- void OnColorProfile(const std::vector<char>& color_profile);
void OnChangeResizeRect(const gfx::Rect& resizer_rect);
virtual void OnWasHidden();
virtual void OnWasShown(bool needs_repainting,
@@ -717,8 +715,6 @@ class CONTENT_EXPORT RenderWidget
std::queue<SyntheticGestureCompletionCallback>
pending_synthetic_gesture_callbacks_;
- uint32_t next_output_surface_id_;
-
#if defined(OS_ANDROID)
// Indicates value in the focused text field is in dirty state, i.e. modified
// by script etc., not by user input.
@@ -760,6 +756,12 @@ class CONTENT_EXPORT RenderWidget
std::unique_ptr<scheduler::RenderWidgetSchedulingState>
render_widget_scheduling_state_;
+ // Mouse Lock dispatcher attached to this view.
+ std::unique_ptr<RenderWidgetMouseLockDispatcher> mouse_lock_dispatcher_;
+
+ // Wraps the |webwidget_| as a MouseLockDispatcher::LockTarget interface.
+ std::unique_ptr<MouseLockDispatcher::LockTarget> webwidget_mouse_lock_target_;
+
private:
// When emulated, this returns original device scale factor.
float GetOriginalDeviceScaleFactor() const;
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.cc b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
index 30a6372c082..10df6034b8f 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
@@ -145,8 +145,7 @@ class PepperWidget : public WebWidget {
size_ = size;
WebRect plugin_rect(0, 0, size_.width, size_.height);
- widget_->plugin()->ViewChanged(plugin_rect, plugin_rect, plugin_rect,
- std::vector<gfx::Rect>());
+ widget_->plugin()->ViewChanged(plugin_rect, plugin_rect, plugin_rect);
widget_->Invalidate();
}
diff --git a/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc b/chromium/content/renderer/render_widget_mouse_lock_dispatcher.cc
index bdd747b044e..970bef08fd6 100644
--- a/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc
+++ b/chromium/content/renderer/render_widget_mouse_lock_dispatcher.cc
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/renderer/render_view_mouse_lock_dispatcher.h"
+#include "content/renderer/render_widget_mouse_lock_dispatcher.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_view_impl.h"
+#include "ipc/ipc_message.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
@@ -15,31 +16,29 @@ using blink::WebUserGestureIndicator;
namespace content {
-RenderViewMouseLockDispatcher::RenderViewMouseLockDispatcher(
- RenderViewImpl* render_view_impl)
- : RenderViewObserver(render_view_impl),
- render_view_impl_(render_view_impl) {
-}
+RenderWidgetMouseLockDispatcher::RenderWidgetMouseLockDispatcher(
+ RenderWidget* render_widget)
+ : render_widget_(render_widget) {}
-RenderViewMouseLockDispatcher::~RenderViewMouseLockDispatcher() {
-}
+RenderWidgetMouseLockDispatcher::~RenderWidgetMouseLockDispatcher() {}
-void RenderViewMouseLockDispatcher::SendLockMouseRequest(
+void RenderWidgetMouseLockDispatcher::SendLockMouseRequest(
bool unlocked_by_target) {
bool user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
- Send(new ViewHostMsg_LockMouse(routing_id(), user_gesture, unlocked_by_target,
- false));
+ render_widget_->Send(new ViewHostMsg_LockMouse(
+ render_widget_->routing_id(), user_gesture, unlocked_by_target, false));
}
-void RenderViewMouseLockDispatcher::SendUnlockMouseRequest() {
- Send(new ViewHostMsg_UnlockMouse(routing_id()));
+void RenderWidgetMouseLockDispatcher::SendUnlockMouseRequest() {
+ render_widget_->Send(
+ new ViewHostMsg_UnlockMouse(render_widget_->routing_id()));
}
-bool RenderViewMouseLockDispatcher::OnMessageReceived(
+bool RenderWidgetMouseLockDispatcher::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RenderViewMouseLockDispatcher, message)
+ IPC_BEGIN_MESSAGE_MAP(RenderWidgetMouseLockDispatcher, message)
IPC_MESSAGE_HANDLER(ViewMsg_LockMouse_ACK, OnLockMouseACK)
IPC_MESSAGE_FORWARD(ViewMsg_MouseLockLost,
static_cast<MouseLockDispatcher*>(this),
@@ -49,7 +48,7 @@ bool RenderViewMouseLockDispatcher::OnMessageReceived(
return handled;
}
-void RenderViewMouseLockDispatcher::OnLockMouseACK(bool succeeded) {
+void RenderWidgetMouseLockDispatcher::OnLockMouseACK(bool succeeded) {
// Notify the base class.
MouseLockDispatcher::OnLockMouseACK(succeeded);
@@ -59,8 +58,8 @@ void RenderViewMouseLockDispatcher::OnLockMouseACK(bool succeeded) {
// Mouse Capture is implicitly given for the duration of a drag event, and
// sends all mouse events to the initial target of the drag.
// If Lock is entered it supercedes any in progress Capture.
- if (succeeded && render_view_impl_->GetWidget()->webwidget())
- render_view_impl_->GetWidget()->webwidget()->mouseCaptureLost();
+ if (succeeded && render_widget_->webwidget())
+ render_widget_->webwidget()->mouseCaptureLost();
}
} // namespace content
diff --git a/chromium/content/renderer/render_widget_mouse_lock_dispatcher.h b/chromium/content/renderer/render_widget_mouse_lock_dispatcher.h
new file mode 100644
index 00000000000..ed5ecee0259
--- /dev/null
+++ b/chromium/content/renderer/render_widget_mouse_lock_dispatcher.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_RENDER_WIDGET_MOUSE_LOCK_DISPATCHER_H_
+#define CONTENT_RENDERER_RENDER_WIDGET_MOUSE_LOCK_DISPATCHER_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "content/renderer/mouse_lock_dispatcher.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace content {
+
+class RenderWidget;
+
+// RenderWidgetMouseLockDispatcher is owned by RenderWidget.
+class RenderWidgetMouseLockDispatcher : public MouseLockDispatcher {
+ public:
+ explicit RenderWidgetMouseLockDispatcher(RenderWidget* render_widget);
+ ~RenderWidgetMouseLockDispatcher() override;
+
+ bool OnMessageReceived(const IPC::Message& message);
+
+ private:
+ // MouseLockDispatcher implementation.
+ void SendLockMouseRequest(bool unlocked_by_target) override;
+ void SendUnlockMouseRequest() override;
+
+ void OnLockMouseACK(bool succeeded);
+
+ RenderWidget* render_widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetMouseLockDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_RENDER_WIDGET_MOUSE_LOCK_DISPATCHER_H_
diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc
index 91b687f20d9..9b7ac2ea586 100644
--- a/chromium/content/renderer/render_widget_unittest.cc
+++ b/chromium/content/renderer/render_widget_unittest.cc
@@ -4,6 +4,7 @@
#include "content/renderer/render_widget.h"
+#include <tuple>
#include <vector>
#include "base/macros.h"
@@ -167,7 +168,7 @@ TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
InputHostMsg_HandleInputEvent_ACK::Param params;
InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
- InputEventAckState ack_state = base::get<0>(params).state;
+ InputEventAckState ack_state = std::get<0>(params).state;
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
widget()->sink()->ClearMessages();
@@ -185,7 +186,7 @@ TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
message = widget()->sink()->GetMessageAt(0);
EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
- ack_state = base::get<0>(params).state;
+ ack_state = std::get<0>(params).state;
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
widget()->sink()->ClearMessages();
}
@@ -212,7 +213,7 @@ TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
InputHostMsg_HandleInputEvent_ACK::Param params;
InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
- InputEventAckState ack_state = base::get<0>(params).state;
+ InputEventAckState ack_state = std::get<0>(params).state;
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
widget()->sink()->ClearMessages();
@@ -223,7 +224,7 @@ TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
message = widget()->sink()->GetMessageAt(0);
EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
- ack_state = base::get<0>(params).state;
+ ack_state = std::get<0>(params).state;
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
widget()->sink()->ClearMessages();
}
@@ -248,7 +249,7 @@ TEST_F(RenderWidgetUnittest, EventOverscroll) {
ASSERT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
InputHostMsg_HandleInputEvent_ACK::Param params;
InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
- const InputEventAck& ack = base::get<0>(params);
+ const InputEventAck& ack = std::get<0>(params);
ASSERT_EQ(ack.type, scroll.type);
ASSERT_TRUE(ack.overscroll);
EXPECT_EQ(gfx::Vector2dF(0, 10), ack.overscroll->accumulated_overscroll);
@@ -269,7 +270,7 @@ TEST_F(RenderWidgetUnittest, FlingOverscroll) {
ASSERT_EQ(InputHostMsg_DidOverscroll::ID, message->type());
InputHostMsg_DidOverscroll::Param params;
InputHostMsg_DidOverscroll::Read(message, &params);
- const DidOverscrollParams& overscroll = base::get<0>(params);
+ const DidOverscrollParams& overscroll = std::get<0>(params);
EXPECT_EQ(gfx::Vector2dF(10, 5), overscroll.latest_overscroll_delta);
EXPECT_EQ(gfx::Vector2dF(5, 5), overscroll.accumulated_overscroll);
EXPECT_EQ(gfx::PointF(1, 1), overscroll.causal_event_viewport_point);
diff --git a/chromium/content/renderer/renderer.sb b/chromium/content/renderer/renderer.sb
index 8c0f569abcc..7afdf86b297 100644
--- a/chromium/content/renderer/renderer.sb
+++ b/chromium/content/renderer/renderer.sb
@@ -34,18 +34,6 @@
(allow file-read-metadata (regex #"^/(private/)?etc$"))
-; https://crbug.com/508935
-; TODO(tkent): Remove this section when we drop 'results' attribute support.
-; https://crbug.com/590117
-(if (param-true? elcap-or-later)
- (allow file-read*
- (literal "/usr/lib/libcrypto.0.9.8.dylib")
- (literal "/usr/lib/libcsfde.dylib")
- (literal "/usr/lib/libcurl.4.dylib")
- (literal "/usr/lib/libCoreStorage.dylib")
- (literal "/usr/lib/libsasl2.2.dylib")
- (literal "/usr/lib/libutil.dylib")))
-
; https://crbug.com/605840
; file-read-metadata /System/Library/LinguisticData/en/US/hyphenation.dat
; for CFStringIsHyphenationAvailableForLocale and CFStringGetHyphenationLocationBeforeIndex
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.cc b/chromium/content/renderer/renderer_blink_platform_impl.cc
index 478cf8161ce..a3878139660 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.cc
+++ b/chromium/content/renderer/renderer_blink_platform_impl.cc
@@ -8,6 +8,7 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/guid.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
@@ -43,10 +44,8 @@
#include "content/common/frame_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu_process_launch_causes.h"
-#include "content/common/mime_registry_messages.h"
#include "content/common/render_process_messages.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/service_registry.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/media_stream_utils.h"
@@ -61,6 +60,7 @@
#include "content/renderer/gamepad_shared_memory_reader.h"
#include "content/renderer/media/audio_decoder.h"
#include "content/renderer/media/canvas_capture_handler.h"
+#include "content/renderer/media/html_audio_element_capturer_source.h"
#include "content/renderer/media/html_video_element_capturer_source.h"
#include "content/renderer/media/image_capture_frame_grabber.h"
#include "content/renderer/media/media_recorder_handler.h"
@@ -84,6 +84,7 @@
#include "media/base/mime_util.h"
#include "media/blink/webcontentdecryptionmodule_impl.h"
#include "media/filters/stream_parser_factory.h"
+#include "mojo/common/common_type_converters.h"
#include "storage/common/database/database_identifier.h"
#include "storage/common/quota/quota_types.h"
#include "third_party/WebKit/public/platform/BlameContext.h"
@@ -99,9 +100,9 @@
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebVector.h"
+#include "third_party/WebKit/public/platform/mime_registry.mojom.h"
#include "third_party/WebKit/public/platform/modules/device_orientation/WebDeviceMotionListener.h"
#include "third_party/WebKit/public/platform/modules/device_orientation/WebDeviceOrientationListener.h"
-#include "ui/gfx/color_profile.h"
#include "url/gurl.h"
#if defined(OS_MACOSX)
@@ -192,6 +193,9 @@ class RendererBlinkPlatformImpl::MimeRegistry
const blink::WebString& codecs) override;
blink::WebString mimeTypeForExtension(
const blink::WebString& file_extension) override;
+
+ private:
+ blink::mojom::MimeRegistryPtr mime_registry_;
};
class RendererBlinkPlatformImpl::FileUtilities : public WebFileUtilitiesImpl {
@@ -238,7 +242,7 @@ class RendererBlinkPlatformImpl::SandboxSupport
RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
scheduler::RendererScheduler* renderer_scheduler,
- base::WeakPtr<ServiceRegistry> service_registry)
+ base::WeakPtr<shell::InterfaceProvider> remote_interfaces)
: BlinkPlatformImpl(renderer_scheduler->DefaultTaskRunner()),
main_thread_(renderer_scheduler->CreateMainThread()),
clipboard_delegate_(new RendererClipboardDelegate),
@@ -250,7 +254,8 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
loading_task_runner_(renderer_scheduler->LoadingTaskRunner()),
web_scrollbar_behavior_(new WebScrollbarBehaviorImpl),
renderer_scheduler_(renderer_scheduler),
- blink_service_registry_(new BlinkServiceRegistryImpl(service_registry)) {
+ blink_service_registry_(
+ new BlinkServiceRegistryImpl(remote_interfaces)) {
#if !defined(OS_ANDROID) && !defined(OS_WIN)
if (g_sandbox_enabled && sandboxEnabled()) {
sandbox_support_.reset(new RendererBlinkPlatformImpl::SandboxSupport);
@@ -511,11 +516,15 @@ WebString RendererBlinkPlatformImpl::MimeRegistry::mimeTypeForExtension(
const WebString& file_extension) {
// The sandbox restricts our access to the registry, so we need to proxy
// these calls over to the browser process.
- std::string mime_type;
- RenderThread::Get()->Send(
- new MimeRegistryMsg_GetMimeTypeFromExtension(
- blink::WebStringToFilePath(file_extension).value(), &mime_type));
- return base::ASCIIToUTF16(mime_type);
+ if (!mime_registry_)
+ RenderThread::Get()->GetRemoteInterfaces()->GetInterface(&mime_registry_);
+
+ mojo::String mime_type;
+ if (!mime_registry_->GetMimeTypeFromExtension(
+ mojo::String::From(base::string16(file_extension)), &mime_type)) {
+ return WebString();
+ }
+ return base::ASCIIToUTF16(mime_type.get());
}
//------------------------------------------------------------------------------
@@ -639,11 +648,8 @@ long long RendererBlinkPlatformImpl::databaseGetFileSize(
long long RendererBlinkPlatformImpl::databaseGetSpaceAvailableForOrigin(
const blink::WebSecurityOrigin& origin) {
- // TODO(jsbell): Pass url::Origin over IPC instead of database
- // identifier/GURL. https://crbug.com/591482
- return DatabaseUtil::DatabaseGetSpaceAvailable(WebString::fromUTF8(
- storage::GetIdentifierFromOrigin(WebSecurityOriginToGURL(origin))),
- sync_message_filter_.get());
+ return DatabaseUtil::DatabaseGetSpaceAvailable(origin,
+ sync_message_filter_.get());
}
bool RendererBlinkPlatformImpl::databaseSetFileSize(
@@ -836,27 +842,6 @@ blink::WebString RendererBlinkPlatformImpl::signedPublicKeyAndChallengeString(
//------------------------------------------------------------------------------
-void RendererBlinkPlatformImpl::screenColorProfile(
- WebVector<char>* to_profile) {
-#if defined(OS_WIN)
- // On Windows screen color profile is only available in the browser.
- std::vector<char> profile;
- // This Send() can be called from any impl-side thread. Use a thread
- // safe send to avoid crashing trying to access RenderThread::Get(),
- // which is not accessible from arbitrary threads.
- thread_safe_sender_->Send(
- new RenderProcessHostMsg_GetMonitorColorProfile(&profile));
- *to_profile = profile;
-#else
- // On other platforms, the primary monitor color profile can be read
- // directly.
- gfx::ColorProfile profile;
- *to_profile = profile.profile();
-#endif
-}
-
-//------------------------------------------------------------------------------
-
blink::WebScrollbarBehavior* RendererBlinkPlatformImpl::scrollbarBehavior() {
return web_scrollbar_behavior_.get();
}
@@ -975,6 +960,33 @@ void RendererBlinkPlatformImpl::createHTMLVideoElementCapturer(
#endif
}
+void RendererBlinkPlatformImpl::createHTMLAudioElementCapturer(
+ WebMediaStream* web_media_stream,
+ WebMediaPlayer* web_media_player) {
+ DCHECK(web_media_stream);
+ DCHECK(web_media_player);
+
+ blink::WebMediaStreamSource web_media_stream_source;
+ blink::WebMediaStreamTrack web_media_stream_track;
+ const WebString track_id = WebString::fromUTF8(base::GenerateGUID());
+
+ web_media_stream_source.initialize(track_id,
+ blink::WebMediaStreamSource::TypeAudio,
+ track_id,
+ false /* is_remote */);
+ web_media_stream_track.initialize(web_media_stream_source);
+
+ MediaStreamAudioSource* const media_stream_source =
+ HtmlAudioElementCapturerSource::CreateFromWebMediaPlayerImpl(
+ web_media_player);
+
+ // Takes ownership of |media_stream_source|.
+ web_media_stream_source.setExtraData(media_stream_source);
+
+ media_stream_source->ConnectToTrack(web_media_stream_track);
+ web_media_stream->addTrack(web_media_stream_track);
+}
+
//------------------------------------------------------------------------------
WebImageCaptureFrameGrabber*
@@ -1072,6 +1084,8 @@ RendererBlinkPlatformImpl::createOffscreenGraphicsContext3DProvider(
attributes.samples = 0;
attributes.sample_buffers = 0;
attributes.bind_generates_resource = false;
+ // Prefer discrete GPU for WebGL.
+ attributes.gpu_preference = gl::PreferDiscreteGpu;
attributes.fail_if_major_perf_caveat =
web_attributes.failIfMajorPerformanceCaveat;
@@ -1084,15 +1098,13 @@ RendererBlinkPlatformImpl::createOffscreenGraphicsContext3DProvider(
constexpr bool automatic_flushes = true;
constexpr bool support_locking = false;
- // Prefer discrete GPU for WebGL.
- constexpr gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
scoped_refptr<ContextProviderCommandBuffer> provider(
new ContextProviderCommandBuffer(
std::move(gpu_channel_host), gpu::GPU_STREAM_DEFAULT,
gpu::GpuStreamPriority::NORMAL, gpu::kNullSurfaceHandle,
- GURL(top_document_web_url), gpu_preference, automatic_flushes,
- support_locking, gpu::SharedMemoryLimits(), attributes, share_context,
+ GURL(top_document_web_url), automatic_flushes, support_locking,
+ gpu::SharedMemoryLimits(), attributes, share_context,
command_buffer_metrics::OFFSCREEN_CONTEXT_FOR_WEBGL));
return new WebGraphicsContext3DProviderImpl(std::move(provider));
}
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.h b/chromium/content/renderer/renderer_blink_platform_impl.h
index 85b8fb8bab4..ac345facef6 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.h
+++ b/chromium/content/renderer/renderer_blink_platform_impl.h
@@ -48,6 +48,10 @@ class RendererScheduler;
class WebThreadImplForRendererScheduler;
}
+namespace shell {
+class InterfaceProvider;
+}
+
namespace content {
class BlinkServiceRegistryImpl;
class DeviceLightEventPump;
@@ -58,7 +62,6 @@ class PlatformEventObserverBase;
class QuotaMessageFilter;
class RendererClipboardDelegate;
class RenderView;
-class ServiceRegistry;
class ThreadSafeSender;
class WebClipboardImpl;
class WebDatabaseObserverImpl;
@@ -66,8 +69,9 @@ class WebFileSystemImpl;
class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
public:
- RendererBlinkPlatformImpl(scheduler::RendererScheduler* renderer_scheduler,
- base::WeakPtr<ServiceRegistry> service_registry);
+ RendererBlinkPlatformImpl(
+ scheduler::RendererScheduler* renderer_scheduler,
+ base::WeakPtr<shell::InterfaceProvider> remote_interfaces);
~RendererBlinkPlatformImpl() override;
// Shutdown must be called just prior to shutting down blink.
@@ -129,7 +133,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
void getPluginList(bool refresh,
blink::WebPluginListBuilder* builder) override;
blink::WebPublicSuffixList* publicSuffixList() override;
- void screenColorProfile(blink::WebVector<char>* to_profile) override;
blink::WebScrollbarBehavior* scrollbarBehavior() override;
blink::WebIDBFactory* idbFactory() override;
blink::WebServiceWorkerCacheStorage* cacheStorage(
@@ -177,6 +180,9 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
void createHTMLVideoElementCapturer(
blink::WebMediaStream* web_media_stream,
blink::WebMediaPlayer* web_media_player) override;
+ void createHTMLAudioElementCapturer(
+ blink::WebMediaStream* web_media_stream,
+ blink::WebMediaPlayer* web_media_player) override;
blink::WebImageCaptureFrameGrabber* createImageCaptureFrameGrabber() override;
blink::WebGraphicsContext3DProvider* createOffscreenGraphicsContext3DProvider(
const blink::Platform::ContextAttributes& attributes,
diff --git a/chromium/content/renderer/renderer_main.cc b/chromium/content/renderer/renderer_main.cc
index a00d117ce0c..149c18f8c68 100644
--- a/chromium/content/renderer/renderer_main.cc
+++ b/chromium/content/renderer/renderer_main.cc
@@ -52,7 +52,7 @@
#endif
#if defined(ENABLE_WEBRTC)
-#include "third_party/libjingle/overrides/init_webrtc.h"
+#include "third_party/webrtc_overrides/init_webrtc.h"
#endif
#if defined(USE_OZONE)
@@ -91,8 +91,6 @@ int RendererMain(const MainFunctionParams& parameters) {
const base::CommandLine& parsed_command_line = parameters.command_line;
- MojoShellConnectionImpl::Create();
-
#if defined(OS_MACOSX)
base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool;
#endif // OS_MACOSX
@@ -200,8 +198,6 @@ int RendererMain(const MainFunctionParams& parameters) {
TRACE_EVENT_ASYNC_END0("toplevel", "RendererMain.START_MSG_LOOP", 0);
}
- MojoShellConnectionImpl::Destroy();
-
#if defined(LEAK_SANITIZER)
// Run leak detection before RenderProcessImpl goes out of scope. This helps
// ignore shutdown-only leaks.
diff --git a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc
index f0060ef0b21..5f2071d3779 100644
--- a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc
+++ b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc
@@ -31,6 +31,10 @@ bool ScreenOrientationDispatcher::OnMessageReceived(
return handled;
}
+void ScreenOrientationDispatcher::OnDestruct() {
+ delete this;
+}
+
void ScreenOrientationDispatcher::OnLockSuccess(int request_id) {
blink::WebLockOrientationCallback* callback =
pending_callbacks_.Lookup(request_id);
diff --git a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h
index 4eadeb191fe..9d108d27668 100644
--- a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h
+++ b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h
@@ -34,6 +34,7 @@ class CONTENT_EXPORT ScreenOrientationDispatcher :
// RenderFrameObserver implementation.
bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() override;
// blink::WebScreenOrientationClient implementation.
void lockOrientation(blink::WebScreenOrientationLockType orientation,
diff --git a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc
index 4d9cf0226d2..b5f7bebf0ef 100644
--- a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc
+++ b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc
@@ -6,6 +6,7 @@
#include <list>
#include <memory>
+#include <tuple>
#include "base/logging.h"
#include "content/common/screen_orientation_messages.h"
@@ -72,9 +73,9 @@ class ScreenOrientationDispatcherTest : public testing::Test {
ScreenOrientationHostMsg_LockRequest::ID);
EXPECT_TRUE(msg != NULL);
- base::Tuple<blink::WebScreenOrientationLockType, int> params;
+ std::tuple<blink::WebScreenOrientationLockType, int> params;
ScreenOrientationHostMsg_LockRequest::Read(msg, &params);
- return base::get<1>(params);
+ return std::get<1>(params);
}
IPC::TestSink& sink() {
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.cc b/chromium/content/renderer/service_worker/service_worker_context_client.cc
index 6a5cd56673c..c765667871b 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.cc
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc
@@ -29,7 +29,6 @@
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/devtools_messages.h"
#include "content/common/message_port_messages.h"
-#include "content/common/mojo/service_registry_impl.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/common/push_event_payload.h"
@@ -43,6 +42,7 @@
#include "content/renderer/service_worker/service_worker_type_util.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
@@ -99,6 +99,9 @@ class WebServiceWorkerNetworkProviderImpl
std::unique_ptr<RequestExtraData> extra_data(new RequestExtraData);
extra_data->set_service_worker_provider_id(provider->provider_id());
extra_data->set_originated_from_service_worker(true);
+ // Service workers are only available in secure contexts, so all requests
+ // are initiated in a secure context.
+ extra_data->set_initiated_in_secure_context(true);
request.setExtraData(extra_data.release());
}
};
@@ -171,11 +174,13 @@ struct ServiceWorkerContextClient::WorkerContextData {
using SkipWaitingCallbacksMap =
IDMap<blink::WebServiceWorkerSkipWaitingCallbacks, IDMapOwnPointer>;
using SyncEventCallbacksMap =
- IDMap<const mojo::Callback<void(blink::mojom::ServiceWorkerEventStatus)>,
+ IDMap<const base::Callback<void(blink::mojom::ServiceWorkerEventStatus)>,
IDMapOwnPointer>;
explicit WorkerContextData(ServiceWorkerContextClient* owner)
- : weak_factory(owner), proxy_weak_factory(owner->proxy_) {}
+ : interface_registry(nullptr),
+ weak_factory(owner),
+ proxy_weak_factory(owner->proxy_) {}
~WorkerContextData() {
DCHECK(thread_checker.CalledOnValidThread());
@@ -196,7 +201,8 @@ struct ServiceWorkerContextClient::WorkerContextData {
// Pending callbacks for Background Sync Events
SyncEventCallbacksMap sync_event_callbacks;
- ServiceRegistryImpl service_registry;
+ shell::InterfaceRegistry interface_registry;
+ shell::InterfaceProvider remote_interfaces;
base::ThreadChecker thread_checker;
base::WeakPtrFactory<ServiceWorkerContextClient> weak_factory;
@@ -272,12 +278,11 @@ void ServiceWorkerContextClient::OnMessageReceived(
DCHECK(handled);
}
-void ServiceWorkerContextClient::BindServiceRegistry(
- shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services) {
- context_->service_registry.Bind(std::move(services));
- context_->service_registry.BindRemoteServiceProvider(
- std::move(exposed_services));
+void ServiceWorkerContextClient::BindInterfaceProviders(
+ shell::mojom::InterfaceProviderRequest request,
+ shell::mojom::InterfaceProviderPtr remote_interfaces) {
+ context_->interface_registry.Bind(std::move(request));
+ context_->remote_interfaces.Bind(std::move(remote_interfaces));
}
blink::WebURL ServiceWorkerContextClient::scope() const {
@@ -375,8 +380,8 @@ void ServiceWorkerContextClient::workerContextStarted(
DCHECK_NE(registration_info.registration_id,
kInvalidServiceWorkerRegistrationId);
- // Register Mojo services.
- context_->service_registry.ServiceRegistry::AddService(
+ // Register Mojo interfaces.
+ context_->interface_registry.AddInterface(
base::Bind(&BackgroundSyncClientImpl::Create));
SetRegistrationInServiceWorkerGlobalScope(registration_info, version_attrs);
@@ -408,7 +413,8 @@ void ServiceWorkerContextClient::didInitializeWorkerContext(
v8::Local<v8::Context> context) {
GetContentClient()
->renderer()
- ->DidInitializeServiceWorkerContextOnWorkerThread(context, script_url_);
+ ->DidInitializeServiceWorkerContextOnWorkerThread(
+ context, embedded_worker_id_, script_url_);
}
void ServiceWorkerContextClient::willDestroyWorkerContext(
@@ -427,7 +433,7 @@ void ServiceWorkerContextClient::willDestroyWorkerContext(
g_worker_client_tls.Pointer()->Set(NULL);
GetContentClient()->renderer()->WillDestroyServiceWorkerContextOnWorkerThread(
- context, script_url_);
+ context, embedded_worker_id_, script_url_);
}
void ServiceWorkerContextClient::workerContextDestroyed() {
@@ -501,21 +507,23 @@ void ServiceWorkerContextClient::didHandleInstallEvent(
int request_id,
blink::WebServiceWorkerEventResult result) {
Send(new ServiceWorkerHostMsg_InstallEventFinished(
- GetRoutingID(), request_id, result));
+ GetRoutingID(), request_id, result, proxy_->hasFetchEventHandler()));
}
-void ServiceWorkerContextClient::didHandleFetchEvent(int request_id) {
- Send(new ServiceWorkerHostMsg_FetchEventFinished(
- GetRoutingID(), request_id,
- SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
+void ServiceWorkerContextClient::respondToFetchEvent(int response_id) {
+ Send(new ServiceWorkerHostMsg_FetchEventResponse(
+ GetRoutingID(), response_id, SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
ServiceWorkerResponse()));
}
-void ServiceWorkerContextClient::didHandleFetchEvent(
- int request_id,
+void ServiceWorkerContextClient::respondToFetchEvent(
+ int response_id,
const blink::WebServiceWorkerResponse& web_response) {
ServiceWorkerHeaderMap headers;
GetServiceWorkerHeaderMapFromWebResponse(web_response, &headers);
+ ServiceWorkerHeaderList cors_exposed_header_names;
+ GetCorsExposedHeaderNamesFromWebResponse(web_response,
+ &cors_exposed_header_names);
ServiceWorkerResponse response(
web_response.url(), web_response.status(),
web_response.statusText().utf8(), web_response.responseType(), headers,
@@ -523,13 +531,19 @@ void ServiceWorkerContextClient::didHandleFetchEvent(
web_response.streamURL(), web_response.error(),
base::Time::FromInternalValue(web_response.responseTime()),
!web_response.cacheStorageCacheName().isNull(),
- web_response.cacheStorageCacheName().utf8());
- Send(new ServiceWorkerHostMsg_FetchEventFinished(
- GetRoutingID(), request_id,
- SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
+ web_response.cacheStorageCacheName().utf8(), cors_exposed_header_names);
+ Send(new ServiceWorkerHostMsg_FetchEventResponse(
+ GetRoutingID(), response_id, SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
response));
}
+void ServiceWorkerContextClient::didHandleFetchEvent(
+ int event_finish_id,
+ blink::WebServiceWorkerEventResult result) {
+ Send(new ServiceWorkerHostMsg_FetchEventFinished(GetRoutingID(),
+ event_finish_id, result));
+}
+
void ServiceWorkerContextClient::didHandleNotificationClickEvent(
int request_id,
blink::WebServiceWorkerEventResult result) {
@@ -580,7 +594,8 @@ ServiceWorkerContextClient::createServiceWorkerNetworkProvider(
provider_context_ = provider->context();
// Tell the network provider about which version to load.
- provider->SetServiceWorkerVersionId(service_worker_version_id_);
+ provider->SetServiceWorkerVersionId(service_worker_version_id_,
+ embedded_worker_id_);
// The provider is kept around for the lifetime of the DataSource
// and ownership is transferred to the DataSource.
@@ -758,7 +773,8 @@ void ServiceWorkerContextClient::OnInstallEvent(int request_id) {
}
void ServiceWorkerContextClient::OnFetchEvent(
- int request_id,
+ int response_id,
+ int event_finish_id,
const ServiceWorkerFetchRequest& request) {
blink::WebServiceWorkerRequest webRequest;
TRACE_EVENT0("ServiceWorker",
@@ -789,9 +805,9 @@ void ServiceWorkerContextClient::OnFetchEvent(
webRequest.setClientId(blink::WebString::fromUTF8(request.client_id));
webRequest.setIsReload(request.is_reload);
if (request.fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH) {
- proxy_->dispatchForeignFetchEvent(request_id, webRequest);
+ proxy_->dispatchForeignFetchEvent(response_id, event_finish_id, webRequest);
} else {
- proxy_->dispatchFetchEvent(request_id, webRequest);
+ proxy_->dispatchFetchEvent(response_id, event_finish_id, webRequest);
}
}
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.h b/chromium/content/renderer/service_worker/service_worker_context_client.h
index 48b4dbd5178..a009d30c492 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.h
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.h
@@ -13,6 +13,7 @@
#include <string>
#include <vector>
+#include "base/callback.h"
#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -64,7 +65,7 @@ class ServiceWorkerContextClient
: public blink::WebServiceWorkerContextClient {
public:
using SyncCallback =
- mojo::Callback<void(blink::mojom::ServiceWorkerEventStatus)>;
+ base::Callback<void(blink::mojom::ServiceWorkerEventStatus)>;
// Returns a thread-specific client instance. This does NOT create a
// new instance.
@@ -82,11 +83,10 @@ class ServiceWorkerContextClient
int embedded_worker_id,
const IPC::Message& message);
- // Called some time after the worker has started. Attempts to use the
- // ServiceRegistry to connect to services before this method is called are
- // queued up and will resolve after this method is called.
- void BindServiceRegistry(shell::mojom::InterfaceProviderRequest services,
- shell::mojom::InterfaceProviderPtr exposed_services);
+ // Called some time after the worker has started.
+ void BindInterfaceProviders(
+ shell::mojom::InterfaceProviderRequest request,
+ shell::mojom::InterfaceProviderPtr remote_interfaces);
// WebServiceWorkerContextClient overrides.
blink::WebURL scope() const override;
@@ -136,10 +136,12 @@ class ServiceWorkerContextClient
void didHandleInstallEvent(
int request_id,
blink::WebServiceWorkerEventResult result) override;
- void didHandleFetchEvent(int request_id) override;
- void didHandleFetchEvent(
- int request_id,
+ void respondToFetchEvent(int response_id) override;
+ void respondToFetchEvent(
+ int response_id,
const blink::WebServiceWorkerResponse& response) override;
+ void didHandleFetchEvent(int event_finish_id,
+ blink::WebServiceWorkerEventResult result) override;
void didHandleNotificationClickEvent(
int request_id,
blink::WebServiceWorkerEventResult result) override;
@@ -199,7 +201,9 @@ class ServiceWorkerContextClient
int request_id,
const ServiceWorkerMsg_ExtendableMessageEvent_Params& params);
void OnInstallEvent(int request_id);
- void OnFetchEvent(int request_id, const ServiceWorkerFetchRequest& request);
+ void OnFetchEvent(int response_id,
+ int event_finish_id,
+ const ServiceWorkerFetchRequest& request);
void OnNotificationClickEvent(
int request_id,
int64_t persistent_notification_id,
diff --git a/chromium/content/renderer/service_worker/service_worker_type_util.cc b/chromium/content/renderer/service_worker/service_worker_type_util.cc
index 9eb9f9c6c53..35769afd267 100644
--- a/chromium/content/renderer/service_worker/service_worker_type_util.cc
+++ b/chromium/content/renderer/service_worker/service_worker_type_util.cc
@@ -61,4 +61,14 @@ void GetServiceWorkerHeaderMapFromWebResponse(
web_response.visitHTTPHeaderFields(MakeHeaderVisitor(headers).get());
}
+void GetCorsExposedHeaderNamesFromWebResponse(
+ const blink::WebServiceWorkerResponse& web_response,
+ ServiceWorkerHeaderList* result) {
+ blink::WebVector<blink::WebString> headers =
+ web_response.corsExposedHeaderNames();
+ result->resize(headers.size());
+ std::transform(headers.begin(), headers.end(), result->begin(),
+ [](const blink::WebString& s) { return s.latin1(); });
+}
+
} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_type_util.h b/chromium/content/renderer/service_worker/service_worker_type_util.h
index 439231fdebd..f1cfa84e7a3 100644
--- a/chromium/content/renderer/service_worker/service_worker_type_util.h
+++ b/chromium/content/renderer/service_worker/service_worker_type_util.h
@@ -22,6 +22,10 @@ void GetServiceWorkerHeaderMapFromWebResponse(
const blink::WebServiceWorkerResponse& web_response,
ServiceWorkerHeaderMap* headers);
+void GetCorsExposedHeaderNamesFromWebResponse(
+ const blink::WebServiceWorkerResponse& web_response,
+ ServiceWorkerHeaderList* result);
+
} // namespace content
#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_UTIL_H_
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 4b7509754fc..1b58b4f59dd 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -18,6 +18,7 @@
#include "content/child/shared_worker_devtools_agent.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/worker_messages.h"
+#include "content/public/common/origin_util.h"
#include "content/renderer/devtools/devtools_agent.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h"
@@ -72,6 +73,7 @@ class DataSourceExtraData
public:
DataSourceExtraData() {}
~DataSourceExtraData() override {}
+ bool is_secure_context = false;
};
// Called on the main thread only and blink owns it.
@@ -86,13 +88,19 @@ class WebServiceWorkerNetworkProviderImpl
GetNetworkProviderFromDataSource(data_source);
std::unique_ptr<RequestExtraData> extra_data(new RequestExtraData);
extra_data->set_service_worker_provider_id(provider->provider_id());
+ extra_data->set_initiated_in_secure_context(
+ static_cast<DataSourceExtraData*>(data_source->getExtraData())
+ ->is_secure_context);
request.setExtraData(extra_data.release());
// Explicitly set the SkipServiceWorker flag for subresources here if the
// renderer process hasn't received SetControllerServiceWorker message.
if (request.getRequestContext() !=
blink::WebURLRequest::RequestContextSharedWorker &&
- !provider->IsControlledByServiceWorker()) {
- request.setSkipServiceWorker(true);
+ !provider->IsControlledByServiceWorker() &&
+ request.skipServiceWorker() !=
+ blink::WebURLRequest::SkipServiceWorker::All) {
+ request.setSkipServiceWorker(
+ blink::WebURLRequest::SkipServiceWorker::Controlling);
}
}
@@ -248,6 +256,7 @@ EmbeddedSharedWorkerStub::createServiceWorkerNetworkProvider(
// The provider is kept around for the lifetime of the DataSource
// and ownership is transferred to the DataSource.
DataSourceExtraData* extra_data = new DataSourceExtraData();
+ extra_data->is_secure_context = IsOriginSecure(url_);
data_source->setExtraData(extra_data);
ServiceWorkerNetworkProvider::AttachToDocumentState(extra_data,
std::move(provider));
diff --git a/chromium/content/renderer/shared_worker_repository.cc b/chromium/content/renderer/shared_worker_repository.cc
index 607e044fe27..466a79b6877 100644
--- a/chromium/content/renderer/shared_worker_repository.cc
+++ b/chromium/content/renderer/shared_worker_repository.cc
@@ -59,4 +59,8 @@ void SharedWorkerRepository::documentDetached(DocumentID document) {
}
}
+void SharedWorkerRepository::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/shared_worker_repository.h b/chromium/content/renderer/shared_worker_repository.h
index 93ac628c379..8714f3af39d 100644
--- a/chromium/content/renderer/shared_worker_repository.h
+++ b/chromium/content/renderer/shared_worker_repository.h
@@ -37,6 +37,9 @@ class SharedWorkerRepository : public RenderFrameObserver,
void documentDetached(DocumentID document_id) override;
private:
+ // RenderFrameObserver implementation.
+ void OnDestruct() override;
+
std::set<DocumentID> documents_with_workers_;
DISALLOW_COPY_AND_ASSIGN(SharedWorkerRepository);
diff --git a/chromium/content/renderer/speech_recognition_dispatcher.cc b/chromium/content/renderer/speech_recognition_dispatcher.cc
index 585b61cd8da..e707f4105df 100644
--- a/chromium/content/renderer/speech_recognition_dispatcher.cc
+++ b/chromium/content/renderer/speech_recognition_dispatcher.cc
@@ -66,6 +66,10 @@ bool SpeechRecognitionDispatcher::OnMessageReceived(
return handled;
}
+void SpeechRecognitionDispatcher::OnDestruct() {
+ delete this;
+}
+
void SpeechRecognitionDispatcher::start(
const WebSpeechRecognitionHandle& handle,
const WebSpeechRecognitionParams& params,
diff --git a/chromium/content/renderer/speech_recognition_dispatcher.h b/chromium/content/renderer/speech_recognition_dispatcher.h
index bde0bdf0f33..d0cddc075ea 100644
--- a/chromium/content/renderer/speech_recognition_dispatcher.h
+++ b/chromium/content/renderer/speech_recognition_dispatcher.h
@@ -45,6 +45,7 @@ class SpeechRecognitionDispatcher : public RenderViewObserver,
private:
// RenderViewObserver implementation.
bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() override;
// blink::WebSpeechRecognizer implementation.
void start(const blink::WebSpeechRecognitionHandle&,
diff --git a/chromium/content/renderer/stats_collection_observer.cc b/chromium/content/renderer/stats_collection_observer.cc
index 4c4b911ec8c..f2c45bf461c 100644
--- a/chromium/content/renderer/stats_collection_observer.cc
+++ b/chromium/content/renderer/stats_collection_observer.cc
@@ -30,4 +30,8 @@ void StatsCollectionObserver::DidStopLoading() {
impl->RemoveObserver(this);
}
+void StatsCollectionObserver::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/stats_collection_observer.h b/chromium/content/renderer/stats_collection_observer.h
index 5a17dfe6933..e1b73233120 100644
--- a/chromium/content/renderer/stats_collection_observer.h
+++ b/chromium/content/renderer/stats_collection_observer.h
@@ -30,6 +30,9 @@ class StatsCollectionObserver : public RenderViewObserver {
const base::Time& load_stop_time() { return stop_time_; }
private:
+ // RenderViewObserver implementation.
+ void OnDestruct() override;
+
base::Time start_time_;
base::Time stop_time_;
diff --git a/chromium/content/renderer/text_input_client_observer.cc b/chromium/content/renderer/text_input_client_observer.cc
index e3b8bd7a377..3c953eebaad 100644
--- a/chromium/content/renderer/text_input_client_observer.cc
+++ b/chromium/content/renderer/text_input_client_observer.cc
@@ -48,6 +48,10 @@ bool TextInputClientObserver::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+void TextInputClientObserver::OnDestruct() {
+ delete this;
+}
+
blink::WebView* TextInputClientObserver::webview() {
return render_view()->GetWebView();
}
diff --git a/chromium/content/renderer/text_input_client_observer.h b/chromium/content/renderer/text_input_client_observer.h
index c41b670ce22..2c538a61c2b 100644
--- a/chromium/content/renderer/text_input_client_observer.h
+++ b/chromium/content/renderer/text_input_client_observer.h
@@ -31,6 +31,9 @@ class TextInputClientObserver : public RenderViewObserver {
bool OnMessageReceived(const IPC::Message& message) override;
private:
+ // RenderViewObserver implementation.
+ void OnDestruct() override;
+
// Returns the WebView of the RenderView.
blink::WebView* webview();
diff --git a/chromium/content/renderer/visual_state_browsertest.cc b/chromium/content/renderer/visual_state_browsertest.cc
index 26d9a6ddd26..2a8b49bff8f 100644
--- a/chromium/content/renderer/visual_state_browsertest.cc
+++ b/chromium/content/renderer/visual_state_browsertest.cc
@@ -50,6 +50,9 @@ class CommitObserver : public RenderViewObserver {
int GetCommitCount() { return commit_count_; }
private:
+ // RenderViewObserver implementation.
+ void OnDestruct() override { delete this; }
+
std::set<base::Closure*> quit_closures_;
int commit_count_;
};
diff --git a/chromium/content/renderer/web_ui_extension.cc b/chromium/content/renderer/web_ui_extension.cc
index 0751e6ee68b..a793b4e215b 100644
--- a/chromium/content/renderer/web_ui_extension.cc
+++ b/chromium/content/renderer/web_ui_extension.cc
@@ -5,6 +5,7 @@
#include "content/renderer/web_ui_extension.h"
#include <memory>
+#include <utility>
#include "base/values.h"
#include "content/common/view_messages.h"
@@ -108,13 +109,9 @@ void WebUIExtension::Send(gin::Arguments* args) {
}
std::unique_ptr<V8ValueConverter> converter(V8ValueConverter::create());
-
- base::Value* value =
- converter->FromV8Value(obj, frame->mainWorldScriptContext());
- base::ListValue* list = NULL;
- value->GetAsList(&list);
- DCHECK(list);
- content.reset(list);
+ content = base::ListValue::From(
+ converter->FromV8Value(obj, frame->mainWorldScriptContext()));
+ DCHECK(content);
}
// Send the message up to the browser.
diff --git a/chromium/content/renderer/web_ui_extension_data.cc b/chromium/content/renderer/web_ui_extension_data.cc
index 80d570fd9a1..43cf15ec347 100644
--- a/chromium/content/renderer/web_ui_extension_data.cc
+++ b/chromium/content/renderer/web_ui_extension_data.cc
@@ -39,4 +39,8 @@ void WebUIExtensionData::OnSetWebUIProperty(const std::string& name,
variable_map_[name] = value;
}
+void WebUIExtensionData::OnDestruct() {
+ delete this;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/web_ui_extension_data.h b/chromium/content/renderer/web_ui_extension_data.h
index 8bbac72a5b8..566faed6c4d 100644
--- a/chromium/content/renderer/web_ui_extension_data.h
+++ b/chromium/content/renderer/web_ui_extension_data.h
@@ -28,6 +28,7 @@ class WebUIExtensionData
private:
// RenderViewObserver implementation.
bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() override;
void OnSetWebUIProperty(const std::string& name, const std::string& value);
diff --git a/chromium/content/shell/common/shell_content_client.cc b/chromium/content/shell/common/shell_content_client.cc
index 82c2f0c5033..ea5ea1ccd82 100644
--- a/chromium/content/shell/common/shell_content_client.cc
+++ b/chromium/content/shell/common/shell_content_client.cc
@@ -20,19 +20,6 @@
namespace content {
-namespace {
-
-// This is the public key which the content shell will use to enable origin
-// trial features.
-// TODO(iclelland): Update this comment with the location of the public and
-// private key files when the command-line tool CL lands
-static const uint8_t kOriginTrialPublicKey[] = {
- 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
-
std::string GetShellUserAgent() {
std::string product = "Chrome/" CONTENT_SHELL_VERSION;
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -41,10 +28,7 @@ std::string GetShellUserAgent() {
return BuildUserAgentFromProduct(product);
}
-ShellContentClient::ShellContentClient()
- : origin_trial_public_key_(base::StringPiece(
- reinterpret_cast<const char*>(kOriginTrialPublicKey),
- arraysize(kOriginTrialPublicKey))) {}
+ShellContentClient::ShellContentClient() {}
ShellContentClient::~ShellContentClient() {}
@@ -98,7 +82,7 @@ base::StringPiece ShellContentClient::GetDataResource(
resource_id, scale_factor);
}
-base::RefCountedStaticMemory* ShellContentClient::GetDataResourceBytes(
+base::RefCountedMemory* ShellContentClient::GetDataResourceBytes(
int resource_id) const {
return ResourceBundle::GetSharedInstance().LoadDataResourceBytes(resource_id);
}
@@ -112,8 +96,8 @@ bool ShellContentClient::IsSupplementarySiteIsolationModeEnabled() {
switches::kIsolateSitesForTesting);
}
-base::StringPiece ShellContentClient::GetOriginTrialPublicKey() {
- return origin_trial_public_key_;
+OriginTrialPolicy* ShellContentClient::GetOriginTrialPolicy() {
+ return &origin_trial_policy_;
}
} // namespace content
diff --git a/chromium/content/shell/common/shell_content_client.h b/chromium/content/shell/common/shell_content_client.h
index 2b1e7b65b10..1c22125caee 100644
--- a/chromium/content/shell/common/shell_content_client.h
+++ b/chromium/content/shell/common/shell_content_client.h
@@ -10,6 +10,8 @@
#include "base/compiler_specific.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/origin_trial_policy.h"
+#include "content/shell/common/shell_origin_trial_policy.h"
namespace content {
@@ -25,14 +27,14 @@ class ShellContentClient : public ContentClient {
base::StringPiece GetDataResource(
int resource_id,
ui::ScaleFactor scale_factor) const override;
- base::RefCountedStaticMemory* GetDataResourceBytes(
+ base::RefCountedMemory* GetDataResourceBytes(
int resource_id) const override;
gfx::Image& GetNativeImageNamed(int resource_id) const override;
bool IsSupplementarySiteIsolationModeEnabled() override;
- base::StringPiece GetOriginTrialPublicKey() override;
+ OriginTrialPolicy* GetOriginTrialPolicy() override;
private:
- base::StringPiece origin_trial_public_key_;
+ ShellOriginTrialPolicy origin_trial_policy_;
};
} // namespace content
diff --git a/chromium/content/shell/common/shell_origin_trial_policy.cc b/chromium/content/shell/common/shell_origin_trial_policy.cc
new file mode 100644
index 00000000000..bb2088308b2
--- /dev/null
+++ b/chromium/content/shell/common/shell_origin_trial_policy.cc
@@ -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.
+
+#include "content/shell/common/shell_origin_trial_policy.h"
+
+namespace content {
+
+namespace {
+
+// This is the public key which the content shell will use to enable origin
+// trial features. Trial tokens for use in layout tests can be created with the
+// tool in /tools/origin_trials/generate_token.py, using the private key
+// contained in /tools/origin_trials/eftest.key.
+static const uint8_t kOriginTrialPublicKey[] = {
+ 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
+
+ShellOriginTrialPolicy::ShellOriginTrialPolicy()
+ : public_key_(base::StringPiece(
+ reinterpret_cast<const char*>(kOriginTrialPublicKey),
+ arraysize(kOriginTrialPublicKey))) {}
+
+ShellOriginTrialPolicy::~ShellOriginTrialPolicy() {}
+
+base::StringPiece ShellOriginTrialPolicy::GetPublicKey() const {
+ return public_key_;
+}
+
+bool ShellOriginTrialPolicy::IsFeatureDisabled(
+ base::StringPiece feature) const {
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/shell/common/shell_origin_trial_policy.h b/chromium/content/shell/common/shell_origin_trial_policy.h
new file mode 100644
index 00000000000..e296e330eb1
--- /dev/null
+++ b/chromium/content/shell/common/shell_origin_trial_policy.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_SHELL_COMMON_SHELL_ORIGIN_TRIAL_POLICY_H_
+#define CONTENT_SHELL_COMMON_SHELL_ORIGIN_TRIAL_POLICY_H_
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "content/public/common/origin_trial_policy.h"
+
+namespace content {
+
+class ShellOriginTrialPolicy : public OriginTrialPolicy {
+ public:
+ ShellOriginTrialPolicy();
+ ~ShellOriginTrialPolicy() override;
+
+ // OriginTrialPolicy interface
+ base::StringPiece GetPublicKey() const override;
+ bool IsFeatureDisabled(base::StringPiece feature) const override;
+
+ private:
+ base::StringPiece public_key_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellOriginTrialPolicy);
+};
+
+} // namespace content
+
+#endif // CONTENT_SHELL_COMMON_SHELL_ORIGIN_TRIAL_POLICY_H_
diff --git a/chromium/content/utility/BUILD.gn b/chromium/content/utility/BUILD.gn
index 957fb43f01a..883fbd1d482 100644
--- a/chromium/content/utility/BUILD.gn
+++ b/chromium/content/utility/BUILD.gn
@@ -22,11 +22,12 @@ source_set("utility") {
"//base",
"//components/scheduler",
"//content:export",
+ "//content/child",
"//content/public/child:child_sources",
"//content/public/common:common_sources",
- "//courgette:courgette_lib",
"//mojo/common",
"//mojo/public/cpp/bindings",
+ "//sandbox",
"//services/shell",
"//services/shell/public/cpp",
"//services/shell/public/interfaces",
diff --git a/chromium/content/utility/utility_process_control_impl.h b/chromium/content/utility/utility_process_control_impl.h
index bf4bd62673f..ff8bc412dd0 100644
--- a/chromium/content/utility/utility_process_control_impl.h
+++ b/chromium/content/utility/utility_process_control_impl.h
@@ -11,7 +11,7 @@
namespace content {
// Customization of ProcessControlImpl for the utility process. Exposed to the
-// browser via the utility process's ServiceRegistry.
+// browser via the utility process's InterfaceRegistry.
class UtilityProcessControlImpl : public ProcessControlImpl {
public:
UtilityProcessControlImpl();
diff --git a/chromium/content/utility/utility_thread_impl.cc b/chromium/content/utility/utility_thread_impl.cc
index edbf498303a..8425e664eb5 100644
--- a/chromium/content/utility/utility_thread_impl.cc
+++ b/chromium/content/utility/utility_thread_impl.cc
@@ -18,6 +18,7 @@
#include "content/utility/utility_blink_platform_impl.h"
#include "content/utility/utility_process_control_impl.h"
#include "ipc/ipc_sync_channel.h"
+#include "services/shell/public/cpp/interface_registry.h"
#include "third_party/WebKit/public/web/WebKit.h"
#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
@@ -46,6 +47,7 @@ UtilityThreadImpl::UtilityThreadImpl()
UtilityThreadImpl::UtilityThreadImpl(const InProcessChildThreadParams& params)
: ChildThreadImpl(ChildThreadImpl::Options::Builder()
.InBrowserProcess(params)
+ .UseMojoChannel(true)
.Build()) {
Init();
}
@@ -94,10 +96,11 @@ void UtilityThreadImpl::Init() {
GetContentClient()->utility()->UtilityThreadStarted();
process_control_.reset(new UtilityProcessControlImpl);
- service_registry()->AddService(base::Bind(
+ GetInterfaceRegistry()->AddInterface(base::Bind(
&UtilityThreadImpl::BindProcessControlRequest, base::Unretained(this)));
- GetContentClient()->utility()->RegisterMojoServices(service_registry());
+ GetContentClient()->utility()->ExposeInterfacesToBrowser(
+ GetInterfaceRegistry());
}
bool UtilityThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
diff --git a/chromium/content/zygote/zygote_main_linux.cc b/chromium/content/zygote/zygote_main_linux.cc
index 8620eb98d11..60e88406939 100644
--- a/chromium/content/zygote/zygote_main_linux.cc
+++ b/chromium/content/zygote/zygote_main_linux.cc
@@ -64,7 +64,7 @@
#endif
#if defined(ENABLE_WEBRTC)
-#include "third_party/libjingle/overrides/init_webrtc.h"
+#include "third_party/webrtc_overrides/init_webrtc.h"
#endif
#if defined(SANITIZER_COVERAGE)
@@ -329,7 +329,6 @@ static void ZygotePreSandboxInit() {
base::RandUint64();
base::SysInfo::AmountOfPhysicalMemory();
- base::SysInfo::MaxSharedMemorySize();
base::SysInfo::NumberOfProcessors();
// ICU DateFormat class (used in base/time_format.cc) needs to get the